add formal verif
authorcompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Wed, 15 Oct 2008 14:14:27 +0000 (14:14 +0000)
committercompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Wed, 15 Oct 2008 14:14:27 +0000 (14:14 +0000)
git-svn-id: http://ltt.polymtl.ca/svn@3108 04897980-b3bd-0310-b5e0-8ef037075253

100 files changed:
trunk/verif/Spin/Doc/Book.Ch6.add [new file with mode: 0755]
trunk/verif/Spin/Doc/Book.Errata [new file with mode: 0755]
trunk/verif/Spin/Doc/Book.answers [new file with mode: 0755]
trunk/verif/Spin/Doc/Book.samples [new file with mode: 0755]
trunk/verif/Spin/Doc/Book2003Errata.html [new file with mode: 0755]
trunk/verif/Spin/Doc/Book91_Ch6_add.txt [new file with mode: 0755]
trunk/verif/Spin/Doc/Book91_Errata.txt [new file with mode: 0755]
trunk/verif/Spin/Doc/Book91_answers.txt [new file with mode: 0755]
trunk/verif/Spin/Doc/Book91_samples_bundle [new file with mode: 0755]
trunk/verif/Spin/Doc/V1.Updates [new file with mode: 0755]
trunk/verif/Spin/Doc/V2.Updates [new file with mode: 0755]
trunk/verif/Spin/Doc/V3.Updates [new file with mode: 0755]
trunk/verif/Spin/Doc/V4.Updates [new file with mode: 0755]
trunk/verif/Spin/Doc/V5.Updates [new file with mode: 0755]
trunk/verif/Spin/Man/spin.1 [new file with mode: 0755]
trunk/verif/Spin/README.html [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/dstep.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/flow.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/guided.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/main.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/make_pc [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/makefile [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/mesg.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen1.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen1.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen2.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen2.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen3.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen3.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen4.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen4.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen5.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen5.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen6.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pangen6.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/pc_zpp.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/ps_msc.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/reprosrc.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/run.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/sched.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/spin [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/spin.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/spin.y [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/spinlex.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/structs.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/sym.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl_buchi.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl_cache.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl_lex.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl_main.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl_mem.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl_parse.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl_rewrt.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/tl_trans.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/vars.c [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/version.h [new file with mode: 0755]
trunk/verif/Spin/Src5.1.6/y.output [new file with mode: 0644]
trunk/verif/Spin/Src5.1.6/y.tab.h [new file with mode: 0644]
trunk/verif/Spin/Test/README.tests [new file with mode: 0755]
trunk/verif/Spin/Test/abp [new file with mode: 0755]
trunk/verif/Spin/Test/erathostenes [new file with mode: 0755]
trunk/verif/Spin/Test/eratosthenes [new file with mode: 0755]
trunk/verif/Spin/Test/examples [new file with mode: 0755]
trunk/verif/Spin/Test/hello [new file with mode: 0755]
trunk/verif/Spin/Test/leader [new file with mode: 0755]
trunk/verif/Spin/Test/leader.ltl [new file with mode: 0755]
trunk/verif/Spin/Test/leader2 [new file with mode: 0755]
trunk/verif/Spin/Test/leader_trace [new file with mode: 0755]
trunk/verif/Spin/Test/loops [new file with mode: 0755]
trunk/verif/Spin/Test/mobile1 [new file with mode: 0755]
trunk/verif/Spin/Test/mobile1.ltl [new file with mode: 0755]
trunk/verif/Spin/Test/mobile2 [new file with mode: 0755]
trunk/verif/Spin/Test/mobile2.ltl [new file with mode: 0755]
trunk/verif/Spin/Test/pathfinder [new file with mode: 0755]
trunk/verif/Spin/Test/peterson [new file with mode: 0755]
trunk/verif/Spin/Test/petersonN [new file with mode: 0755]
trunk/verif/Spin/Test/pftp [new file with mode: 0755]
trunk/verif/Spin/Test/priorities [new file with mode: 0755]
trunk/verif/Spin/Test/snoopy [new file with mode: 0755]
trunk/verif/Spin/Test/sort [new file with mode: 0755]
trunk/verif/Spin/Test/wordcount [new file with mode: 0755]
trunk/verif/Spin/Xspin5.1/xspin510.tcl [new file with mode: 0755]
trunk/verif/examples/buffer.spin [new file with mode: 0644]
trunk/verif/examples/buffer.spin.bkp1 [new file with mode: 0644]
trunk/verif/examples/buffer.spin.bkp2 [new file with mode: 0644]
trunk/verif/examples/buffer.spin.missing_retrieve_count [new file with mode: 0644]
trunk/verif/examples/buffer.spin.trail [new file with mode: 0644]
trunk/verif/examples/pan [new file with mode: 0755]
trunk/verif/examples/pan.b [new file with mode: 0644]
trunk/verif/examples/pan.c [new file with mode: 0644]
trunk/verif/examples/pan.h [new file with mode: 0644]
trunk/verif/examples/pan.m [new file with mode: 0644]
trunk/verif/examples/pan.t [new file with mode: 0644]
trunk/verif/examples/run [new file with mode: 0755]
trunk/verif/examples/run2 [new file with mode: 0755]
trunk/verif/examples/run3 [new file with mode: 0755]
trunk/verif/examples/spin-increment.spin [new file with mode: 0644]
trunk/verif/examples/spin-increment.spin.trail [new file with mode: 0644]
trunk/verif/spin516.tar.gz [new file with mode: 0644]

diff --git a/trunk/verif/Spin/Doc/Book.Ch6.add b/trunk/verif/Spin/Doc/Book.Ch6.add
new file mode 100755 (executable)
index 0000000..4dbf164
--- /dev/null
@@ -0,0 +1,183 @@
+An appendix to Chapter 6 of the book: some extra explanation on pid's
+and on temporal claims.  Updated for Spin Version 2.0 - January 1995.
+
+PROCESS IDs
+
+In Spin 2.0 and later the never claim can refer to the control state
+of any process, but not to their local variables.
+This functionality is meant to be used for building correctness assertions
+with never claims.  It should never be used for anything else.
+An example is
+       Receiver[pid]@place
+where `place' the name of a label within `proctype Receiver,' and
+`pid' is the value returned by the run statement that instantiated the
+copy of the Receiver proctype that we are interested in.
+
+There is a misleading suggestion in the book that says that you can
+usually guess the `pid's.  Wiser is to always use the explicit value
+returned by the `run()' statement that instantiated the proces.
+Processes started with the `active' prefix obtain instantiation
+numbers starting at value 1, in the order in which they appear in the
+specification.  Each process also has a local variable _pid that
+holds its own instantiation number.
+
+SPECIFYING TEMPORAL CLAIMS
+
+The body of a temporal claim is defined just like PROMELA proctype bodies.
+This means that all control flow structures, such as if-fi selections,
+do-od repetitions, and goto jumps, are allowed.
+There is, however, one important difference:
+
+       Every statement inside a temporal claim is (interpreted as) a condition.
+       A never claim should therefore never contain statements that can
+       have side-effects (assignments, communications, run-statements, etc.)
+
+Temporal claims are used to express behaviors that are considered undesirable
+or illegal.  We say that a temporal claim is `matched' if the undesirable
+behavior can be realized, and thus the claim violated.
+
+The recommended use of a temporal claim is in combination with acceptance labels.
+There are two ways to `match' a temporal claim, depending on whether the
+undesirable behavior defines a terminating or a cyclic execution sequence.
+
+o A temporal claim is matched when it terminates (reaches its closing curly brace).
+  That is, the claim can be violated if the closing curly brace of the PROMELA
+  body of the claim is reachable for at least one execution sequence.
+
+o For a cyclic execution sequence, the claim is matched only when an explicit
+  acceptance cycle exists.  The acceptance labels within temporal claims
+  are user defined, there are no defaults.  This means that in the absence of
+  acceptance labels no cyclic behavior can be matched by a temporal claim.
+  It also means that to check a cyclic temporal claim, acceptance labels should
+  only occur within the claim and not elsewhere in the PROMELA code.
+
+
+SEMANTICS
+
+The normal system behavior of a PROMELA system is defined as the
+`asynchronous product' of the behaviors of the individual processes.
+Given an arbitrary system state, its successor states are obtained
+in two steps.  In the first step all the executable (atomic) statements in the
+individual processes are identified.  In the second step, each one of these
+statements is executed.
+Each single execution produces a successor state in the asynchronous product.
+The complete system behavior is thus defined recursively and
+represents all possible interleavings of the individual process behaviors.
+Call this asynchronous product machine the `global machine'.
+
+The addition of a temporal claim defines an additional `synchronous product'
+of this global machine with the state machine that defines the temporal
+claim.  Call the latter machine the `claim machine', and call the new
+synchronous product the `labeled machine'.
+
+Every state in the labeled machine is a pair (p,q) with p a state in the global
+machine and q a state in the claim machine.  Every transition in the labeled
+machine is similarly defined by a pair (r,s) with r a transition in the global
+machine and s a transition in the claim machine.
+In other words, every transition in the `synchronous' product is a joint move
+of the global machine and the claim machine.
+(By contrast, every transition in an `asynchronous' product would correspond
+to a single transition in either the global machine or the claim machine, thus
+interleaving transitions instead of combining them.)
+
+Since all statements in the claim machine are boolean propositions, the second
+half of the transition pair (r,s) is either true or false.
+Call all transitions where this proposition is true `matching transitions'.
+In a matching transition proposition s evaluates to true in state system state r.
+Notice that the claim machine has at least one stop state E, the state
+at the closing curly brace of the claim body.
+
+The semantics of temporal claims can now be summed up as follows.
+
+o If the labeled machine contains any sequence of matching transitions only,
+  that connects its initial state with a state (p,E) for any p, the temporal
+  claim can be matched by a terminating sequence (a correctness violation).
+
+o If the labeled machine contains any cycle of matching transitions only, that
+  passes through an acceptance state, the temporal claim can be matched by a
+  cyclic sequence.
+
+
+EXAMPLES
+
+Listed below are the equivalent PROMELA definitions for the three basic
+temporal properties defined by Zohar Manna & Amir Pnueli in
+``Tools and Rules for the Practicing Verifier'' Stanford University,
+Report STAN-CS-90-1321, July 1990, 34 pgs.
+
+The following descriptions are quoted from Manna & Pnueli:
+
+       ``There are three classes of properties we [...] believe to cover
+       the majority of properties one would ever wish to verify.''
+
+       1. Invariance
+       ``An invariance property refers to an assertion p, and requires that p
+       is an invariant over all the computations of a program P, i.e. all
+       the states arising in a computation of P satisfy p.  In temporal
+       logic notation, such properties are expressed by [] p, for a state
+       formula p.''
+
+       Corresponding Temporal Claim in PROMELA:
+       never {
+               do
+               :: p
+               :: !p -> break
+               od
+       }
+
+       2. Response
+       ``A response property refers to two assertions p and q, and
+       requires that every p-state (a state satisfying p) arising in
+       a computation is eventually followed by a q-state.
+       In temporal logic notation this is written as p -> <> q.''
+
+       Corresponding Temporal Claim in PROMELA:
+       never {
+               do
+               :: true
+               :: p && !q -> break
+               od;
+       accept:
+               do
+               :: !q
+               od
+       }
+
+       Note that using (!p || q) instead of `skip' would check only the
+       first occurrence of p becoming true while q is false.
+       The above formalization checks for all occurrences, also future ones.
+       Strictly seen, therefore, the claim above uses a common interpretation
+       of the formula, requiring it to hold always, or: [] { p -> <> q }
+
+       3. Precedence
+       ``A simple precedence property refers to three assertions p, q, and r.
+       It requires that any p-state initiates a q-interval (i.e. an interval
+       all of whose states satisfy q) which, either runs to the end of the
+       computation, or is terminated by an r-state.
+       Such a property is useful to express the restriction that, following
+       a certain condition, one future event will always be preceded by
+       another future event.
+       For example, it may express the property that, from the time a certain
+       input has arrived, there will be an output before the next input.
+       Note that this does not guarantee [require] that the output will actually
+       be produced. It only guarantees [requires] that the next input (if any)
+       will be preceded by an output.  In temporal logic, this property is
+       expressed by p -> (q U r), using the unless operator (weak until) U.
+
+       Corresponding Temporal Claim in PROMELA:
+
+       never {
+               do
+               :: skip         /* to match any occurrence */
+               :: p &&  q && !r -> break
+               :: p && !q && !r -> goto error
+               od;
+               do
+               ::  q && !r
+               :: !q && !r -> break
+               od;
+       error:  skip
+       }
+
+       Strictly again, this encodes: [] { p -> (q U r) }
+       To match just the first occurence, replace skip with (!p || r).
diff --git a/trunk/verif/Spin/Doc/Book.Errata b/trunk/verif/Spin/Doc/Book.Errata
new file mode 100755 (executable)
index 0000000..e3df18d
--- /dev/null
@@ -0,0 +1,444 @@
+Errata for `Design and Validation of Computer Protocols'
+[trivial typos not listed]
+
+CHAPTER 2, page 26 - Example of a Shorter Error Scenario
+============================================================
+
+A duplicate message can be accepted after even a single
+transmission error occurs.  E.g.:
+
+          (A)                                (B)
+           ~                                  ~
+           |                                  |
+           |    ack 'z' /-----------<---------+
+           +-----------/                      |
+accept(z)  |                                  |
+           +-----------\ ack 'a' -> err       |
+           |             \----------->--------+
+           |                                  |
+           |     nak 'z' /-----------<--------+
+           +------------/                     |
+accept(z)  |                                  |
+
+
+CHAPTER 3, page 61/62 - Revised CRC-Algorithm
+(Bits renumbered in more standard right to left order.)
+============================================================
+
+The  following  C  program,  by Don Mitchell  of  AT&T  Bell
+Laboratories,  generates a  lookup table  for  an  arbitrary
+checksum polynomial.  Input  for  the  routine  is  an octal
+number, specified as an argument, that encodes the generator
+polynomial.
+In the version of the program shown here, compliments of Ned
+W.  Rhodes,  Software  Systems Group, bits are numbered from
+zero to r-1, with bit zero corresponding to  the  right-most
+bit,  and  r  the  degree  of the generator polynomial.  (In
+Mitchell's original algorithm the bits in  the  message  and
+generator polynomial were reversed.)  The r-th bit itself is
+omitted from the code word, since  it  is  implicit  in  the
+length.   Using  this  program  takes  two  separate  steps.
+First, the program is  compiled  and  run  to  generate  the
+lookup  tables.  Then the checksum generation routine can be
+compiled, with the precalculated lookup tables in place.  On
+a UNIX system, the program is compiled as
+
+            $ cc -o crc_init crc_init.c
+
+Lookup tables for the two most popular  CRC-polynomials  can
+now be produced as follows:
+
+            $ crc_init 0100005 > crc_16.h
+            $ crc_init  010041 > crc_ccitt.h
+
+This is the text of crc_init.c:
+
+
+    main(argc, argv)
+            int argc; char *argv[];
+    {
+            unsigned long crc, poly;
+            int n, i;
+
+            sscanf(argv[1], "%lo", &poly);
+            if (poly & 0xffff0000)
+            {       fprintf(stderr, "polynomial is too large\n");
+                    exit(1);
+            }
+
+            printf("/*\n *  CRC 0%o\n */\n", poly);
+            printf("static unsigned short crc_table[256] = {\n");
+            for (n = 0; n < 256; n++)
+            {       if (n % 8 == 0) printf("    ");
+                    crc = n << 8;
+                    for (i = 0; i < 8; i++)
+                    {       if (crc & 0x8000)
+                                    crc = (crc << 1) ^ poly;
+                            else
+                                    crc <<= 1;
+                            crc &= 0xFFFF;
+                    }
+                    if (n == 255) printf("0x%04X ", crc);
+                    else          printf("0x%04X, ", crc);
+                    if (n % 8 == 7) printf("\n");
+            }
+            exit(0);
+    }
+
+The table can now be used to generate checksums:
+
+    unsigned short
+    cksum(s, n)
+            register unsigned char *s;
+            register int n;
+    {
+            register unsigned short crc=0;
+
+            while (n-- > 0)
+               crc = crc_table[(crc>>8 ^ *s++) & 0xff] ^ (crc<<8);
+
+            return crc;
+    }
+
+
+CHAPTER 4, page 81 - Typo
+============================================================
+
+old<   Taking the modulo M effect into account, this becomes:
+       valid(m) = ( 0 < p - m <= W ) || ( 0 < p - M - m <= W )
+
+new>   Taking the modulo M effect into account (p is always
+       smaller than M), this becomes:
+       valid(m) = ( 0 < p - m <= W ) || ( 0 < p + M - m <= W )
+
+ERROR, Page 83, Figure 4.14
+===========================
+
+should not "accept:i" if (a==e) is false
+
+
+CHAPTER 5, error/typos
+===========================
+
+Page 96, bottom
+
+The mutual exclusion algorithm attributed to Dekker is
+really a simplication of Dekker's algorithm that is known
+as Peterson's algorithm.
+Dekker's original solution is modeled in Promela like this:
+
+#define true   1
+#define false  0
+#define Aturn  1
+#define Bturn  0
+
+bool x, y, t;
+
+proctype A()
+{
+       do
+       :: x = true;
+               if
+               :: y == true && t == Bturn ->
+                       x = false;
+                       (t == Aturn)
+               :: y == false ->
+                       break
+               fi
+       od;
+
+       /* critical section */
+
+       t = Bturn;
+       x = false
+}
+
+proctype B()
+{
+       do
+       :: y = true;
+               if
+               :: x == true && t == Aturn ->
+                       y = false;
+                       (t == Bturn)
+               :: x == false ->
+                       break
+               fi
+       od;
+
+       /* critical section */
+
+       t = Aturn;
+       y = false
+}
+
+init { run A(); run B() }
+
+===========================
+
+Page 98, last paragraph
+
+old>   "If the receive operation tries to retrieve more parameters
+        than are available, the value of the extra parameters is undefined;
+        if it receives fewer than the number of parameters that was sent,
+        the extra information is lost."
+new>   "It is always an error if the receive operation tries to retrieve
+        a different number of parameters than the corresponding channel
+        declaration specifies."
+
+===========================
+
+Page 99, last line of "init", middle of page:
+
+old<   qname!qforb
+
+new>   qname[0]!qforb
+
+Page 100, delete last line on page:
+
+old<   byte name;      /* delete */
+
+Page 103, in the Dijkstra example:
+
+old<   chan sema = [0] of { bit };
+
+new>   chan sema = [0] of { mtype };
+
+Page 108, "init" section, top of page:
+
+old<   chan Ain  = [2] of { byte };
+       chan Bin  = [2] of { byte };
+       chan Aout = [2] of { byte };
+       chan Bout = [2] of { byte };
+
+new>   chan Ain  = [2] of { byte, byte };
+       chan Bin  = [2] of { byte, byte };
+       chan Aout = [2] of { byte, byte };
+       chan Bout = [2] of { byte, byte };
+
+===========================
+
+Page 107, last sentence of first paragraph Section 5.12:
+
+old<   discussed in Section 2.4.
+new>   discussed in Section 2.3.
+
+===========================
+
+Page 110, exercise 5-3:
+
+old<   Revise the two programs from Section 5.6
+new>   Revise the two programs from Section 5.8
+
+
+CHAPTER 6
+
+
+TYPO, page 117
+=======================
+old< chan sema[0] of {bit};
+new> chan sema = [0] of {bit};
+
+SERIOUS OMISSION, Section 6.4, page 116-117:
+=================================================
+The treatment of formalizing system invariants in a 1-statement
+monitor process is correct only if the model does not contain
+any timeout statements.
+If it does, the statements in the model that would be executed
+after a timeout expires are not checked (since assert is always
+executable, it would always be executed before the timeout expires
+under default timeout heuristics used in spin).
+there are two possible solutions:
+
+- disable the default timeout heuristics for a fully exhaustive
+  search for all possible choices of timeouts (brute force)
+  to do this, include a single line
+       #define timeout skip
+  as the first line of your model - and nothing else has to change
+
+- use a safer formalization of the system invariant, using a never claim.
+  the simples formalization is:
+       never { do :: assert(invariant) od }
+  which checks the truth of the invariant for every reachable state,
+  independent of timeouts.
+  another way would be to use the implicit matching behavior of a never
+  claim, without an explicit assertion:
+       never
+       {       do
+               ::  (invariant) /* things are fine, the invariant holds */
+               :: !(invariant) -> break        /* invariant fails - match */
+               od
+       }
+
+CLARIFICATION, page 118, Section 6.5
+====================================
+The validator SPIN does not enforce the second criterion
+for a proper endstate, i.e., the emptiness of all channels.
+It does enforce the revised first criterion from the bottom
+of page 118.
+
+TYPO, page 121 middle:
+=================================================
+
+old< never { do :: skip od -> P -> !Q }
+
+new> never { do :: skip :: break od -> P -> !Q }
+
+ADDED EXPLANATIONS (throughout page 121 and onw.):
+=================================================
+
+A terminating claim is matched, and the corresponding correctness
+property thereby violated, if and when the claim body terminates.
+
+A non-terminating claim is matched, and the corresponding
+correctness property violated, if and when an acceptance cycle
+is detected.
+
+SPECIFYING TEMPORAL CLAIMS
+
+The body of a temporal claim is defined just like  PROMELA
+proctype  bodies.   This  means that all control flow struc-
+tures, such as  if-fi selections,  do-od repetitions,  and
+goto  jumps,  are allowed.  There is, however, one important
+difference:
+
+  Every statement inside a temporal claim is  (interpreted
+  as) a boolean condition.
+
+Specifically, this means that the statements inside temporal
+claims  should  be free of side-effects.  For reference, the
+PROMELA  statements  with  side-effects  are:   assignments,
+assertions,   sends,   receives,  and    printf  statements.
+
+Temporal  claims  are  used  to  express  system
+behaviors  that  are  considered undesirable or illegal.  We
+say that a temporal claim  is  matched  if  the  undesirable
+behavior can be realized, and thus our correctness claim can
+be violated.  The most useful application of temporal claims
+is  in  combination  with acceptance labels.  There are then
+two ways to match a temporal claim, depending on whether the
+undesirable behavior defines terminating or cyclic execution
+sequences.
+
+     For a terminating execution sequence, a temporal  claim
+     is  matched  only  when  it  can terminate (reaches the
+     closing curly brace) That is, the claim can be violated
+     if  the  closing curly brace of the PROMELA body of the
+     claim is reachable.
+
+     For a cyclic execution sequence, the claim  is  matched
+     only  when  an  explicit  acceptance cycle exists.  The
+     acceptance  labels  within  temporal  claims  are  user
+     defined, there are no defaults.  This means that in the
+     absence of acceptance labels no cyclic behavior can  be
+     matched  by  a  temporal  claim.  It also means that to
+     check a cyclic temporal claim, acceptance labels should
+     only  occur  within  the claim and not elsewhere in the
+     PROMELA code.
+
+ERROR, page 124, top
+=======================
+old<   :: len(receiver) == 0
+
+new>   :: skip /* allow any time delay */
+
+ERROR, page 125, top
+=======================
+the claim can of course always be violated (== matched),
+whether timeout is redefined or not.
+
+CHAPTER 7
+
+ERROR, page 139, bottom
+=======================
+old< Pr(Burst >= 17) = 0.08  . e ^ { -0.08  . 17 } = 0.007
+
+new> Pr(Burst >= 17) = 0.009 . e ^ { -0.009 . 17 } = 0.007
+
+ERROR, page 156, middle
+=======================
+old<                   flow_to_dll[n]!sync_ack,0
+new>                   flow_to_dll[n]!sync_ack,m
+                       (and move the new line up to precede: "m=0;")
+
+old<                   flow_to_ses[n]!sync_ack,0
+new>                   flow_to_ses[n]!sync_ack,m
+
+old<   To avoid circularity, the synchronization messages
+       do not carry sequence numbers.
+new>   The sync_ack message echos the session number of the
+       sync message.
+
+ERROR, page 156, bottom
+=======================
+old<                   ||   (0<p-m-M && p-m-M<=W));
+new>                   ||   (0<p-m+M && p-m+M<=W));
+
+
+CHAPTER 11
+
+ERROR, page 224, algorithm "analyze()"
+======================================
+old<   q = element from W;
+new>   q = last element from W;
+
+further down:
+=============
+old<   If states are stored in set W in first-in first-out order,
+       the algorithm performs a breadth-first search of the state space tree.
+new>   If states are stored in set W in first-in last-out (i.e., stack)
+       order, the algorithm performs a depth-first search of the state space tree.
+
+further down:
+=============
+old<   If states are stored in first-in last-out (i.e., stack)
+       < order, this changes into a depth-first search.
+
+new>   If states are stored and removed in first-in first-out
+       order, this changes into a breadth-first search
+       (element q must be deleted upon retrieval from set W in
+       this type of algorithm).
+
+Page 227, top
+=============
+old<   q = element from W;
+new>   q = last element from W;
+
+Page 237, bottom
+================
+old<   after removing states 4, 3, and 2 from the stack...
+new>   after removing states 4, and 3 from the stack...
+
+CHAPTER 13
+
+Page 315, 2nd para in 13.9
+==========================
+The first two sentences of this paragraph are incorrect.
+At the low end, just 1 state would be stored in the hash-array,
+taking up 2 bits of storage out of N available bits; at the
+high end, all N bits would be set at the end of the run, and 
+(allowing overlaps) we cannot have seen more than N states.
+This leads to a possible range of values for the hash factor
+of N/2 >= hf >= 1
+For full state space storage the hash factor is meaningless.
+
+CHAPTER 14
+
+Page 331, lines 86, 88, and 94
+==============================
+See the corrections described for CHAPTER 7, page 156.
+
+APPENDIX C
+==============================
+
+Page 387-388
+The syntax of remote referencing has changed in SPIN Version 2.0.
+Remote referencing to local variables is no longer allowed
+(page 387, 5th line from below).
+The syntax for referencing the state of another process has changed
+from (page 388, 3rd line):
+       same[2]:here
+to:
+       same[2]@here
+
+=end errata=
diff --git a/trunk/verif/Spin/Doc/Book.answers b/trunk/verif/Spin/Doc/Book.answers
new file mode 100755 (executable)
index 0000000..b70deb3
--- /dev/null
@@ -0,0 +1,612 @@
+
+
+Answers to selected exercises from
+'Design and Validation of Computer Protocols'
+=============================================
+
+1.1
+Assuming that torches in the two groups would be
+raised and lowered simultaneously,
+the code for the first character in the first group
+could have clashed with the pre-defined start of text code.
+
+If torches are not raised simultaneously it is conceivable
+that group numbers could be paired with the wrong character numbers.
+
+A well-trained transmitter might also overestimate the receiver's
+ability to translate the codes on the fly.
+as is still true today: receiving is a more time consuming task
+than transmitting.
+
+1.2
+Assuming that a torch code is displayed for a minimum of 30 seconds,
+the torch telegraph transmits a choice of 1 out of 25 (between 4
+and 5 bits of information), giving a speed of roughly 0.15 bits/sec.
+Chappe's telegraph transmitted a choice of 1 out of 128 every 15 to 20
+seconds, giving a transmission speed of roughly 0.5 bits/sec.
+On Polybius' telegraph the 15 characters of the message
+``protocol failure'' would take 15x30 seconds or 7.5 minutes to transmit...
+(Note that a code for the space was not available.)
+On Chappe's system the 16 characters (space included) would be
+transmitted in 4 minutes, assuming that no predefined code
+was assigned to either the word `protocol' or the word `failure.'
+(As far as we know, there wasn't.)
+
+1.3
+Removing the redundancy in messages increases the chance that a
+single transmission error would make a large part of a message
+inrecognizable.  It could cause a lot of extra traffic from receiver
+back to sender, asking for retransmissions, and additional transmissions
+of messages.  The same tradeoff is still valid on today's communication
+channels (see Chapter 3).
+
+1.4
+The signalman at A had to make sure that not one but two
+trains would leave the tunnel, before he admitted the third.
+The two trains could reach signalman B in approximately 2 minutes.
+At 25 symbols per minute, that would allow the two signalmen
+to exchange roughly 50 characters of text.
+A could have signaled: "two trains now in tunnel - how many left?"
+for a total of 42 characters.
+Assuming that B would have answered eventually "one train left,"
+that would still leave A puzzling if B had really understood his
+message, and if so, where the second train could possibly be.
+Considering also that signalman A had been on duty for almost
+18 hours when the accident occured, it is not entirely certain
+that he could have succesfully resolved the protocol problem.
+Note that he still would have had to `invent' part of the protocol
+for resolving the problem in real-time.
+
+1.5
+Replace the message `train in tunnel' with `increment the number of
+trains in the tunnel by one.'  Similarly, replace the message `tunnel
+is clear' by `decrement the number of trains in the tunnel by one.'
+The message `is tunnel clear' becomes `how many trains are in the
+tunnel?' with the possible responses spelled out with numerals 0 to 9.
+Either signalman can increment or decrement the number.
+The rule of the tunnel is invariantly that the number of trains in
+the tunnel is either zero or one, and only one signalman may transmit
+at a time. (To resolve conflicts on access to the transmission line,
+one could simply give one of the signalmen a fixed priority.)
+
+1.6
+A livelock would result.  Assuming that the semaphore operators would
+quickly enough recognize the livelock, it is still an open question
+what they would (should) do to recover properly from such an occurence.
+
+1.7
+One possible scenario, observed by Jon Bentley in real life, is that
+two connections are made, and both parties are charged for the call.
+Clearly, a dream come true for the telephone companies.
+
+2.1
+Service - the simplex transfer of arbitrary messages from a designated
+sender to a designated receiver.
+
+Assumptions about the environment - sufficient visibility and small enough
+distance to make and accurate detection (and counting) of torches possible
+for both sender and receiver.  There seems to be an implicit assumption of
+an error-free channel.  There is also the implicit assumption that the
+receiver will always be able to keep up with the sender and will not get
+out of sync with the symbols that have to be decoded.
+
+Vocabulary - 24 characters from the Greek alphabet, plus two control messages
+(the start of text message and its acknowledgement).
+
+Encoding - each character, and each control message, is encoded into two
+numbers, both between 1 and 5.
+Since there are 26 distinct messages and only 5x5=25 distinct codes, some
+ambiguity is unavoidable.
+
+Procedure rules - minimal.  Apparently there was only a single handshake
+at the start of the transmission.  All other interactions (end of transmission,
+error recovery, flow control) were undefined and would have had to be
+improvised in the field.  There is also no resolution of a potential conflict
+at the start of transmission (assuming that both parties could decide to
+start sending at the same time).
+
+2.2
+The procedure rules can include a poll message once per
+complete page - interrogating the printer about it's status
+(confirming that it is online and confirming that it
+is not out of paper - both conditions that can change from
+one page to the next).  Note that the procedure rules must
+also guarantee that no more than one user can use the printer
+at a time.
+
+2.3
+Service - establishing a voice connection between two subscribers
+of a phone system. (Let's conveniently ignore multi-party connections,
+or faxes and modems.)
+
+Assumptions about environment - the phone system is infinitely
+available and error-free (sic).
+
+Vocabulary - off-hook, on-hook, dial 0 ... dial 9 (ignore star and sharp).
+Dial-tone, busy-tone, ring-tone.  All messages listed here are control
+messages - the `data' of the protocol is encoded in the voice message.
+(For completeness then we could list `voice' as a separate message in the
+vocabulary, without attempting to formalize it's `encoding.')
+
+Encoding - lifting the receiver, lowering the receiver,
+pushing one of 10 labeled buttons.
+
+Informal procedure rules -  Go off-hook, if no dial-tone is returned
+go on-hook and repeat a random amount of time later.
+If there is a dial-tone, push the sequence of buttons that identify the
+required destination to the phone system.
+If a busy-tone is returned in this interval, go on-hook, wait a random
+amount of time, and repeat from the start.
+If a ring-tone is returned - the call has been established - wait a
+random amount of time, go on-hook.
+
+Note that the random wait period after a busy signal makes it less likely
+that a `Lovers' Paradox' can be created (cf. Exercise 1.7).
+To be complete, the phone systems behavior should also be listed.
+Be warned that the latter is not a trivial exercise....
+
+2.4
+The revised version is the famous alternating bit protocol, see Chapter 4.
+
+2.5
+The receiver can then determine where a message (should) end by
+counting the number of bytes it receives, following the header.
+It does not have to scan for a pre-defined message terminator.
+
+2.6
+For isntance, a character stuffed protocol always transmits an integral
+number of bytes.  A bit stuffed protocol carries slightly less overhead.
+
+2.7
+See Bertsekas and Gallager, [1987, p. 78-79].
+
+2.8
+More detailed sample assignments for software projects such as
+this one are available from the author (email to gerard@research.att.com).
+
+3.1
+The code rate is 0.2.  Protection against bursts is limited
+to errors affecting maximally 2 out of the 5 bytes.
+At 56 Kbits/sec that means bursts smaller than 0.28 msec.
+
+3.3
+Does the crc need to be protected by a crc?
+
+3.4
+In many cases English sentences are redundant enough that
+forward error correction is possible.  Any real conversation,
+though, contains many examples of feedback error correction
+to resolve ambiguities.
+To stick with the example - if the sentence ``the dog run'' is
+received, the original version (i.e., one or more dogs) cannot be
+determined without feedback error control.
+
+3.5
+(a) - the checksum is 6 bits wide.
+(b) - the original data is equal to the first n-6 bits of the code word
+(6 bits in this case).
+(c) - there were no transmission errors other than possible multiples
+of the generator polynomial itself.
+
+3.6
+The standard example is that of the voyager space craft near
+the planet Jupiter receiving a course adjustment from earth.
+A retransmission of the message would mean hours delay and invalidate
+the original commands.
+If the return channel has a high probability of error (e.g., a low
+power transmitter on board the spacecraft, sending out a very weak
+signal back to earth), the chances that a retransmission request would
+reach the earth intact may also be unacceptably low.
+
+3.8
+It is impossible to reduce a non-zero error rate to zero.
+The probability of error can be brought arbitrarily close to zero,
+at the expense of transmission speed, but it cannot reach zero.
+The scheme suggested would violate this principle and therefore
+should be placed in the same category as perpetuum mobiles and time-travel.
+
+3.9
+Fletcher's algorithm can be classified as a systematic block code.
+
+4.2
+The alternating bit protocol does not protect against
+duplication errors or reordering errors.
+Duplication errors persist (duplicate messages do not dissapear
+but generate duplicate acks etc, for the duration of the session.)
+Reordering can cause erroneous data to be accepted.
+
+4.5
+Too short a timeout creates duplicate messages.
+The duplicates lower the throughput for the remainder of the session.
+Too long a timeout increases idle-time and lowers the
+throughput.
+
+4.6
+Ignore duplicate acks.
+
+4.8
+See Bertsekas and Gallager [1987, pp. 28-29].
+
+4.9
+In at least one case (when the receiver is one full window of
+messages behind the sender) there is a confusion case where
+the receiver cannot tell if an incoming message is a repeat
+from W messages back, or a new message.
+
+4.10
+Store the data in buffer[n%W] where W is window size.
+
+4.11
+Use time-stamps and restrict the maximum life time of
+a message.  Note however that time-stamps are just another
+flavor of sequence numbers and they would have to be selected
+from a sufficiently large window.
+For 32 bit sequence numbers one message transmission
+per micro-second would recycle the number in 71 minutes.
+For 64 bit sequence numbers, the number recycles
+at the same transmission speed in 500,000 years.
+
+4.12
+Alpha controls the rate of adaption to changes in
+network performance.
+Beta controls the allowed variance in response time.
+(It estimates the load variance of the remote host.)
+
+4.13
+Most importantly, all assumptions about the environment,
+specifically of the tranmission channel used, are missing completely.
+
+4.14
+The message could be received again and cause a duplicate acceptance.
+
+5.1
+An assignment is always executable.  The variable b would be set
+to the value 0.
+
+5.2
+If the receive is executable on the first attempt to execute
+the statement, the message would be received, and the condition
+would be false (since the `executability' value of the receive is
+non-zero).  The statement would block, and would be repeated.
+If the receive is (finally) non-executable, the receive fails,
+but the condition becomes true and executable.
+For all clarity: this is not valid Promela syntax.  In Promela
+the rule is that the evaluation of a condition must always be
+completely side-effect free.
+
+5.3
+
+/***** Factorial - without channels *****/
+
+int par[16];
+int done[16];
+int depth;
+
+proctype fact()
+{      int r, n, m;
+
+       m = depth;
+       n = par[m];
+       if
+       :: (n <= 1) -> r = 1
+       :: (n >= 2) ->
+               depth = m + 1;
+                       par[m+1] = n-1;
+                       run fact();
+                       done[m+1];
+                       r = par[m+1];
+               depth = m;
+               r = r*n
+       fi;
+       par[m] = r;
+       printf("Value: %d\n", par[m]);
+       done[m] = 1
+}
+
+init
+{      depth = 0;
+       par[0] = 12;
+       run fact();
+       done[0];
+       printf("value: %d\n", par[0])
+       /* factorial of 12: 12*11*10....*2*1 = 479001600 */
+}
+
+/***** Ackermann's function *****/
+
+short  ans[100];
+short done[100];       /* synchronization */
+
+proctype ack(short a, b, c)
+{
+       if
+       :: (a == 0) ->
+               ans[c] = b+1
+       :: (a != 0) ->
+               done[c+1] = 0;
+               if
+               :: (b == 0) ->
+                       run ack(a-1, 1, c+1)
+               :: (b != 0) ->
+                       run ack(a, b-1, c+1);
+                       done[c+1];      /* wait */
+                       done[c+1] = 0;
+                       run ack(a-1, ans[c+1], c+1)
+               fi;
+               done[c+1];      /* wait */
+               ans[c] = ans[c+1]
+       fi;
+       done[c] = 1
+}
+init
+{
+       run ack(3, 3, 0);
+       done[0];        /* wait */
+       printf("ack(3,3) = %d\n", ans[0])
+}
+
+5.10
+
+Here, as an inspiration, is another sort program, performing
+a tree-sort.
+
+/**** Tree sorter ****/
+
+mtype = { data, eof };
+
+proctype seed(chan in)
+{      byte num, nr;
+
+       do
+       :: (num < 250) -> num = num + 5
+       :: (num >   3) -> num = num - 3
+       :: in!data,num
+       :: (num > 200) -> in!eof,0 -> break
+       od
+}
+
+init {
+       chan in[1] of { byte, byte };
+       chan rgt [1] of { byte, byte };
+       byte n;
+
+       run seed(in);
+       in?data,n;
+       run node(n, rgt, in);
+       do
+       :: rgt?eof,0 -> printf("\n"); break
+       :: rgt?data,n -> printf("%d, ", n)
+       od
+       
+}
+
+proctype node(byte hold; chan up, down)
+{      chan lft [1] of { byte, byte };
+       chan rgt [1] of { byte, byte };
+       chan ret [1] of { byte, byte };
+       byte n; bit havergt, havelft;
+
+       do
+       :: down?data,n ->
+               if
+               :: (n >  hold) ->
+                       if
+                       :: ( havelft) -> lft!data,n
+                       :: (!havelft) -> havelft=1;
+                               run node(n, ret, lft)
+                       fi
+               :: (n <= hold) ->
+                       if
+                       :: ( havergt) -> rgt!data,n
+                       :: (!havergt) -> havergt=1;
+                               run node(n, ret, rgt)
+                       fi
+               fi
+       :: down?eof,0 -> break
+       od;
+       if
+       :: (!havergt) -> skip
+       :: ( havergt) -> rgt!eof,0;
+               do
+               :: ret?data,n -> up!data,n
+               :: ret?eof,0 -> break
+               od
+       fi;
+       up!data,hold;
+       if
+       :: (!havelft) -> skip
+       :: ( havelft) -> lft!eof,0;
+               do
+               :: ret?data,n -> up!data,n
+               :: ret?eof,0 -> break
+               od
+       fi;
+       up!eof,0
+}
+
+5.13
+Promela is a validation modeling language, not an implementation language.
+Why does a civil engineer not use steel beams in wooden bridge models?
+
+6.1
+The assertion can be placed inside the critical section.
+The simplest way is as follows (rewritten with some features
+from the more recent versions of Spin):
+
+       mtype = { p, v }
+       
+       chan sema[0] of { mtype };
+       byte cnt;
+       
+       active proctype dijkstra()      /* 1 semaphore process */
+       {       do
+               :: sema!p -> sema?v
+               od
+       }
+       active [3] proctype user()      /* 3 user processes */
+       {
+               sema?p;
+               cnt++;
+               assert (cnt == 0 || cnt == 1);  /* critical section */
+               cnt--;
+               sem!v
+               skip   /* non-critical section */
+       }
+
+6.2
+To check the truth of the invariant
+for every reachable state, one can write simply:
+
+       never { do :: assert(invariant) od }
+
+Or to match an invalid behavior by reaching the
+end of the never claim, without assertions:
+
+       never
+       {       do
+               ::  (invariant) /* things are fine, the invariant holds */
+               :: !(invariant) -> break        /* invariant fails - match */
+               od
+       }
+
+Note that semi-colons (or arrows) in never claims match system transitions,
+(i.e., each transition in the system must be matched by a move in the
+never claim;  the claim does not move independently).
+
+6.5
+Using accept labels, for instance:
+
+       proctype A()
+       {       do
+               :: x = true;
+                       t = Bturn;
+                       (y == false || t == Aturn);
+                       ain = true;
+       CS:             skip;   /* the critical section */
+                       ain = false;
+                       x = false
+               od
+       }
+       ... and simularly for proctype B()
+
+       never {
+               do
+               :: skip         /* allow arbitrary initial execution */
+               :: !A[1]@CS -> goto accept1
+               :: !B[2]@CS -> goto accept2
+               od;
+       accept1:
+               do :: !A[1]@CS od       /* process 1 denied access forever */
+       accept2:
+               do :: !B[2]@CS od       /* process 2 denied access forever */
+       }
+
+
+6.6.a
+       never {
+               do
+               :: skip /* after an arbitrary number of steps */
+               :: p -> break
+               od;
+       accept:
+               do
+               :: p    /* can only match if p remains true forever */
+               od
+       }
+
+6.6.b
+For instance:
+       never {
+               do
+               :: assert(q || p)       /* "!q implies p" */
+               od
+       }
+
+6.6.c
+       never {    /* <> (p U q) */
+               do
+               :: skip /* after an arbitrary number of steps */
+               :: p -> break   /* eventually */
+               od;
+               do
+               :: p            /* p remains true */
+               :: q -> break   /* at least until q becomes true */
+               od
+               /* invalid behavior is matched if we get here */
+       }
+
+The translation has been automated, and is standard in Spin version 2.7
+and later (Spin option -f).
+
+6.7
+A research problem -- there are no easy answers.
+
+6.8
+       assert(0)
+is an immediate violation in both finite or infinite execution sequences,
+and is a safety property.
+
+       accept: do :: skip od
+
+is only a violation for an infinite execution sequence, and is a liveness
+property (i.e., requires a nested depth-first search for acceptance
+cycles). The safety property can be proven more effieciently.
+Other than this, the two properties are equivalent;
+
+7.1
+Layers 3 to 5 and layer 7.
+
+7.2
+At the sender: first checksumming, then byte stuffing and framing.
+At the receiver: first unstuffing and de-framing, then checksum
+verification.
+
+7.3
+Rate control is placed at the layer that handles the units it
+refers too (for bit rates, it is the physical layer - for packets
+it would be the layer that produces packets, etc.).
+Dynamic flow control belongs in the flow control module.
+
+7.13
+The one-bit solution will no longer work.
+
+8.1
+The dash is used as a don't care symbol - any valid symbol
+could replace it without changing the validity of the specification.
+The epsilon is a null-element, i.e. it represents the absence
+of a symbol (the empty set).
+
+8.7
+No, the run and chan operators are defined to be unexecutable
+when an (implementation dependent) bound is reached.
+
+9.2
+No.
+
+9.5
+More states, up to a predefined bound only.  Fewer states, yes.
+
+9.6
+No, the IUT could be arbitrarily large.
+
+9.8
+It can no longer detect transfer errors.
+
+10.2
+The computational complexity will make an interactive
+solution impossible for all but the simplest
+applications.
+
+11.3
+Missing from the program text is that variable j is
+initialized to 1 minus the value of i.
+
+12.1
+Note that the number of states to be searched by a validator on
+such a protocol would multiply by the range of the time count...
+
+13.1
+If done right, the changes will be minimal (say 10 to 20 lines
+of source).
+The memory requirements will very quickly make validations
+effectively impossible.
diff --git a/trunk/verif/Spin/Doc/Book.samples b/trunk/verif/Spin/Doc/Book.samples
new file mode 100755 (executable)
index 0000000..43b4f6d
--- /dev/null
@@ -0,0 +1,1769 @@
+# To unbundle, sh this file
+echo README 1>&2
+sed 's/.//' >README <<'//GO.SYSIN DD README'
+-Readme
+-------
+-The files in this set contain the text of examples
+-used in the Design and\16 Validation of Computer
+-Protocols book.  The name of each file corresponds to the
+-page number in the book where the example appears in its
+-most useful version.  The overview below gives a short
+-descriptive phrase for each file.
+-
+-Description           Page Nr = Filename
+------------             ------------------
+-hello world   =       p95.1
+-tiny examples =       p94 p95.2 p96.1 p97.1 p97.2 p101 p102 p104.1
+-useful demos  =       p99 p104.2 p105.2 p116 p248
+-mutual excl.  =       p96.2 p105.1 p117 p320
+-Lynch's prot. =       p107 p312
+-alternatin bit        =       p123
+-chappe's prot.        =       p319
+-
+-Large runs
+-----------
+-ackerman's fct        =       p108    # read info at start of the file
+-
+-Pftp Protocol
+--------------
+-upper tester  =       p325.test       # not runnable
+-flow control l.       =       p329 p330
+-session layer =       p337.pftp.ses p342.pftp.ses1 p347.pftp.ses5
+-all pftp      =       App.F.pftp - plus 8 include files
+-
+-See also the single file version of pftp in: Test/pftp
+-
+-General
+--------
+-Use these examples for inspiration, and to get quickly
+-acquainted with the language and the Spin software.
+-All examples - except p123 - can be used with both version
+-1 and version 2 of SPIN. (p123 was modifed for versoin 2.0
+-to use the new syntax for remote referencing).
+-If you repeat the runs that are listed in the book for
+-these examples, you should expect to get roughly the same
+-numbers in the result - although in some cases there may
+-be small differences that are due to changes in bookkeeping.
+-
+-For instance, for p329, the book (Spin V1.0) says
+-on pg. 332, using a BITSTATE run, that there are:
+-      90845 + 317134 + 182425 states (stored + linked + matched)
+-Spin V2.0 reports the numbers:
+-      90837 + 317122 + 182421 states (stored + atomic + matched)
+-and when compiled for partial order reduction (-DREDUCE):
+-      74016 + 203616 + 104008 states (stored + atomic + matched)
+-
+-If you repeat a BITSTATE run, of course, by the nature of the
+-machine dependent effect of hashing, you may get different
+-coverage and hash-factors for larger runs.  The implementation
+-of the hash functions has also been improved in version 2.0,
+-so the numbers you see will likely differ. The numbers, though,
+-should still be in the same range as those reported in the book.
+-
+-The last set of file (prefixed App.F) is included for completeness.
+-As explained in the book: don't expect to be able to do an
+-exhaustive verification for this specification as listed.
+-In chapter 14 it is illustrated how the spec can be broken up
+-into smaller portions that are more easily verified.
+-
+-Some Small Experiments
+------------------------
+-Try:
+-      spin p95.1              # small simulation run
+-
+-      spin -s p108            # bigger simulation run, track send stmnts
+-
+-      spin -a p312            # lynch's protocol - generate verifier
+-      cc -o pan pan.c         # compile it for exhaustive verification
+-      pan                     # prove correctness of assertions etc.
+-      spin -t -r -s p312      # display the error trace
+-
+-now edit p312 to change all three channel declarations in init
+-to look like: ``chan AtoB = [1] of { mtype byte }''
+-and repeat the above four steps.
+-note the improvement in the trace.
+-
+-      spin -a p123            # alternating bit protocol - generate verifier
+-      cc -o pan pan.c         # compile it for exhaustive verification
+-      pan -a                  # check violations of the never claim
+-      spin -t -r -s p123      # display the error trace
+-
+-for more intuitive use of all the above options: try using the
+-graphical interface xspin, and repeat the experiments.
+//GO.SYSIN DD README
+echo App.F.datalink 1>&2
+sed 's/.//' >App.F.datalink <<'//GO.SYSIN DD App.F.datalink'
+-/*
+- * Datalink Layer Validation Model
+- */
+-
+-proctype data_link()
+-{     byte type, seq;
+-
+-end:    do
+-      :: flow_to_dll[0]?type,seq ->
+-              if
+-              :: dll_to_flow[1]!type,seq
+-              :: skip /* lose message */
+-              fi
+-      :: flow_to_dll[1]?type,seq ->
+-              if
+-              :: dll_to_flow[0]!type,seq
+-              :: skip /* lose message */
+-              fi
+-      od
+-}
+//GO.SYSIN DD App.F.datalink
+echo App.F.defines 1>&2
+sed 's/.//' >App.F.defines <<'//GO.SYSIN DD App.F.defines'
+-/*
+- * Global Definitions
+- */
+-
+-#define LOSS          0       /* message loss   */
+-#define DUPS          0       /* duplicate msgs */
+-#define QSZ           2       /* queue size     */
+-
+-mtype = {
+-      red, white, blue,
+-      abort, accept, ack, sync_ack, close, connect,
+-      create, data, eof, open, reject, sync, transfer,
+-      FATAL, NON_FATAL, COMPLETE
+-      }
+-
+-chan use_to_pres[2] = [QSZ] of { byte };
+-chan pres_to_use[2] = [QSZ] of { byte };
+-chan pres_to_ses[2] = [QSZ] of { byte };
+-chan ses_to_pres[2] = [QSZ] of { byte, byte };
+-chan ses_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_ses[2] = [QSZ] of { byte, byte };
+-chan dll_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_dll[2] = [QSZ] of { byte, byte };
+-chan ses_to_fsrv[2] = [0] of { byte };
+-chan fsrv_to_ses[2] = [0] of { byte };
+//GO.SYSIN DD App.F.defines
+echo App.F.flow_cl 1>&2
+sed 's/.//' >App.F.flow_cl <<'//GO.SYSIN DD App.F.flow_cl'
+-/*
+- * Flow Control Layer Validation Model
+- */
+-
+-#define true  1
+-#define false 0
+-
+-#define M     4       /* range sequence numbers   */
+-#define W     2       /* window size: M/2         */
+-
+-proctype fc(bit n)
+-{     bool    busy[M];        /* outstanding messages    */
+-      byte    q;              /* seq# oldest unacked msg */
+-      byte    m;              /* seq# last msg received  */
+-      byte    s;              /* seq# next msg to send   */
+-      byte    window;         /* nr of outstanding msgs  */
+-      byte    type;           /* msg type                */
+-      bit     received[M];    /* receiver housekeeping   */
+-      bit     x;              /* scratch variable        */
+-      byte    p;              /* seq# of last msg acked  */
+-      byte    I_buf[M], O_buf[M];     /* message buffers */
+-
+-      /* sender part */
+-end:  do
+-      :: atomic {
+-         (window < W  && len(ses_to_flow[n]) >  0
+-                      && len(flow_to_dll[n]) < QSZ) ->
+-                      ses_to_flow[n]?type,x;
+-                      window = window + 1;
+-                      busy[s] = true;
+-                      O_buf[s] = type;
+-                      flow_to_dll[n]!type,s;
+-                      if
+-                      :: (type != sync) ->
+-                              s = (s+1)%M
+-                      :: (type == sync) ->
+-                              window = 0;
+-                              s = M;
+-                              do
+-                              :: (s > 0) ->
+-                                      s = s-1;
+-                                      busy[s] = false
+-                              :: (s == 0) ->
+-                                      break
+-                              od
+-                      fi
+-              }
+-      :: atomic {
+-              (window > 0 && busy[q] == false) ->
+-              window = window - 1;
+-              q = (q+1)%M
+-         }
+-#if DUPS
+-      :: atomic {
+-              (len(flow_to_dll[n]) < QSZ
+-               && window > 0 && busy[q] == true) ->
+-              flow_to_dll[n]! O_buf[q],q
+-         }
+-#endif
+-      :: atomic {
+-              (timeout && len(flow_to_dll[n]) < QSZ
+-               && window > 0 && busy[q] == true) ->
+-              flow_to_dll[n]! O_buf[q],q
+-         }
+-
+-      /* receiver part */
+-#if LOSS
+-      :: dll_to_flow[n]?type,m /* lose any message */
+-#endif
+-      :: dll_to_flow[n]?type,m ->
+-              if
+-              :: atomic {
+-                      (type == ack) ->
+-                      busy[m] = false
+-                 }
+-              :: atomic {
+-                      (type == sync) ->
+-                      flow_to_dll[n]!sync_ack,m;
+-                      m = 0;
+-                      do
+-                      :: (m < M) ->
+-                              received[m] = 0;
+-                              m = m+1
+-                      :: (m == M) ->
+-                              break
+-                      od
+-                 }
+-              :: (type == sync_ack) ->
+-                      flow_to_ses[n]!sync_ack,m
+-              :: (type != ack && type != sync && type != sync_ack)->
+-                      if
+-                      :: atomic {
+-                              (received[m] == true) ->
+-                                      x = ((0<p-m   && p-m<=W)
+-                                      ||   (0<p-m+M && p-m+M<=W)) };
+-                                      if
+-                                      :: (x) -> flow_to_dll[n]!ack,m
+-                                      :: (!x) /* else skip */
+-                                      fi
+-                      :: atomic {
+-                              (received[m] == false) ->
+-                                      I_buf[m] = type;
+-                                      received[m] = true;
+-                                      received[(m-W+M)%M] = false
+-                       }
+-                      fi
+-              fi
+-      :: (received[p] == true && len(flow_to_ses[n])<QSZ
+-                              && len(flow_to_dll[n])<QSZ) ->
+-              flow_to_ses[n]!I_buf[p],0;
+-              flow_to_dll[n]!ack,p;
+-              p = (p+1)%M
+-      od
+-}
+//GO.SYSIN DD App.F.flow_cl
+echo App.F.fserver 1>&2
+sed 's/.//' >App.F.fserver <<'//GO.SYSIN DD App.F.fserver'
+-/*
+- * File Server Validation Model
+- */
+-
+-proctype fserver(bit n)
+-{
+-end:  do
+-      :: ses_to_fsrv[n]?create ->     /* incoming */
+-              if
+-              :: fsrv_to_ses[n]!reject
+-              :: fsrv_to_ses[n]!accept ->
+-                      do
+-                      :: ses_to_fsrv[n]?data
+-                      :: ses_to_fsrv[n]?eof -> break
+-                      :: ses_to_fsrv[n]?close -> break
+-                      od
+-              fi
+-      :: ses_to_fsrv[n]?open ->               /* outgoing */
+-              if
+-              :: fsrv_to_ses[n]!reject
+-              :: fsrv_to_ses[n]!accept ->
+-                      do
+-                      :: fsrv_to_ses[n]!data -> progress: skip
+-                      :: ses_to_fsrv[n]?close -> break
+-                      :: fsrv_to_ses[n]!eof -> break
+-                      od
+-              fi
+-      od
+-}
+//GO.SYSIN DD App.F.fserver
+echo App.F.pftp 1>&2
+sed 's/.//' >App.F.pftp <<'//GO.SYSIN DD App.F.pftp'
+-/*
+- * PROMELA Validation Model - startup script
+- */
+-
+-#include "App.F.defines"
+-#include "App.F.user"
+-#include "App.F.present"
+-#include "App.F.session"
+-#include "App.F.fserver"
+-#include "App.F.flow_cl"
+-#include "App.F.datalink"
+-
+-init
+-{     atomic {
+-        run userprc(0); run userprc(1);
+-        run present(0); run present(1);
+-        run session(0); run session(1);
+-        run fserver(0); run fserver(1);
+-        run fc(0);      run fc(1);
+-        run data_link()
+-      }
+-}
+//GO.SYSIN DD App.F.pftp
+echo App.F.present 1>&2
+sed 's/.//' >App.F.present <<'//GO.SYSIN DD App.F.present'
+-/*
+- * Presentation Layer Validation Model
+- */
+-
+-proctype present(bit n)
+-{     byte status, uabort;
+-
+-endIDLE:
+-      do
+-      :: use_to_pres[n]?transfer ->
+-              uabort = 0;
+-              break
+-      :: use_to_pres[n]?abort ->
+-              skip
+-      od;
+-
+-TRANSFER:
+-      pres_to_ses[n]!transfer;
+-      do
+-      :: use_to_pres[n]?abort ->
+-              if
+-              :: (!uabort) ->
+-                      uabort = 1;
+-                      pres_to_ses[n]!abort
+-              :: (uabort) ->
+-                      assert(1+1!=2)
+-              fi
+-      :: ses_to_pres[n]?accept,0 ->
+-              goto DONE
+-      :: ses_to_pres[n]?reject(status) ->
+-              if
+-              :: (status == FATAL || uabort) ->
+-                      goto FAIL
+-              :: (status == NON_FATAL && !uabort) ->
+-progress:             goto TRANSFER
+-              fi
+-      od;
+-DONE:
+-      pres_to_use[n]!accept;
+-      goto endIDLE;
+-FAIL:
+-      pres_to_use[n]!reject;
+-      goto endIDLE
+-}
+//GO.SYSIN DD App.F.present
+echo App.F.session 1>&2
+sed 's/.//' >App.F.session <<'//GO.SYSIN DD App.F.session'
+-/*
+- * Session Layer Validation Model
+- */
+-
+-proctype session(bit n)
+-{     bit toggle;
+-      byte type, status;
+-
+-endIDLE:
+-      do
+-      :: pres_to_ses[n]?type ->
+-              if
+-              :: (type == transfer) ->
+-                      goto DATA_OUT
+-              :: (type != transfer)   /* ignore */
+-              fi
+-      :: flow_to_ses[n]?type,0 ->
+-              if
+-              :: (type == connect) ->
+-                      goto DATA_IN
+-              :: (type != connect)    /* ignore */
+-              fi
+-      od;
+-
+-DATA_IN:              /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!create;
+-      do
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_flow[n]!reject,0;
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              ses_to_flow[n]!accept,0;
+-              break
+-      od;
+-                      /* 2. Receive the data, upto eof */
+-      do
+-      :: flow_to_ses[n]?data,0 ->
+-              ses_to_fsrv[n]!data
+-      :: flow_to_ses[n]?eof,0 ->
+-              ses_to_fsrv[n]!eof;
+-              break
+-      :: pres_to_ses[n]?transfer ->
+-              ses_to_pres[n]!reject(NON_FATAL)
+-      :: flow_to_ses[n]?close,0 ->    /* remote user aborted */
+-              ses_to_fsrv[n]!close;
+-              break
+-      :: timeout ->           /* got disconnected */
+-              ses_to_fsrv[n]!close;
+-              goto endIDLE
+-      od;
+-                      /* 3. Close the connection */
+-      ses_to_flow[n]!close,0;
+-      goto endIDLE;
+-
+-DATA_OUT:             /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!open;
+-      if
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              skip
+-      fi;
+-                      /* 2. initialize flow control */
+-      ses_to_flow[n]!sync,toggle;
+-      do
+-      :: atomic {
+-              flow_to_ses[n]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-         }
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      od;
+-      toggle = 1 - toggle;
+-                      /* 3. prepare remote file fsrver */
+-      ses_to_flow[n]!connect,0;
+-      if
+-      :: flow_to_ses[n]?reject,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?connect,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(NON_FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?accept,0 ->
+-              skip
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      fi;
+-                      /* 4. Transmit the data, upto eof */
+-      do
+-      :: fsrv_to_ses[n]?data ->
+-              ses_to_flow[n]!data,0
+-      :: fsrv_to_ses[n]?eof ->
+-              ses_to_flow[n]!eof,0;
+-              status = COMPLETE;
+-              break
+-      :: pres_to_ses[n]?abort ->      /* local user aborted */
+-              ses_to_fsrv[n]!close;
+-              ses_to_flow[n]!close,0;
+-              status = FATAL;
+-              break
+-      od;
+-                      /* 5. Close the connection */
+-      do
+-      :: pres_to_ses[n]?abort         /* ignore */
+-      :: flow_to_ses[n]?close,0 ->
+-              if
+-              :: (status == COMPLETE) ->
+-                      ses_to_pres[n]!accept,0
+-              :: (status != COMPLETE) ->
+-                      ses_to_pres[n]!reject(status)
+-              fi;
+-              break
+-      :: timeout ->
+-              ses_to_pres[n]!reject(FATAL);
+-              break
+-      od;
+-      goto endIDLE
+-}
+//GO.SYSIN DD App.F.session
+echo App.F.user 1>&2
+sed 's/.//' >App.F.user <<'//GO.SYSIN DD App.F.user'
+-/*
+- * User Layer Validation Model
+- */
+-
+-proctype userprc(bit n)
+-{
+-      use_to_pres[n]!transfer;
+-      if
+-      :: pres_to_use[n]?accept -> goto Done
+-      :: pres_to_use[n]?reject -> goto Done
+-      :: use_to_pres[n]!abort  -> goto Aborted
+-      fi;
+-Aborted:
+-      if
+-      :: pres_to_use[n]?accept -> goto Done
+-      :: pres_to_use[n]?reject -> goto Done
+-      fi;
+-Done:
+-      skip
+-}
+//GO.SYSIN DD App.F.user
+echo p101 1>&2
+sed 's/.//' >p101 <<'//GO.SYSIN DD p101'
+-#define msgtype 33
+-
+-chan name = [0] of { byte, byte };
+-
+-/* byte name;         typo  - this line shouldn't have been here */
+-
+-proctype A()
+-{     name!msgtype(124);
+-      name!msgtype(121)
+-}
+-proctype B()
+-{     byte state;
+-      name?msgtype(state)
+-}
+-init
+-{     atomic { run A(); run B() }
+-}
+//GO.SYSIN DD p101
+echo p102 1>&2
+sed 's/.//' >p102 <<'//GO.SYSIN DD p102'
+-#define a 1
+-#define b 2
+-
+-chan ch = [1] of { byte };
+-
+-proctype A() { ch!a }
+-proctype B() { ch!b }
+-proctype C()
+-{     if
+-      :: ch?a
+-      :: ch?b
+-      fi
+-}
+-init { atomic { run A(); run B(); run C() } }
+//GO.SYSIN DD p102
+echo p104.1 1>&2
+sed 's/.//' >p104.1 <<'//GO.SYSIN DD p104.1'
+-#define N    128
+-#define size  16
+-
+-chan in    = [size] of { short };
+-chan large = [size] of { short };
+-chan small = [size] of { short };
+-
+-proctype split()
+-{     short cargo;
+-
+-      do
+-      :: in?cargo ->
+-              if
+-              :: (cargo >= N) -> large!cargo
+-              :: (cargo <  N) -> small!cargo
+-              fi
+-      od
+-}
+-init {        run split() }
+//GO.SYSIN DD p104.1
+echo p104.2 1>&2
+sed 's/.//' >p104.2 <<'//GO.SYSIN DD p104.2'
+-#define N    128
+-#define size  16
+-
+-chan in    = [size] of { short };
+-chan large = [size] of { short };
+-chan small = [size] of { short };
+-
+-proctype split()
+-{     short cargo;
+-
+-      do
+-      :: in?cargo ->
+-              if
+-              :: (cargo >= N) -> large!cargo
+-              :: (cargo <  N) -> small!cargo
+-              fi
+-      od
+-}
+-proctype merge()
+-{     short cargo;
+-
+-      do
+-      ::      if
+-              :: large?cargo
+-              :: small?cargo
+-              fi;
+-              in!cargo
+-      od
+-}
+-init
+-{     in!345; in!12; in!6777; in!32; in!0;
+-      run split(); run merge()
+-}
+//GO.SYSIN DD p104.2
+echo p105.1 1>&2
+sed 's/.//' >p105.1 <<'//GO.SYSIN DD p105.1'
+-#define p     0
+-#define v     1
+-
+-chan sema = [0] of { bit };
+-
+-proctype dijkstra()
+-{     do
+-      :: sema!p -> sema?v
+-      od      
+-}
+-proctype user()
+-{     sema?p;
+-      /* critical section */
+-      sema!v
+-      /* non-critical section */
+-}
+-init
+-{     atomic {
+-              run dijkstra();
+-              run user(); run user(); run user()
+-      }
+-}
+//GO.SYSIN DD p105.1
+echo p105.2 1>&2
+sed 's/.//' >p105.2 <<'//GO.SYSIN DD p105.2'
+-proctype fact(int n; chan p)
+-{     int result;
+-
+-      if
+-      :: (n <= 1) -> p!1
+-      :: (n >= 2) ->
+-              chan child = [1] of { int };
+-              run fact(n-1, child);
+-              child?result;
+-              p!n*result
+-      fi
+-}
+-init
+-{     int result;
+-      chan child = [1] of { int };
+-
+-      run fact(7, child);
+-      child?result;
+-      printf("result: %d\n", result)
+-}
+//GO.SYSIN DD p105.2
+echo p107 1>&2
+sed 's/.//' >p107 <<'//GO.SYSIN DD p107'
+-mtype = { ack, nak, err, next, accept }
+-
+-proctype transfer(chan in, out, chin, chout)
+-{     byte o, i;
+-
+-      in?next(o);
+-      do
+-      :: chin?nak(i) -> out!accept(i); chout!ack(o)
+-      :: chin?ack(i) -> out!accept(i); in?next(o); chout!ack(o)
+-      :: chin?err(i) -> chout!nak(o)
+-      od
+-}
+-init
+-{     chan AtoB = [1] of { byte, byte };
+-      chan BtoA = [1] of { byte, byte };
+-      chan Ain  = [2] of { byte, byte };
+-      chan Bin  = [2] of { byte, byte };
+-      chan Aout = [2] of { byte, byte };
+-      chan Bout = [2] of { byte, byte };
+-
+-      atomic {
+-              run transfer(Ain, Aout, AtoB, BtoA);
+-              run transfer(Bin, Bout, BtoA, AtoB)
+-      };
+-      AtoB!err(0)
+-}
+//GO.SYSIN DD p107
+echo p108 1>&2
+sed 's/.//' >p108 <<'//GO.SYSIN DD p108'
+-/***** Ackermann's function *****/
+-
+-/*    a good example where a simulation run is the
+-      better choice - and verification is overkill.
+-
+-      1. simulation
+-              -> straight simulation (spin p108) takes
+-              -> approx. 6.4 sec on an SGI R3000
+-              -> prints the answer: ack(3,3) = 61
+-              -> after creating 2433 processes
+-
+-      note: all process invocations can, at least in one
+-      feasible execution scenario, overlap - if each
+-      process chooses to hang around indefinitely in
+-      its dying state, at the closing curly brace.
+-      this means that the maximum state vector `could' grow
+-      to hold all 2433 processes or about 2433*12 bytes of data.
+-      the assert(0) at the end makes sure though that the run
+-      stops the first time we complete an execution sequence
+-      that computes the answer, so the following suffices:
+-
+-      2. verification
+-              -> spin -a p108
+-              -> cc -DVECTORSZ=2048 -o pan pan.c
+-              -> pan -m15000
+-              -> which completes in about 5 sec
+- */
+-
+-proctype ack(short a, b; chan ch1)
+-{     chan ch2 = [1] of { short };
+-      short ans;
+-
+-      if
+-      :: (a == 0) ->
+-              ans = b+1
+-      :: (a != 0) ->
+-              if
+-              :: (b == 0) ->
+-                      run ack(a-1, 1, ch2)
+-              :: (b != 0) ->
+-                      run ack(a, b-1, ch2);
+-                      ch2?ans;
+-                      run ack(a-1, ans, ch2)
+-              fi;
+-              ch2?ans
+-      fi;
+-      ch1!ans
+-}
+-init
+-{     chan ch = [1] of { short };
+-      short ans;
+-
+-      run ack(3, 3, ch);
+-      ch?ans;
+-      printf("ack(3,3) = %d\n", ans);
+-      assert(0)       /* a forced stop, (Chapter 6) */
+-}
+//GO.SYSIN DD p108
+echo p116 1>&2
+sed 's/.//' >p116 <<'//GO.SYSIN DD p116'
+-byte state = 1;
+-
+-proctype A()
+-{     (state == 1) -> state = state + 1;
+-      assert(state == 2)
+-}
+-proctype B()
+-{     (state == 1) -> state = state - 1;
+-      assert(state == 0)
+-}
+-init { run A(); run B() }
+//GO.SYSIN DD p116
+echo p117 1>&2
+sed 's/.//' >p117 <<'//GO.SYSIN DD p117'
+-#define p     0
+-#define v     1
+-
+-chan sema = [0] of { bit };   /* typo in original `=' was missing */
+-
+-proctype dijkstra()
+-{     do
+-      :: sema!p -> sema?v
+-      od      
+-}
+-byte count;
+-
+-proctype user()
+-{     sema?p;
+-      count = count+1;
+-      skip;   /* critical section */
+-      count = count-1;
+-      sema!v;
+-      skip    /* non-critical section */
+-}
+-proctype monitor() { assert(count == 0 || count == 1) }
+-init
+-{     atomic {
+-              run dijkstra(); run monitor();
+-              run user(); run user(); run user()
+-      }
+-}
+//GO.SYSIN DD p117
+echo p123 1>&2
+sed 's/.//' >p123 <<'//GO.SYSIN DD p123'
+-/* alternating bit - version with message loss */
+-
+-#define MAX   3
+-
+-mtype = { msg0, msg1, ack0, ack1 };
+-
+-chan  sender  =[1] of { byte };
+-chan  receiver=[1] of { byte };
+-
+-proctype Sender()
+-{     byte any;
+-again:
+-      do
+-      :: receiver!msg1;
+-              if
+-              :: sender?ack1 -> break
+-              :: sender?any /* lost */
+-              :: timeout    /* retransmit */
+-              fi
+-      od;
+-      do
+-      :: receiver!msg0;
+-              if
+-              :: sender?ack0 -> break
+-              :: sender?any /* lost */
+-              :: timeout    /* retransmit */
+-              fi
+-      od;
+-      goto again
+-}
+-
+-proctype Receiver()
+-{     byte any;
+-again:
+-      do
+-      :: receiver?msg1 -> sender!ack1; break
+-      :: receiver?msg0 -> sender!ack0
+-      :: receiver?any /* lost */
+-      od;
+-P0:
+-      do
+-      :: receiver?msg0 -> sender!ack0; break
+-      :: receiver?msg1 -> sender!ack1
+-      :: receiver?any /* lost */
+-      od;
+-P1:
+-      goto again
+-}
+-
+-init { atomic { run Sender(); run Receiver() } }
+-
+-never {
+-      do
+-      :: skip /* allow any time delay */
+-      :: receiver?[msg0] -> goto accept0
+-      :: receiver?[msg1] -> goto accept1
+-      od;
+-accept0:
+-      do
+-      :: !Receiver[2]@P0      /* n.b. new syntax of remote reference */
+-      od;
+-accept1:
+-      do
+-      :: !Receiver[2]@P1
+-      od
+-}
+//GO.SYSIN DD p123
+echo p248 1>&2
+sed 's/.//' >p248 <<'//GO.SYSIN DD p248'
+-proctype fact(int n; chan p)
+-{     int result;
+-
+-      if
+-      :: (n <= 1) -> p!1
+-      :: (n >= 2) ->
+-              chan child = [1] of { int };
+-              run fact(n-1, child);
+-              child?result;
+-              p!n*result
+-      fi
+-}
+-init
+-{     int result;
+-      chan child = [1] of { int };
+-
+-      run fact(12, child);
+-      child?result;
+-      printf("result: %d\n", result)
+-}
+//GO.SYSIN DD p248
+echo p312 1>&2
+sed 's/.//' >p312 <<'//GO.SYSIN DD p312'
+-#define MIN   9       /* first data message to send */
+-#define MAX   12      /* last  data message to send */
+-#define FILL  99      /* filler message */
+-
+-mtype = { ack, nak, err }
+-
+-proctype transfer(chan chin, chout)
+-{     byte o, i, last_i=MIN;
+-
+-      o = MIN+1;
+-      do
+-      :: chin?nak(i) ->
+-              assert(i == last_i+1);
+-              chout!ack(o)
+-      :: chin?ack(i) ->
+-              if
+-              :: (o <  MAX) -> o = o+1        /* next */
+-              :: (o >= MAX) -> o = FILL       /* done */
+-              fi;
+-              chout!ack(o)
+-      :: chin?err(i) ->
+-              chout!nak(o)
+-      od
+-}
+-
+-proctype channel(chan in, out)
+-{     byte md, mt;
+-      do
+-      :: in?mt,md ->
+-              if
+-              :: out!mt,md
+-              :: out!err,0
+-              fi
+-      od
+-}
+-
+-init
+-{     chan AtoB = [1] of { byte, byte };
+-      chan BtoC = [1] of { byte, byte };
+-      chan CtoA = [1] of { byte, byte };
+-      atomic {
+-              run transfer(AtoB, BtoC);
+-              run channel(BtoC, CtoA);
+-              run transfer(CtoA, AtoB)
+-      };
+-      AtoB!err,0      /* start */
+-}
+//GO.SYSIN DD p312
+echo p319 1>&2
+sed 's/.//' >p319 <<'//GO.SYSIN DD p319'
+-#define true  1
+-#define false 0
+-
+-bool busy[3];
+-
+-chan   up[3] = [1] of { byte };
+-chan down[3] = [1] of { byte };
+-
+-mtype = { start, attention, data, stop }
+-
+-proctype station(byte id; chan in, out)
+-{     do
+-      :: in?start ->
+-              atomic { !busy[id] -> busy[id] = true };
+-              out!attention;
+-              do
+-              :: in?data -> out!data
+-              :: in?stop -> break
+-              od;
+-              out!stop;
+-              busy[id] = false
+-      :: atomic { !busy[id] -> busy[id] = true };
+-              out!start;
+-              in?attention;
+-              do
+-              :: out!data -> in?data
+-              :: out!stop -> break
+-              od;
+-              in?stop;
+-              busy[id] = false
+-      od
+-}
+-
+-init {
+-      atomic {
+-              run station(0, up[2], down[2]);
+-              run station(1, up[0], down[0]);
+-              run station(2, up[1], down[1]);
+-
+-              run station(0, down[0], up[0]);
+-              run station(1, down[1], up[1]);
+-              run station(2, down[2], up[2])
+-      }
+-}
+//GO.SYSIN DD p319
+echo p320 1>&2
+sed 's/.//' >p320 <<'//GO.SYSIN DD p320'
+-#define true  1
+-#define false 0
+-#define Aturn false
+-#define Bturn true
+-
+-bool x, y, t;
+-bool ain, bin;
+-
+-proctype A()
+-{     x = true;
+-      t = Bturn;
+-      (y == false || t == Aturn);
+-      ain = true;
+-      assert(bin == false);   /* critical section */
+-      ain = false;
+-      x = false
+-}
+-
+-proctype B()
+-{     y = true;
+-      t = Aturn;
+-      (x == false || t == Bturn);
+-      bin = true;
+-      assert(ain == false);   /* critical section */
+-      bin = false;
+-      y = false
+-}
+-
+-init
+-{     run A(); run B()
+-}
+//GO.SYSIN DD p320
+echo p325.test 1>&2
+sed 's/.//' >p325.test <<'//GO.SYSIN DD p325.test'
+-proctype test_sender(bit n)
+-{     byte type, toggle;
+-
+-      ses_to_flow[n]!sync,toggle;
+-      do
+-      :: flow_to_ses[n]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-      :: timeout ->
+-              ses_to_flow[n]!sync,toggle
+-      od;
+-      toggle = 1 - toggle;
+-
+-      do
+-      :: ses_to_flow[n]!data,white
+-      :: ses_to_flow[n]!data,red -> break
+-      od;
+-      do
+-      :: ses_to_flow[n]!data,white
+-      :: ses_to_flow[n]!data,blue -> break
+-      od;
+-      do
+-      :: ses_to_flow[n]!data,white
+-      :: break
+-      od
+-}
+-proctype test_receiver(bit n)
+-{
+-      do
+-      :: flow_to_ses[n]?data,white
+-      :: flow_to_ses[n]?data,red -> break
+-      od;
+-      do
+-      :: flow_to_ses[n]?data,white
+-      :: flow_to_ses[n]?data,blue -> break
+-      od;
+-end:  do
+-      :: flow_to_ses[n]?data,white
+-      od
+-}
+//GO.SYSIN DD p325.test
+echo p327.upper 1>&2
+sed 's/.//' >p327.upper <<'//GO.SYSIN DD p327.upper'
+-proctype upper()
+-{     byte s_state, r_state;
+-      byte type, toggle;
+-
+-      ses_to_flow[0]!sync,toggle;
+-      do
+-      :: flow_to_ses[0]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-      :: timeout ->
+-              ses_to_flow[0]!sync,toggle
+-      od;
+-      toggle = 1 - toggle;
+-
+-      do
+-      /* sender */
+-      :: ses_to_flow[0]!white,0
+-      :: atomic {
+-              (s_state == 0 && len (ses_to_flow[0]) < QSZ) ->
+-              ses_to_flow[0]!red,0 ->
+-              s_state = 1
+-         }
+-      :: atomic {
+-              (s_state == 1 && len (ses_to_flow[0]) < QSZ) ->
+-              ses_to_flow[0]!blue,0 ->
+-              s_state = 2
+-         }
+-      /* receiver */
+-      :: flow_to_ses[1]?white,0
+-      :: atomic {
+-              (r_state == 0 && flow_to_ses[1]?[red]) ->
+-              flow_to_ses[1]?red,0 ->
+-              r_state = 1
+-         }
+-      :: atomic {
+-              (r_state == 0 && flow_to_ses[1]?[blue]) ->
+-              assert(0)
+-         }
+-      :: atomic {
+-              (r_state == 1 && flow_to_ses[1]?[blue]) ->
+-              flow_to_ses[1]?blue,0;
+-              break
+-         }
+-      :: atomic {
+-              (r_state == 1 && flow_to_ses[1]?[red]) ->
+-              assert(0)
+-         }
+-      od;
+-end:
+-      do
+-      :: flow_to_ses[1]?white,0
+-      :: flow_to_ses[1]?red,0 -> assert(0)
+-      :: flow_to_ses[1]?blue,0 -> assert(0)
+-      od
+-}
+//GO.SYSIN DD p327.upper
+echo p329 1>&2
+sed 's/.//' >p329 <<'//GO.SYSIN DD p329'
+-/*
+- * PROMELA Validation Model
+- * FLOW CONTROL LAYER VALIDATION
+- */
+-
+-#define LOSS          0       /* message loss   */
+-#define DUPS          0       /* duplicate msgs */
+-#define QSZ           2       /* queue size     */
+-
+-mtype = {
+-      red, white, blue,
+-      abort, accept, ack, sync_ack, close, connect,
+-      create, data, eof, open, reject, sync, transfer,
+-      FATAL, NON_FATAL, COMPLETE
+-      }
+-
+-chan ses_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_ses[2] = [QSZ] of { byte, byte };
+-chan dll_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_dll[2];
+-
+-#include "App.F.flow_cl"
+-#include "p327.upper"
+-
+-init
+-{
+-      atomic {
+-        flow_to_dll[0] = dll_to_flow[1];
+-        flow_to_dll[1] = dll_to_flow[0];
+-        run fc(0); run fc(1);
+-        run upper()
+-      }
+-}
+//GO.SYSIN DD p329
+echo p330 1>&2
+sed 's/.//' >p330 <<'//GO.SYSIN DD p330'
+-/*
+- * PROMELA Validation Model
+- * FLOW CONTROL LAYER VALIDATION
+- */
+-
+-#define LOSS          0       /* message loss   */
+-#define DUPS          0       /* duplicate msgs */
+-#define QSZ           2       /* queue size     */
+-
+-mtype = {
+-      red, white, blue,
+-      abort, accept, ack, sync_ack, close, connect,
+-      create, data, eof, open, reject, sync, transfer,
+-      FATAL, NON_FATAL, COMPLETE
+-      }
+-
+-chan ses_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_ses[2] = [QSZ] of { byte, byte };
+-chan dll_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_dll[2];
+-
+-#include "App.F.flow_cl"
+-#include "p327.upper"
+-
+-init
+-{
+-      atomic {
+-        flow_to_dll[0] = dll_to_flow[1];
+-        flow_to_dll[1] = dll_to_flow[0];
+-        run fc(0); run fc(1);
+-        run upper()
+-      }
+-}
+//GO.SYSIN DD p330
+echo p337.defines2 1>&2
+sed 's/.//' >p337.defines2 <<'//GO.SYSIN DD p337.defines2'
+-/*
+- * PROMELA Validation Model
+- * global definitions
+- */
+-
+-#define QSZ           2       /* queue size     */
+-
+-mtype = {
+-      red, white, blue,
+-      abort, accept, ack, sync_ack, close, connect,
+-      create, data, eof, open, reject, sync, transfer,
+-      FATAL, NON_FATAL, COMPLETE
+-      }
+-
+-chan use_to_pres[2] = [QSZ] of { mtype };
+-chan pres_to_use[2] = [QSZ] of { mtype };
+-chan pres_to_ses[2] = [QSZ] of { mtype };
+-chan ses_to_pres[2] = [QSZ] of { mtype, byte };
+-chan ses_to_flow[2] = [QSZ] of { mtype, byte };
+-chan ses_to_fsrv[2] = [0] of { mtype };
+-chan fsrv_to_ses[2] = [0] of { mtype };
+-chan flow_to_ses[2];
+//GO.SYSIN DD p337.defines2
+echo p337.fserver 1>&2
+sed 's/.//' >p337.fserver <<'//GO.SYSIN DD p337.fserver'
+-/*
+- * File Server Validation Model
+- */
+-
+-proctype fserver(bit n)
+-{
+-end:  do
+-      :: ses_to_fsrv[n]?create ->     /* incoming */
+-              if
+-              :: fsrv_to_ses[n]!reject
+-              :: fsrv_to_ses[n]!accept ->
+-                      do
+-                      :: ses_to_fsrv[n]?data
+-                      :: ses_to_fsrv[n]?eof -> break
+-                      :: ses_to_fsrv[n]?close -> break
+-                      od
+-              fi
+-      :: ses_to_fsrv[n]?open ->               /* outgoing */
+-              if
+-              :: fsrv_to_ses[n]!reject
+-              :: fsrv_to_ses[n]!accept ->
+-                      do
+-                      :: fsrv_to_ses[n]!data -> progress: skip
+-                      :: ses_to_fsrv[n]?close -> break
+-                      :: fsrv_to_ses[n]!eof -> break
+-                      od
+-              fi
+-      od
+-}
+//GO.SYSIN DD p337.fserver
+echo p337.pftp.ses 1>&2
+sed 's/.//' >p337.pftp.ses <<'//GO.SYSIN DD p337.pftp.ses'
+-/*
+- * PROMELA Validation Model
+- * Session Layer
+- */
+-
+-#include "p337.defines2"
+-#include "p337.user"
+-#include "App.F.present"
+-#include "p337.session"
+-#include "p337.fserver"
+-
+-init
+-{     atomic {
+-        run userprc(0); run userprc(1);
+-        run present(0); run present(1);
+-        run session(0); run session(1);
+-        run fserver(0); run fserver(1);
+-        flow_to_ses[0] = ses_to_flow[1];
+-        flow_to_ses[1] = ses_to_flow[0]
+-      }
+-}
+//GO.SYSIN DD p337.pftp.ses
+echo p337.session 1>&2
+sed 's/.//' >p337.session <<'//GO.SYSIN DD p337.session'
+-/*
+- * Session Layer Validation Model
+- */
+-
+-proctype session(bit n)
+-{     bit toggle;
+-      byte type, status;
+-
+-endIDLE:
+-      do
+-      :: pres_to_ses[n]?type ->
+-              if
+-              :: (type == transfer) ->
+-                      goto DATA_OUT
+-              :: (type != transfer)   /* ignore */
+-              fi
+-      :: flow_to_ses[n]?type,0 ->
+-              if
+-              :: (type == connect) ->
+-                      goto DATA_IN
+-              :: (type != connect)    /* ignore */
+-              fi
+-      od;
+-
+-DATA_IN:              /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!create;
+-      do
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_flow[n]!reject,0;
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              ses_to_flow[n]!accept,0;
+-              break
+-      od;
+-                      /* 2. Receive the data, upto eof */
+-      do
+-      :: flow_to_ses[n]?data,0 ->
+-              ses_to_fsrv[n]!data
+-      :: flow_to_ses[n]?eof,0 ->
+-              ses_to_fsrv[n]!eof;
+-              break
+-      :: pres_to_ses[n]?transfer ->
+-              ses_to_pres[n]!reject(NON_FATAL)
+-      :: flow_to_ses[n]?close,0 ->    /* remote user aborted */
+-              ses_to_fsrv[n]!close;
+-              break
+-      :: timeout ->           /* got disconnected */
+-              ses_to_fsrv[n]!close;
+-              goto endIDLE
+-      od;
+-                      /* 3. Close the connection */
+-      ses_to_flow[n]!close,0;
+-      goto endIDLE;
+-
+-DATA_OUT:             /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!open;
+-      if
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              skip
+-      fi;
+-                      /* 2. initialize flow control *** disabled
+-      ses_to_flow[n]!sync,toggle;
+-      do
+-      :: atomic {
+-              flow_to_ses[n]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-         }
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      od;
+-      toggle = 1 - toggle;
+-                      /* 3. prepare remote file fsrver */
+-      ses_to_flow[n]!connect,0;
+-      if
+-      :: flow_to_ses[n]?reject,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?connect,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(NON_FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?accept,0 ->
+-              skip
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      fi;
+-                      /* 4. Transmit the data, upto eof */
+-      do
+-      :: fsrv_to_ses[n]?data ->
+-              ses_to_flow[n]!data,0
+-      :: fsrv_to_ses[n]?eof ->
+-              ses_to_flow[n]!eof,0;
+-              status = COMPLETE;
+-              break
+-      :: pres_to_ses[n]?abort ->      /* local user aborted */
+-              ses_to_fsrv[n]!close;
+-              ses_to_flow[n]!close,0;
+-              status = FATAL;
+-              break
+-      od;
+-                      /* 5. Close the connection */
+-      do
+-      :: pres_to_ses[n]?abort         /* ignore */
+-      :: flow_to_ses[n]?close,0 ->
+-              if
+-              :: (status == COMPLETE) ->
+-                      ses_to_pres[n]!accept,0
+-              :: (status != COMPLETE) ->
+-                      ses_to_pres[n]!reject(status)
+-              fi;
+-              break
+-      :: timeout ->
+-              ses_to_pres[n]!reject(FATAL);
+-              break
+-      od;
+-      goto endIDLE
+-}
+//GO.SYSIN DD p337.session
+echo p337.user 1>&2
+sed 's/.//' >p337.user <<'//GO.SYSIN DD p337.user'
+-/*
+- * User Layer Validation Model
+- */
+-
+-proctype userprc(bit n)
+-{
+-      use_to_pres[n]!transfer;
+-      if
+-      :: pres_to_use[n]?accept -> goto Done
+-      :: pres_to_use[n]?reject -> goto Done
+-      :: use_to_pres[n]!abort  -> goto Aborted
+-      fi;
+-Aborted:
+-      if
+-      :: pres_to_use[n]?accept -> goto Done
+-      :: pres_to_use[n]?reject -> goto Done
+-      fi;
+-Done:
+-      skip
+-}
+//GO.SYSIN DD p337.user
+echo p342.pftp.ses1 1>&2
+sed 's/.//' >p342.pftp.ses1 <<'//GO.SYSIN DD p342.pftp.ses1'
+-/*
+- * PROMELA Validation Model
+- * Session Layer
+- */
+-
+-#include "p337.defines2"
+-#include "p337.user"
+-#include "App.F.present"
+-#include "p337.session"
+-#include "p337.fserver"
+-
+-init
+-{
+-      atomic {
+-        run userprc(0); run userprc(1);
+-        run present(0); run present(1);
+-        run session(0); run session(1);
+-        run fserver(0); run fserver(1);
+-        flow_to_ses[0] = ses_to_flow[1];
+-        flow_to_ses[1] = ses_to_flow[0]
+-      };
+-      atomic {
+-              byte any;
+-              chan foo = [1] of { byte, byte };
+-              ses_to_flow[0] = foo;
+-              ses_to_flow[1] = foo
+-      };
+-end:  do
+-      :: foo?any,any
+-      od
+-}
+//GO.SYSIN DD p342.pftp.ses1
+echo p343.claim 1>&2
+sed 's/.//' >p343.claim <<'//GO.SYSIN DD p343.claim'
+-never {
+-      skip;   /* match first step of init (spin version 2.0) */
+-      do
+-      :: !pres_to_ses[0]?[transfer]
+-      && !flow_to_ses[0]?[connect]
+-      :: pres_to_ses[0]?[transfer] ->
+-              goto accept0
+-      :: flow_to_ses[0]?[connect] ->
+-              goto accept1
+-      od;
+-accept0:
+-      do
+-      :: !ses_to_pres[0]?[accept]
+-      && !ses_to_pres[0]?[reject]
+-      od;
+-accept1:
+-      do
+-      :: !ses_to_pres[1]?[accept]
+-      && !ses_to_pres[1]?[reject]
+-      od
+-}
+//GO.SYSIN DD p343.claim
+echo p347.pftp.ses5 1>&2
+sed 's/.//' >p347.pftp.ses5 <<'//GO.SYSIN DD p347.pftp.ses5'
+-/*
+- * PROMELA Validation Model
+- * Session Layer
+- */
+-
+-#include "p337.defines2"
+-#include "p347.pres.sim"
+-#include "p347.session.prog"
+-#include "p337.fserver"
+-
+-init
+-{     atomic {
+-        run present(0); run present(1);
+-        run session(0); run session(1);
+-        run fserver(0); run fserver(1);
+-        flow_to_ses[0] = ses_to_flow[1];
+-        flow_to_ses[1] = ses_to_flow[0]
+-      }
+-}
+//GO.SYSIN DD p347.pftp.ses5
+echo p347.pres.sim 1>&2
+sed 's/.//' >p347.pres.sim <<'//GO.SYSIN DD p347.pres.sim'
+-/*
+- * PROMELA Validation Model
+- * Presentation & User Layer - combined and reduced
+- */
+-
+-proctype present(bit n)
+-{     byte status;
+-progress0:
+-      pres_to_ses[n]!transfer ->
+-      do
+-      :: pres_to_ses[n]!abort;
+-progress1:    skip
+-      :: ses_to_pres[n]?accept,status ->
+-                      break
+-      :: ses_to_pres[n]?reject,status ->
+-              if
+-              :: (status == NON_FATAL) ->
+-                      goto progress0
+-              :: (status != NON_FATAL) ->
+-                      break
+-              fi
+-      od
+-}
+//GO.SYSIN DD p347.pres.sim
+echo p347.session.prog 1>&2
+sed 's/.//' >p347.session.prog <<'//GO.SYSIN DD p347.session.prog'
+-/*
+- * Session Layer Validation Model
+- */
+-
+-proctype session(bit n)
+-{     bit toggle;
+-      byte type, status;
+-
+-endIDLE:
+-      do
+-      :: pres_to_ses[n]?type ->
+-              if
+-              :: (type == transfer) ->
+-                      goto progressDATA_OUT
+-              :: (type != transfer)   /* ignore */
+-              fi
+-      :: flow_to_ses[n]?type,0 ->
+-              if
+-              :: (type == connect) ->
+-                      goto progressDATA_IN
+-              :: (type != connect)    /* ignore */
+-              fi
+-      od;
+-
+-progressDATA_IN:              /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!create;
+-      do
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_flow[n]!reject,0;
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              ses_to_flow[n]!accept,0;
+-              break
+-      od;
+-                      /* 2. Receive the data, upto eof */
+-      do
+-      :: flow_to_ses[n]?data,0 ->
+-progress:     ses_to_fsrv[n]!data
+-      :: flow_to_ses[n]?eof,0 ->
+-              ses_to_fsrv[n]!eof;
+-              break
+-      :: pres_to_ses[n]?transfer ->
+-              ses_to_pres[n]!reject(NON_FATAL)
+-      :: flow_to_ses[n]?close,0 ->    /* remote user aborted */
+-              ses_to_fsrv[n]!close;
+-              break
+-      :: timeout ->           /* got disconnected */
+-              ses_to_fsrv[n]!close;
+-              goto endIDLE
+-      od;
+-                      /* 3. Close the connection */
+-      ses_to_flow[n]!close,0;
+-      goto endIDLE;
+-
+-progressDATA_OUT:             /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!open;
+-      if
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              skip
+-      fi;
+-                      /* 2. initialize flow control *** disabled
+-      ses_to_flow[n]!sync,toggle;
+-      do
+-      :: atomic {
+-              flow_to_ses[n]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-         }
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      od;
+-      toggle = 1 - toggle;
+-                      /* 3. prepare remote file fsrver */
+-      ses_to_flow[n]!connect,0;
+-      if
+-      :: flow_to_ses[n]?reject,status ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?connect,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(NON_FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?accept,0 ->
+-              skip
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      fi;
+-                      /* 4. Transmit the data, upto eof */
+-      do
+-      :: fsrv_to_ses[n]?data ->
+-              ses_to_flow[n]!data,0
+-      :: fsrv_to_ses[n]?eof ->
+-              ses_to_flow[n]!eof,0;
+-              status = COMPLETE;
+-              break
+-      :: pres_to_ses[n]?abort ->      /* local user aborted */
+-              ses_to_fsrv[n]!close;
+-              ses_to_flow[n]!close,0;
+-              status = FATAL;
+-              break
+-      od;
+-                      /* 5. Close the connection */
+-      do
+-      :: pres_to_ses[n]?abort         /* ignore */
+-      :: flow_to_ses[n]?close,0 ->
+-              if
+-              :: (status == COMPLETE) ->
+-                      ses_to_pres[n]!accept,0
+-              :: (status != COMPLETE) ->
+-                      ses_to_pres[n]!reject(status)
+-              fi;
+-              break
+-      :: timeout ->
+-              ses_to_pres[n]!reject(FATAL);
+-              break
+-      od;
+-      goto endIDLE
+-}
+//GO.SYSIN DD p347.session.prog
+echo p94 1>&2
+sed 's/.//' >p94 <<'//GO.SYSIN DD p94'
+-byte state = 2;
+-
+-proctype A() { (state == 1) -> state = 3 }
+-
+-proctype B() { state = state - 1 }
+-
+-/* added: */
+-init { run A(); run B() }
+//GO.SYSIN DD p94
+echo p95.1 1>&2
+sed 's/.//' >p95.1 <<'//GO.SYSIN DD p95.1'
+-init { printf("hello world\n") }
+//GO.SYSIN DD p95.1
+echo p95.2 1>&2
+sed 's/.//' >p95.2 <<'//GO.SYSIN DD p95.2'
+-proctype A(byte state; short set)
+-{     (state == 1) -> state = set
+-}
+-
+-init { run A(1, 3) }
+//GO.SYSIN DD p95.2
+echo p96.1 1>&2
+sed 's/.//' >p96.1 <<'//GO.SYSIN DD p96.1'
+-byte state = 1;
+-
+-proctype A() { (state == 1) -> state = state + 1 }
+-
+-proctype B() { (state == 1) -> state = state - 1 }
+-
+-init { run A(); run B() }
+//GO.SYSIN DD p96.1
+echo p96.2 1>&2
+sed 's/.//' >p96.2 <<'//GO.SYSIN DD p96.2'
+-#define true  1
+-#define false 0
+-#define Aturn 1
+-#define Bturn 0
+-
+-bool x, y, t;
+-
+-proctype A()
+-{     x = true;
+-      t = Bturn;
+-      (y == false || t == Aturn);
+-      /* critical section */
+-      x = false
+-}
+-proctype B()
+-{     y = true;
+-      t = Aturn;
+-      (x == false || t == Bturn);
+-      /* critical section */
+-      y = false
+-}
+-init { run A(); run B() }
+//GO.SYSIN DD p96.2
+echo p97.1 1>&2
+sed 's/.//' >p97.1 <<'//GO.SYSIN DD p97.1'
+-byte state = 1;
+-proctype A() { atomic { (state == 1) -> state = state + 1 } }
+-proctype B() { atomic { (state == 1) -> state = state - 1 } }
+-init { run A(); run B() }
+//GO.SYSIN DD p97.1
+echo p97.2 1>&2
+sed 's/.//' >p97.2 <<'//GO.SYSIN DD p97.2'
+-proctype nr(short pid, a, b)
+-{     int res;
+-
+-atomic        {       res = (a*a+b)/2*a;
+-              printf("result %d: %d\n", pid, res)
+-      }
+-}
+-init { run nr(1,1,1); run nr(1,2,2); run nr(1,3,2) }
+//GO.SYSIN DD p97.2
+echo p99 1>&2
+sed 's/.//' >p99 <<'//GO.SYSIN DD p99'
+-proctype A(chan q1)
+-{     chan q2;
+-
+-      q1?q2;
+-      q2!123
+-}
+-
+-proctype B(chan qforb)
+-{     int x;
+-
+-      qforb?x;
+-      printf("x = %d\n", x)
+-}
+-
+-init
+-{     chan qname[2] = [1] of { chan };
+-      chan qforb = [1] of { int };
+-
+-      run A(qname[0]);
+-      run B(qforb);
+-
+-      qname[0]!qforb
+-}
+//GO.SYSIN DD p99
diff --git a/trunk/verif/Spin/Doc/Book2003Errata.html b/trunk/verif/Spin/Doc/Book2003Errata.html
new file mode 100755 (executable)
index 0000000..36b9fc4
--- /dev/null
@@ -0,0 +1,383 @@
+<html>\r
+<head>\r
+<title>Book Errata - The Spin Model Checker</title>\r
+</head>\r
+<h3>Typos found in the first printing (August 2003)</h3>\r
+<font face=helvetica,arial>\r
+<ul>\r
+<li>p. vi      chapter 8 topic listings, Breath-First -> Breadth-First</li>\r
+<li>p.  2      line 16 "always explicitly" -> "usually"</li>\r
+<li>p.  3      figure 1.1 is mirror reversed</li>\r
+<li>p. 4       the website crashdatabas.com no longer seems to exist</li>\r
+<li>p. 20      See note (*) below, provided by Heikki Tauriainen (Feb 1, 2006).\r
+<li>p. 22      6th line from the bottom: "if" -> "of"</li>\r
+<li>p. 25      4th line from the bottom: "variable in" -> "variable cnt"</li>\r
+<li>p. 26      10th line from bottom: "set to false" -> "set to true"</li>\r
+<li>p. 27      an error slipped into Figure 2.6. The fragment\r
+<pre>\r
+       M?data ->       /* receive data */\r
+       do\r
+       :: W!data       /* send data */\r
+       :: W!shutup;    /* or shutdown */\r
+               break\r
+       od\r
+</pre>\r
+is an unfortunate last-minute rewrite of the originally intended version:\r
+<pre>\r
+       do\r
+       :: M?data -> W!data\r
+       :: M?data -> W!shutup;\r
+               break\r
+       od\r
+</pre>\r
+The behavior is of course not equivalent.\r
+In particular, the version in the book cannot create the error scenario\r
+given on page 29, but the intended version can.</li>\r
+<li>p. 33      8th line from bottom: "the specification" -> "the specification of"</li>\r
+<li>p. 33      3rd line from bottom: "functions pointers" -> "function pointers</li>\r
+<li>p. 41      "1 <= n <= 32" -> "1 <= n < 32".</li>\r
+<li>p. 43      appel -> apple</li>\r
+<li>p. 52      11th line from the top: "p. 39." -> "p. 38."</li>\r
+<li>p. 69      bottom line: "exclusive read and exclusive write" -> "exclusive receive and exclusive send"</li>\r
+<li>p. 75 and 548      Goldstein -> Goldstine</li>\r
+<li>p. 81 and 271      pan.trail -> fair.pml.trail</li>\r
+<li>p. 81      3rd line from the bottom: "trace fpr" -> "trace for"</li>\r
+<li>p. 82      18th line from the bottom: "process than" -> "process that"</li>\r
+<li>p. 92      4th line from bottom: "Even traces" -> "Event traces"</li>\r
+<li>p. 96      middle of page identify -> identity</li>\r
+<li>p. 96      l. -6, for -> by</li>\r
+<li>p. 111     below figure 5.4: "f==free" -> "f=free"</li>\r
+<li>p. 119     12th line from the bottom; "xDm" -> "Dm"</li>\r
+<li>p. 121     figure 5.8, in captions on bottom two figures: "p" -> "q"</li>\r
+<li>p. 137     14th line from bottom (first rule in list): first 3 chars in wrong font</li>\r
+<li>p. 139     last line; italic P -> roman P</li>\r
+<li>p. 142     3rd line from bottom: "reach" -> "reached"</li>\r
+<li>p. 142     5th line from bottom: omit comma</li>\r
+<li>p. 148     middle of the page: "can be express" -> "can be expressed"</li>\r
+<li>p. 149     5th line from bottom: "eventually always" -> "always eventually"</li>\r
+<li>p. 150     replace "it is impossible for p to hold only in even steps in a run, but never at odd steps"\r
+with "it is possible for p to hold in even steps in a run, but it is not possible for p to hold in odd steps"</li>\r
+<li>p. 150     Omega-Regular Properties, line 1: "that" -> "than"</li>\r
+<li>p. 158     middle of page: redundant space after "("</li>\r
+<li>p. 168     the list of properties given for < and > is not exhaustive</li>\r
+<li>p. 174     11th line from bottom: "but" -> "by"</li>\r
+<li>p. 177     Procedure Search() in Figure 8.6 is incorrect. A corrected version is:\r
+<pre>\r
+Search()\r
+{\r
+       while (Empty_Queue(D) == false)\r
+       {       s = Del_Queue(D)\r
+               for each (s,1,s') member A.T\r
+               if In_Statespace(V, s') == false\r
+               {       Add_Statespace(V, s')\r
+                       Add_Queue(D, s')\r
+               }\r
+       }\r
+}\r
+</pre>\r
+</li>\r
+<li>p. 178     2nd line from top: "at state" -> "at each state", "of each state" -> "of that state"</li>\r
+<li>p. 179     lead -> led</li>\r
+<li>p. 180     before first 'if' stmnt inside for loop add: if (toggle == true)</li>\r
+<li>p. 185     Fig. 8.10, circle at s^{1}_{2} should be dotted</li>\r
+<li>p. 187     line -11: "interative" -> "iterative"</li>\r
+<li>p. 188     replace "(RxB)+(k+2)" with "Rx(B+k+2)"</li>\r
+<li>p. 193     Fig. 9.2, the two circles labeled 0,1,0 should be dashed</li>\r
+<li>p. 193     7th line from bottom: "g=g*2," -> "g=g*2."</li>\r
+<li>p. 196     line -9: "control control" -> "control"</li>\r
+<li>p. 204     last line, "to 133 seconds" -> "to 53 seconds"</li>\r
+<li>p. 208     a goof: m changes from bits to bytes between 2nd and 3rd paragraph</li>\r
+<li>p. 209     in first two formulas: (1-1/m) sup {kr}.</li>\r
+<li>p. 211     3rd line from below: probabilitie -> probabilities</li>\r
+<li>p. 212     line -2: "ration" -> "ratio"</li>\r
+<li>p. 214     A formal -> Formal</li>\r
+<li>p. 216     1st-2nd line: 'collissions' -> 'collisions'</li>\r
+<li>p. 219     last paragraph: missing right parenthesis</li>\r
+<li>p. 228     Celcius -> Celsius</li>\r
+<li>p. 228     in the list at the bottom: there are just 6 entries with 'keep' as a target</li>\r
+<li>p. 237     12th line from below: "postive" -> "zero".</li>\r
+<li>p. 237     4th line from below: "unsound" -> "incomplete".</li>\r
+<li>p. 238     knifes -> knives</li>\r
+<li>p. 241     7th line from bottom: "world0" -> "world\n"</li>\r
+<li>p. 243     Pressburger -> Presburger</li>\r
+<li>p. 251     Selet -> Select</li>\r
+<li>p. 262     10th line from bottom: "do to" -> "due to"</li>\r
+<li>p. 272     an basic -> a basic</li>\r
+<li>p. 272     "As a special feature [...], if the statement" omit "if"</li>\r
+<li>p. 279     "#define q" -> "#define r"\r
+<!--\r
+<li>p. 280     (strong) -> (weak)</li>\r
+-->\r
+<li>p. 281     Automata View -> Automaton View</li>\r
+<li>p. 283     The correct wording of the quote from Willem L. van der Poel, as corrected by its author:\r
+               <pre>"There are no wrong programs, it simply is another program."</pre>\r
+               (email from the author, Feb 1, 2006).\r
+<li>p. 284     8th line from bottom: omit "blue"</li>\r
+<li>p. 287     6th line from top: omit "blue"</li>\r
+<li>p. 307     top of page: "ringtone" -> "ring tone" </li>\r
+<li>p. 307     top of page: "dialtone" -> "dial tone"</li>\r
+<li>p. 307     top of page: "notone" -> "no tone"</li>\r
+<!-- <li>p. 332        3rd line from bottom: UTS without a trademark (see also next page, 1x)</li> -->\r
+<li>p. 333     11th line from top: "and early version" -> "an early version"</li>\r
+<li>p. 338     the line numbered [19] is actually from the FIX</li>\r
+<li>p. 339     6th line from below: pid 1 -> pid 0</li>\r
+<li>p. 393     2nd line from top: "innermostn" -> "innermost"</li>\r
+<li>p. 341     10th line from top: "body ," -> "body,"</li>\r
+<li>p. 346     identificatio -> identification</li>\r
+<li>p. 346     middle of the page: "tranaction" -> "transaction"</li>\r
+<li>p. 349     55 is not the integer square root of either 1024 or 3601.</li>\r
+<li>p. 356     n=1<<30 does not fail on all systems</li>\r
+<li>p. 359     Fig. 15.8: what looks like commas are really single quotes</li>\r
+<li>p. 359     Fig. 15.8: the automaton fails to detect strings that start inside a comment;</li>\r
+unfortunate given the example that also appears on this page...</li>\r
+<li>p. 365     the grammar listing misses productions for inlines</li>\r
+<li>p. 365     [active] PROCTYPE -> [active ['[' const ']']] PROCTYPE</li>\r
+<li>p. 367     "PRINT" -> "PRINTF"</li>\r
+<li>p. 369     in PREDEFINED: "373last" -> "374"</li>\r
+<li>p. 369     in PREDEFINED: "373nr_pr" -> "376"</li>\r
+<li>p. 369     5th line from bottom: "special case" -> "special cases"</li>\r
+<li>p. 370     8th line from bottom: "p.272" -> "p. 272"</li>\r
+<li>p. 370     2nd line from bottom: "(434)" -> "(p. 434)"</li>\r
+<li>p. 370     2nd line from bottom: "(p, 483)" -> "(p. 483)"</li>\r
+<li>p. 371     2nd line from top: "Two" -> "Three"</li>\r
+<li>p. 371     9th line from top: "or both of the above two" -> "of the above" </li>\r
+<li>p. 374     11th line from bottom: "from into" -> "to"</li>\r
+<li>p. 376     5th line from bottom: "at 256" -> "at 255"</li>\r
+<li>p. 377     5th line in DESCRIPTION: "process" -> "processes"</li>\r
+<li>p. 381     4th line from bottom: "four process" -> "four processes"</li>\r
+<li>p. 381     3rd line from bottom: "to three" -> "to four"</li>\r
+<li>p. 390     9th line from bottom: "recepient" -> "recipient"</li>\r
+<li>p. 393     10th line from bottom: "label L1" -> "label L2"\r
+<li>p. 395     6th line from top: "multiple field" -> "multiple fields"</li>\r
+<li>p. 397     4th line from top: "the the" -> "the"</li>\r
+<li>p. 398     11th line from bottom: redundant space after "("</li>\r
+<li>p. 402     7th line from top, "accidentily" -> "accidentally"</li>\r
+<li>p. 404     mixed fonts in Table</li>\r
+<li>p. 404     5th line from bottom: "the fact the" -> "the fact that the"</li>\r
+<li>p. 407     in Notes, 2nd line: "tha" -> "that"</li>\r
+<li>p. 408     "(x < 0)" -> "(x <= 0)"</li>\r
+<li>p. 411     last line: "ltl len" -> "ltl, len"</li>\r
+<li>p. 425     11th line from top: "followin" -> "following"</li>\r
+<li>p. 440     11th line from top: "equivalents" -> "equivalent"</li>\r
+<li>p. 441     middle of page: "LTL formula" -> "LTL formulae"</li>\r
+<li>p. 446     10th line from top: "equivalents" -> "equivalent"</li>\r
+<li>p. 450     last example in notes should be: atomic { P && qname?[ack,var] -> qname?ack,var }</li>\r
+<li>p. 452     15th line from bottom: "will included" -> "will be included"</li>\r
+<li>p. 455     5th line from top: "restrction" -> "restriction"</li>\r
+<li>p. 456     middle of page: "type main" -> "type fact"</li>\r
+<li>p. 456     12th line from bottom: "2,147,483,648" ->"2,147,483,647"</li>\r
+<li>p. 456     10th line from bottom: 13! = 6,227,020,800  (and so even 13! > 2^31-1)</li>\r
+<li>p. 464     9th line from bottom: "just and safe" -> "justified and safe" (2x)</li>\r
+<li>p. 466     1st line in EFFECT: "to the" -> "of the" </li>\r
+<li>p. 476     in EXAMPLES (2x): "b = a" -> "b = tmp"</li>\r
+<li>p. 479     7th line from top: "can are" -> "are"</li>\r
+<li>p. 496     6th line: "in in" -> "in"</li>\r
+<li>p. 498     2nd line from bottom: "coord.trail" -> "example.trail"</li>\r
+<li>p. 509     13th line from bottom: "known the" -> "known. The"</li>\r
+<li>p. 512     middle of page: "an pointer" -> "a pointer"</li>\r
+<li>p. 518     l -8, most -> must</li>\r
+<li>p. 519     l -10, -rthis -> -r, this</li>\r
+<li>p. 521     5th line from bottom: "substitions" -> "substitutions"</li>\r
+<li>p. 528     under basic options -DBFS, "reducting" -> "reducing"</li>\r
+<li>p. 532     under -DSDUMP, replace "-DCHECK" with: "-DVERBOSE or -DDEBUG"</li>\r
+<li>p. 532     under -DSVDUMP, replace "a file named svdump" with "a file with extension .svd"</li>\r
+<li>p. 541     11th line from bottom: "-a" in wrong font</li>\r
+<li>p. 543     middle of page: "two for processes" -> "three for processes"</li>\r
+<li>p. 547     Americans would put "Dijkstra" above "Dillon" in alphabetical order. Dutchmen, though, recognize the "ij" as a single letter, and place "Dijkstra" below "Doran" as shown. Dijkstra was, of course, a Dutchman...</li>\r
+<li>p. 547     Entry for Emerson: "model logic" -> "modal logic"</li>\r
+<li>p. 553     13th line from bottom: "to represents" -> "to represent"</li>\r
+<li>p. 554     10th line from top: "product" -> "products"</li>\r
+<li>p. 561     DEADLOCK DETECTION, 1st line: "is system" -> "is a system"</li>\r
+<li>p. 561     10th line from bottom: replace "invalid endstate" with "valid endstate", and replace the subsentence after the comma with: "from which we can derive the definition of an invalid endstate, matching Spin's formalization of a system deadlock. In an invalid endstate at least one process has not reached its closing curly brace or a state marked with an endstate label."</li>\r
+<li>p. 565     4th line from top: "andq, r" -> "q and r"</li>\r
+<li>p. 566     define BDD (Binary Decision Diagram) and NP (Non-deterministic Polynomial)</li>\r
+<li>p. 572     l 8, wil -> will</li>\r
+<li>p. 575     10th line from bottom should be: spin -a -m ex2</li>\r
+<li>p. 575     9th line from bottom should be: cc -DPC -DBITSTATE -DSAFETY -o pan pan.c</li>\r
+<li>p. 577     C.9., 1st line: "an little" -> "a little"</li>\r
+<li>p. 579     5th line from top: "these tool" -> "these tools"</li>\r
+</ul>\r
+</font>\r
+<hr>\r
+Statistics:\r
+The list above contains\r
+roughly 128 reported typos and goofs in the first printing of the book.\r
+There are approximately 340K words in the book, giving 1 reported defect\r
+per 2,650 words written. At and average of 10 words per sentence, this is\r
+about 4 reported defects per 1,000 sentences in the book, which is roughly\r
+on par with a reasonably good software development process of 1-10 residual\r
+defects (<em>after</em> testing) per 1,000 lines of non-comment source code written.\r
+As in software, the number of reported defects depends both on the number of\r
+latent defects <em>and</em> on the number of users/readers\r
+(i.e., unread books will have no reported typos...).\r
+<hr>\r
+Note (*) on the example used on p. 20, provided by Heikki Tauriainen.\r
+<pre>\r
+Date: Wed, 01 Feb 2006 21:10:54 +0200 (EET) \r
+From: heikki.tauriainen [atsign] tkk [dot] fi \r
+Subject: Spin book: Doran & Thomas's mutual exclusion algorithm \r
+\r
+Dear Dr. Holzmann,\r
+\r
+Keijo Heljanko and I are giving at Helsinki University of Technology\r
+a basic course on parallel and distributed systems, using Spin for\r
+examples on model checking.  To demonstrate using the tool, we\r
+considered Dekker's mutual exclusion algorithm found in your Spin\r
+book (p. 20) and the variant of the algorithm by Doran and Thomas\r
+mentioned on p. 22.\r
+\r
+According to the Spin book, Doran and Thomas's algorithm can be\r
+obtained from Dekker's algorithm by simply changing the outer do-loop\r
+of the algorithm into an if-selection, and this change is claimed to\r
+preserve the correctness of the algorithm.  This doesn't, however,\r
+seem to be the case, as the verification results using the Promela\r
+models distributed in the package\r
+<http://spinroot.com/spin/Doc/Book_extras/examples.tar.gz> were\r
+somewhat unexpected (unless, of course, the models in the package are\r
+deliberately faulty).  I'm referring to the file CH2/mutex.pml in the\r
+package.\r
+\r
+The Promela model uses a preprocessor directive (DORAN) to choose\r
+between the algorithm with the do-loop and the algorithm with the\r
+if-selection. Verifying the model with the do-loop indeed gives the\r
+expected result (no assertion violations).  Firstly, however, Spin\r
+doesn't directly accept the model of the variant of the algorithm:\r
+\r
+$ spin -DDORAN -a mutex.pml\r
+spin: line  30 "mutex.pml", Error: misplaced break statement    saw '-2'' near 'break'\r
+$\r
+\r
+After the obvious change of making the 'break' keyword at line 30\r
+apply only to the variant with the do-loop, that is, changing lines\r
+29--35 to read\r
+\r
+        :: else ->\r
+#ifdef DORAN\r
+        fi;\r
+#else\r
+                break\r
+        od;\r
+#endif\r
+\r
+and then verifying the mutual exclusion algorithm gives, however,\r
+the following (unexpected) result:\r
+\r
+$ spin -DDORAN -a mutex.pml\r
+$ gcc -o -DBFS -o pan pan.c\r
+$ ./pan\r
+pan: assertion violated (cnt==1) (at depth 9)\r
+pan: wrote mutex.pml.trail\r
+(Spin Version 4.2.6 -- 27 October 2005)\r
+Warning: Search not completed\r
+        + Using Breadth-First Search\r
+        + Partial Order Reduction\r
+\r
+Full statespace search for:\r
+        never claim             - (none specified)\r
+        assertion violations    +\r
+        cycle checks            - (disabled by -DSAFETY)\r
+        invalid end states      +\r
+\r
+State-vector 20 byte, depth reached 9, errors: 1\r
+      56 states, stored\r
+              56 nominal states (stored-atomic)\r
+      32 states, matched\r
+      88 transitions (= stored+matched)\r
+       0 atomic steps\r
+hash conflicts: 0 (resolved)\r
+\r
+2.302   memory usage (Mbyte)\r
+\r
+$ spin -DDORAN -p -t mutex.pml\r
+Starting mutex with pid 0\r
+Starting mutex with pid 1\r
+  1:    proc  1 (mutex) line  11 "mutex.pml" (state 1)  [i = _pid]\r
+  1:    proc  1 (mutex) line  12 "mutex.pml" (state 2)  [j = (1-_pid)]\r
+  2:    proc  0 (mutex) line  11 "mutex.pml" (state 1)  [i = _pid]\r
+  2:    proc  0 (mutex) line  12 "mutex.pml" (state 2)  [j = (1-_pid)]\r
+  3:    proc  1 (mutex) line  14 "mutex.pml" (state 3)  [flag[i] = 1]\r
+  4:    proc  1 (mutex) line  29 "mutex.pml" (state 12) [else]\r
+  5:    proc  1 (mutex) line  37 "mutex.pml" (state 15) [cnt = (cnt+1)]\r
+  6:    proc  0 (mutex) line  14 "mutex.pml" (state 3)  [flag[i] = 1]\r
+  7:    proc  0 (mutex) line  21 "mutex.pml" (state 4)  [(flag[j])]\r
+  8:    proc  0 (mutex) line  27 "mutex.pml" (state 9)  [else]\r
+  9:    proc  0 (mutex) line  37 "mutex.pml" (state 15) [cnt = (cnt+1)]\r
+spin: trail ends after 9 steps\r
+#processes: 2\r
+                turn = 0\r
+                flag[0] = 1\r
+                flag[1] = 1\r
+                cnt = 2\r
+  9:    proc  1 (mutex) line  38 "mutex.pml" (state 16)\r
+  9:    proc  0 (mutex) line  38 "mutex.pml" (state 16)\r
+2 processes created\r
+$\r
+\r
+Trying to find a reason for this unexpected result, I compared the\r
+model with the algorithm in Doran and Thomas's original article [1].\r
+It appears that the model in fact differs from that algorithm\r
+(repeated below from [1], Fig. 1)\r
+\r
+Process A                           Process B\r
+  1. A_needs := true;                    B_needs :=  true;\r
+  2. if B_needs then begin               if A_needs then begin\r
+  3.   if turn = 'B' then begin            if turn = 'A' then begin\r
+  4.     A_needs := false;                   B_needs := false;\r
+  5.     wait until turn = 'A';              wait until turn = 'B';\r
+  6.     A_needs := true;                    B_needs := true;\r
+  7.     end;                                end;\r
+  8.   wait until !B_needs;                wait until !A_needs;\r
+  9.   end;                                end;\r
+ 10. CRITICAL SECTION                    CRITICAL SECTION\r
+ 11. turn := 'B';                        turn := 'A';\r
+ 12. A_needs := false;                   B_needs := false;\r
+ 13. NON-CRITICAL SECTION                NON-CRITICAL SECTION\r
+\r
+In particular, the Promela model has no corresponding construct for\r
+line 8 of this algorithm, which appears to be critical to its\r
+correctness: changing the outer if-selection to read\r
+\r
+        if\r
+        :: flag[j] ->\r
+                if\r
+                :: turn == j ->\r
+                        flag[i] = false;\r
+                        !(turn == j);\r
+                        flag[i] = true\r
+                :: else\r
+                fi;\r
+                (!flag[j]);    /* needed for correctness */\r
+        :: else ->\r
+        fi;\r
+\r
+fixes the error.  However, it is not sufficient to simply\r
+replace the do-loop with an if-selection, although the wording\r
+on page 22 of the Spin book can be interpreteted to suggest\r
+otherwise (at least both I and Keijo were surprised, that's why\r
+we decided to write this report).\r
+\r
+(The example file suggests that the model is taken from the book\r
+[2] instead of directly from Doran and Thomas's original article [1].\r
+As a matter of fact, this book---at least its English translation---contains the same error.  This is probably also the\r
+reason why the model is faulty.)\r
+\r
+Best regards,\r
+Heikki Tauriainen\r
+\r
+\r
+References:\r
+\r
+[1] R. W. Doran and L. K. Thomas.  Variants of the software solution to\r
+    mutual exclusion.  Information Processing Letters 10(4--5):206--208,\r
+    1980.\r
+\r
+[2] M. Raynal.  Algorithms for mutual exclusion.  North Oxford Academic\r
+    Publishers Ltd., 1986.\r
+</pre>\r
+<hr>\r
+<a href="http://spinroot.com/spin/Doc/Book_extras/index.html">book home page</a>\r
+<br>\r
+<a href="http://spinroot.com/spin/">Spin home page</a>\r
+<hr>\r
+<font size=2>Last updated: 1 February 2006</font>\r
+</html>\r
diff --git a/trunk/verif/Spin/Doc/Book91_Ch6_add.txt b/trunk/verif/Spin/Doc/Book91_Ch6_add.txt
new file mode 100755 (executable)
index 0000000..9fcd25e
--- /dev/null
@@ -0,0 +1,183 @@
+An appendix to Chapter 6 of the book: some extra explanation on pid's
+and on temporal claims.  Updated for Spin Version 2.0 - January 1995.
+
+PROCESS IDs
+
+In Spin 2.0 and later the never claim can refer to the control state
+of any process, but not to their local variables.
+This functionality is meant to be used for building correctness assertions
+with never claims.  It should never be used for anything else.
+An example is
+       Receiver[pid]@place
+where `place' the name of a label within `proctype Receiver,' and
+`pid' is the value returned by the run statement that instantiated the
+copy of the Receiver proctype that we are interested in.
+
+There is a misleading suggestion in the book that says that you can
+usually guess the `pid's.  Wiser is to always use the explicit value
+returned by the `run()' statement that instantiated the proces.
+Processes started with the `active' prefix obtain instantiation
+numbers starting at value 1, in the order in which they appear in the
+specification.  Each process also has a local variable _pid that
+holds its own instantiation number.
+
+SPECIFYING TEMPORAL CLAIMS
+
+The body of a temporal claim is defined just like PROMELA proctype bodies.
+This means that all control flow structures, such as if-fi selections,
+do-od repetitions, and goto jumps, are allowed.
+There is, however, one important difference:
+
+       Every statement inside a temporal claim is (interpreted as) a condition.
+       A never claim should therefore never contain statements that can
+       have side-effects (assignments, communications, run-statements, etc.)
+
+Temporal claims are used to express behaviors that are considered undesirable
+or illegal.  We say that a temporal claim is `matched' if the undesirable
+behavior can be realized, and thus the claim violated.
+
+The recommended use of a temporal claim is in combination with acceptance labels.
+There are two ways to `match' a temporal claim, depending on whether the
+undesirable behavior defines a terminating or a cyclic execution sequence.
+
+o A temporal claim is matched when it terminates (reaches its closing curly brace).
+  That is, the claim can be violated if the closing curly brace of the PROMELA
+  body of the claim is reachable for at least one execution sequence.
+
+o For a cyclic execution sequence, the claim is matched only when an explicit
+  acceptance cycle exists.  The acceptance labels within temporal claims
+  are user defined, there are no defaults.  This means that in the absence of
+  acceptance labels no cyclic behavior can be matched by a temporal claim.
+  It also means that to check a cyclic temporal claim, acceptance labels should
+  only occur within the claim and not elsewhere in the PROMELA code.
+
+
+SEMANTICS
+
+The normal system behavior of a PROMELA system is defined as the
+`asynchronous product' of the behaviors of the individual processes.
+Given an arbitrary system state, its successor states are obtained
+in two steps.  In the first step all the executable (atomic) statements in the
+individual processes are identified.  In the second step, each one of these
+statements is executed.
+Each single execution produces a successor state in the asynchronous product.
+The complete system behavior is thus defined recursively and
+represents all possible interleavings of the individual process behaviors.
+Call this asynchronous product machine the `global machine'.
+
+The addition of a temporal claim defines an additional `synchronous product'
+of this global machine with the state machine that defines the temporal
+claim.  Call the latter machine the `claim machine', and call the new
+synchronous product the `labeled machine'.
+
+Every state in the labeled machine is a pair (p,q) with p a state in the global
+machine and q a state in the claim machine.  Every transition in the labeled
+machine is similarly defined by a pair (r,s) with r a transition in the global
+machine and s a transition in the claim machine.
+In other words, every transition in the `synchronous' product is a joint move
+of the global machine and the claim machine.
+(By contrast, every transition in an `asynchronous' product would correspond
+to a single transition in either the global machine or the claim machine, thus
+interleaving transitions instead of combining them.)
+
+Since all statements in the claim machine are boolean propositions, the second
+half of the transition pair (r,s) is either true or false.
+Call all transitions where this proposition is true `matching transitions'.
+In a matching transition proposition s evaluates to true in state system state r.
+Notice that the claim machine has at least one stop state E, the state
+at the closing curly brace of the claim body.
+
+The semantics of temporal claims can now be summed up as follows.
+
+o If the labeled machine contains any sequence of matching transitions only,
+  that connects its initial state with a state (p,E) for any p, the temporal
+  claim can be matched by a terminating sequence (a correctness violation).
+
+o If the labeled machine contains any cycle of matching transitions only, that
+  passes through an acceptance state, the temporal claim can be matched by a
+  cyclic sequence.
+
+
+EXAMPLES
+
+Listed below are the equivalent PROMELA definitions for the three basic
+temporal properties defined by Zohar Manna & Amir Pnueli in
+``Tools and Rules for the Practicing Verifier'' Stanford University,
+Report STAN-CS-90-1321, July 1990, 34 pgs.
+
+The following descriptions are quoted from Manna & Pnueli:
+
+       ``There are three classes of properties we [...] believe to cover
+       the majority of properties one would ever wish to verify.''
+
+       1. Invariance
+       ``An invariance property refers to an assertion p, and requires that p
+       is an invariant over all the computations of a program P, i.e. all
+       the states arising in a computation of P satisfy p.  In temporal
+       logic notation, such properties are expressed by [] p, for a state
+       formula p.''
+
+       Corresponding Temporal Claim in PROMELA:
+       never {
+               do
+               :: p
+               :: !p -> break
+               od
+       }
+
+       2. Response
+       ``A response property refers to two assertions p and q, and
+       requires that every p-state (a state satisfying p) arising in
+       a computation is eventually followed by a q-state.
+       In temporal logic notation this is written as p -> <> q.''
+
+       Corresponding Temporal Claim in PROMELA:
+       never {
+               do
+               :: true
+               :: p && !q -> break
+               od;
+       accept:
+               do
+               :: !q
+               od
+       }
+
+       Note that using (!p || q) instead of `skip' would check only the
+       first occurrence of p becoming true while q is false.
+       The above formalization checks for all occurrences, also future ones.
+       Strictly seen, therefore, the claim above uses a common interpretation
+       of the formula, requiring it to hold always, or: [] { p -> <> q }
+
+       3. Precedence
+       ``A simple precedence property refers to three assertions p, q, and r.
+       It requires that any p-state initiates a q-interval (i.e. an interval
+       all of whose states satisfy q) which, either runs to the end of the
+       computation, or is terminated by an r-state.
+       Such a property is useful to express the restriction that, following
+       a certain condition, one future event will always be preceded by
+       another future event.
+       For example, it may express the property that, from the time a certain
+       input has arrived, there will be an output before the next input.
+       Note that this does not guarantee [require] that the output will actually
+       be produced. It only guarantees [requires] that the next input (if any)
+       will be preceded by an output.  In temporal logic, this property is
+       expressed by p -> (q U r), using the unless operator (weak until) U.
+
+       Corresponding Temporal Claim in PROMELA:
+
+       never {
+               do
+               :: true         /* to match any occurrence */
+               :: p &&  q && !r -> break
+               :: p && !q && !r -> goto error
+               od;
+               do
+               ::  q && !r
+               :: !q && !r -> break
+               od;
+       error:  skip
+       }
+
+       Strictly again, this encodes: [] { p -> (q U r) }
+       To match just the first occurence, replace 'true' with (!p || r).
diff --git a/trunk/verif/Spin/Doc/Book91_Errata.txt b/trunk/verif/Spin/Doc/Book91_Errata.txt
new file mode 100755 (executable)
index 0000000..0e9703b
--- /dev/null
@@ -0,0 +1,452 @@
+Errata for `Design and Validation of Computer Protocols'
+[trivial typos not listed]
+
+CHAPTER 2, page 26 - Example of a Shorter Error Scenario
+============================================================
+
+A duplicate message can be accepted after even a single
+transmission error occurs.  E.g.:
+
+          (A)                                (B)
+           ~                                  ~
+           |                                  |
+           |    ack 'z' /-----------<---------+
+           +-----------/                      |
+accept(z)  |                                  |
+           +-----------\ ack 'a' -> err       |
+           |             \----------->--------+
+           |                                  |
+           |     nak 'z' /-----------<--------+
+           +------------/                     |
+accept(z)  |                                  |
+
+
+CHAPTER 3, page 61/62 - Revised CRC-Algorithm
+(Bits renumbered in more standard right to left order.)
+============================================================
+
+The  following  C  program,  by Don Mitchell  of  AT&T  Bell
+Laboratories,  generates a  lookup table  for  an  arbitrary
+checksum polynomial.  Input  for  the  routine  is  an octal
+number, specified as an argument, that encodes the generator
+polynomial.
+In the version of the program shown here, compliments of Ned
+W.  Rhodes,  Software  Systems Group, bits are numbered from
+zero to r-1, with bit zero corresponding to  the  right-most
+bit,  and  r  the  degree  of the generator polynomial.  (In
+Mitchell's original algorithm the bits in  the  message  and
+generator polynomial were reversed.)  The r-th bit itself is
+omitted from the code word, since  it  is  implicit  in  the
+length.   Using  this  program  takes  two  separate  steps.
+First, the program is  compiled  and  run  to  generate  the
+lookup  tables.  Then the checksum generation routine can be
+compiled, with the precalculated lookup tables in place.  On
+a UNIX system, the program is compiled as
+
+            $ cc -o crc_init crc_init.c
+
+Lookup tables for the two most popular  CRC-polynomials  can
+now be produced as follows:
+
+            $ crc_init 0100005 > crc_16.h
+            $ crc_init  010041 > crc_ccitt.h
+
+This is the text of crc_init.c:
+
+
+    main(argc, argv)
+            int argc; char *argv[];
+    {
+            unsigned long crc, poly;
+            int n, i;
+
+            sscanf(argv[1], "%lo", &poly);
+            if (poly & 0xffff0000)
+            {       fprintf(stderr, "polynomial is too large\n");
+                    exit(1);
+            }
+
+            printf("/*\n *  CRC 0%o\n */\n", poly);
+            printf("static unsigned short crc_table[256] = {\n");
+            for (n = 0; n < 256; n++)
+            {       if (n % 8 == 0) printf("    ");
+                    crc = n << 8;
+                    for (i = 0; i < 8; i++)
+                    {       if (crc & 0x8000)
+                                    crc = (crc << 1) ^ poly;
+                            else
+                                    crc <<= 1;
+                            crc &= 0xFFFF;
+                    }
+                    if (n == 255) printf("0x%04X ", crc);
+                    else          printf("0x%04X, ", crc);
+                    if (n % 8 == 7) printf("\n");
+            }
+            exit(0);
+    }
+
+The table can now be used to generate checksums:
+
+    unsigned short
+    cksum(s, n)
+            register unsigned char *s;
+            register int n;
+    {
+            register unsigned short crc=0;
+
+            while (n-- > 0)
+               crc = crc_table[(crc>>8 ^ *s++) & 0xff] ^ (crc<<8);
+
+            return crc;
+    }
+
+
+CHAPTER 4, page 81 - Typo
+============================================================
+
+old<   Taking the modulo M effect into account, this becomes:
+       valid(m) = ( 0 < p - m <= W ) || ( 0 < p - M - m <= W )
+
+new>   Taking the modulo M effect into account (p is always
+       smaller than M), this becomes:
+       valid(m) = ( 0 < p - m <= W ) || ( 0 < p + M - m <= W )
+
+ERROR, Page 83, Figure 4.14
+===========================
+
+should not "accept:i" if (a==e) is false
+
+
+CHAPTER 5, error/typos
+===========================
+
+Page 96, bottom
+
+The mutual exclusion algorithm attributed to Dekker is
+really a simplication of Dekker's algorithm that is known
+as Peterson's algorithm.
+Dekker's original solution is modeled in Promela like this:
+
+#define true   1
+#define false  0
+#define Aturn  1
+#define Bturn  0
+
+bool x, y, t;
+
+proctype A()
+{
+       do
+       :: x = true;
+               if
+               :: y == true && t == Bturn ->
+                       x = false;
+                       (t == Aturn)
+               :: y == false ->
+                       break
+               fi
+       od;
+
+       /* critical section */
+
+       t = Bturn;
+       x = false
+}
+
+proctype B()
+{
+       do
+       :: y = true;
+               if
+               :: x == true && t == Aturn ->
+                       y = false;
+                       (t == Bturn)
+               :: x == false ->
+                       break
+               fi
+       od;
+
+       /* critical section */
+
+       t = Aturn;
+       y = false
+}
+
+init { run A(); run B() }
+
+===========================
+
+Page 98, last paragraph
+
+old>   "If the receive operation tries to retrieve more parameters
+        than are available, the value of the extra parameters is undefined;
+        if it receives fewer than the number of parameters that was sent,
+        the extra information is lost."
+new>   "It is always an error if the receive operation tries to retrieve
+        a different number of parameters than the corresponding channel
+        declaration specifies."
+
+===========================
+
+Page 99, last line of "init", middle of page:
+
+old<   qname!qforb
+
+new>   qname[0]!qforb
+
+Page 100, delete last line on page:
+
+old<   byte name;      /* delete */
+
+Page 103, in the Dijkstra example:
+
+old<   chan sema = [0] of { bit };
+
+new>   chan sema = [0] of { mtype };
+
+Page 108, "init" section, top of page:
+
+old<   chan Ain  = [2] of { byte };
+       chan Bin  = [2] of { byte };
+       chan Aout = [2] of { byte };
+       chan Bout = [2] of { byte };
+
+new>   chan Ain  = [2] of { byte, byte };
+       chan Bin  = [2] of { byte, byte };
+       chan Aout = [2] of { byte, byte };
+       chan Bout = [2] of { byte, byte };
+
+===========================
+
+Page 107, last sentence of first paragraph Section 5.12:
+
+old<   discussed in Section 2.4.
+new>   discussed in Section 2.3.
+
+===========================
+
+Page 110, exercise 5-3:
+
+old<   Revise the two programs from Section 5.6
+new>   Revise the two programs from Section 5.8
+
+
+CHAPTER 6
+
+
+TYPO, page 117
+=======================
+old< chan sema[0] of {bit};
+new> chan sema = [0] of {bit};
+
+SERIOUS OMISSION, Section 6.4, page 116-117:
+=================================================
+The treatment of formalizing system invariants in a 1-statement
+monitor process is correct only if the model does not contain
+any timeout statements.
+If it does, the statements in the model that would be executed
+after a timeout expires are not checked (since assert is always
+executable, it would always be executed before the timeout expires
+under default timeout heuristics used in spin).
+there are two possible solutions:
+
+- disable the default timeout heuristics for a fully exhaustive
+  search for all possible choices of timeouts (brute force)
+  to do this, include a single line
+       #define timeout skip
+  as the first line of your model - and nothing else has to change
+
+- use a safer formalization of the system invariant, using a never claim.
+  the simples formalization is:
+       never { do :: assert(invariant) od }
+  which checks the truth of the invariant for every reachable state,
+  independent of timeouts.
+  another way would be to use the implicit matching behavior of a never
+  claim, without an explicit assertion:
+       never
+       {       do
+               ::  (invariant) /* things are fine, the invariant holds */
+               :: !(invariant) -> break        /* invariant fails - match */
+               od
+       }
+
+CLARIFICATION, page 118, Section 6.5
+====================================
+The validator SPIN does not enforce the second criterion
+for a proper endstate, i.e., the emptiness of all channels.
+It does enforce the revised first criterion from the bottom
+of page 118.
+
+TYPO, page 121 middle:
+=================================================
+
+old< never { do :: skip od -> P -> !Q }
+
+new> never { do :: skip :: break od -> P -> !Q }
+
+ADDED EXPLANATIONS (throughout page 121 and onw.):
+=================================================
+
+A terminating claim is matched, and the corresponding correctness
+property thereby violated, if and when the claim body terminates.
+
+A non-terminating claim is matched, and the corresponding
+correctness property violated, if and when an acceptance cycle
+is detected.
+
+SPECIFYING TEMPORAL CLAIMS
+
+The body of a temporal claim is defined just like  PROMELA
+proctype  bodies.   This  means that all control flow struc-
+tures, such as  if-fi selections,  do-od repetitions,  and
+goto  jumps,  are allowed.  There is, however, one important
+difference:
+
+  Every statement inside a temporal claim is  (interpreted
+  as) a boolean condition.
+
+Specifically, this means that the statements inside temporal
+claims  should  be free of side-effects.  For reference, the
+PROMELA  statements  with  side-effects  are:   assignments,
+assertions,   sends,   receives,  and    printf  statements.
+
+Temporal  claims  are  used  to  express  system
+behaviors  that  are  considered undesirable or illegal.  We
+say that a temporal claim  is  matched  if  the  undesirable
+behavior can be realized, and thus our correctness claim can
+be violated.  The most useful application of temporal claims
+is  in  combination  with acceptance labels.  There are then
+two ways to match a temporal claim, depending on whether the
+undesirable behavior defines terminating or cyclic execution
+sequences.
+
+     For a terminating execution sequence, a temporal  claim
+     is  matched  only  when  it  can terminate (reaches the
+     closing curly brace) That is, the claim can be violated
+     if  the  closing curly brace of the PROMELA body of the
+     claim is reachable.
+
+     For a cyclic execution sequence, the claim  is  matched
+     only  when  an  explicit  acceptance cycle exists.  The
+     acceptance  labels  within  temporal  claims  are  user
+     defined, there are no defaults.  This means that in the
+     absence of acceptance labels no cyclic behavior can  be
+     matched  by  a  temporal  claim.  It also means that to
+     check a cyclic temporal claim, acceptance labels should
+     only  occur  within  the claim and not elsewhere in the
+     PROMELA code.
+
+ERROR, page 124, top
+=======================
+old<   :: len(receiver) == 0
+
+new>   :: skip /* allow any time delay */
+
+ERROR, page 125, top
+=======================
+the claim can of course always be violated (== matched),
+whether timeout is redefined or not.
+
+CHAPTER 7
+
+ERROR, page 139, bottom
+=======================
+old< Pr(Burst >= 17) = 0.08  . e ^ { -0.08  . 17 } = 0.007
+
+new> Pr(Burst >= 17) = 0.009 . e ^ { -0.009 . 17 } = 0.007
+
+ERROR, page 156, middle
+=======================
+old<                   flow_to_dll[n]!sync_ack,0
+new>                   flow_to_dll[n]!sync_ack,m
+                       (and move the new line up to precede: "m=0;")
+
+old<                   flow_to_ses[n]!sync_ack,0
+new>                   flow_to_ses[n]!sync_ack,m
+
+old<   To avoid circularity, the synchronization messages
+       do not carry sequence numbers.
+new>   The sync_ack message echos the session number of the
+       sync message.
+
+ERROR, page 156, bottom
+=======================
+old<                   ||   (0<p-m-M && p-m-M<=W));
+new>                   ||   (0<p-m+M && p-m+M<=W));
+
+
+CHAPTER 11
+
+ERROR, page 224, algorithm "analyze()"
+======================================
+old<   q = element from W;
+new>   q = last element from W;
+
+further down:
+=============
+old<   If states are stored in set W in first-in first-out order,
+       the algorithm performs a breadth-first search of the state space tree.
+new>   If states are stored in set W in first-in last-out (i.e., stack)
+       order, the algorithm performs a depth-first search of the state space tree.
+
+further down:
+=============
+old<   If states are stored in first-in last-out (i.e., stack)
+       < order, this changes into a depth-first search.
+
+new>   If states are stored and removed in first-in first-out
+       order, this changes into a breadth-first search
+       (element q must be deleted upon retrieval from set W in
+       this type of algorithm).
+
+Page 227, top
+=============
+old<   q = element from W;
+new>   q = last element from W;
+
+Page 237, bottom
+================
+old<   after removing states 4, 3, and 2 from the stack...
+new>   after removing states 4, and 3 from the stack...
+
+CHAPTER 13
+
+Page 315, 2nd para in 13.9
+==========================
+The first two sentences of this paragraph are incorrect.
+At the low end, just 1 state would be stored in the hash-array,
+taking up 2 bits of storage out of N available bits; at the
+high end, all N bits would be set at the end of the run, and 
+(allowing overlaps) we cannot have seen more than N states.
+This leads to a possible range of values for the hash factor
+of N/2 >= hf >= 1
+For full state space storage the hash factor is meaningless.
+
+CHAPTER 14
+
+Page 331, lines 86, 88, and 94
+==============================
+See the corrections described for CHAPTER 7, page 156.
+
+APPENDIX C
+==============================
+
+Page 387-388
+The syntax of remote referencing has changed in SPIN Version 2.0.
+Remote referencing to local variables is no longer allowed
+(page 387, 5th line from below).
+The syntax for referencing the state of another process has changed
+from (page 388, 3rd line):
+       same[2]:here
+to:
+       same[2]@here
+
+/===================================================================\
+| Final Erratum:                                                    |
+|                                                                   |
+| This book is now replaced with the new, up to date description of |
+| the current version of Spin (per 9/2003):                         |
+|      http://spinroot.com/spin/Doc/Book_extras/index.html         |
+\===================================================================/
+
+=end errata=
diff --git a/trunk/verif/Spin/Doc/Book91_answers.txt b/trunk/verif/Spin/Doc/Book91_answers.txt
new file mode 100755 (executable)
index 0000000..b70deb3
--- /dev/null
@@ -0,0 +1,612 @@
+
+
+Answers to selected exercises from
+'Design and Validation of Computer Protocols'
+=============================================
+
+1.1
+Assuming that torches in the two groups would be
+raised and lowered simultaneously,
+the code for the first character in the first group
+could have clashed with the pre-defined start of text code.
+
+If torches are not raised simultaneously it is conceivable
+that group numbers could be paired with the wrong character numbers.
+
+A well-trained transmitter might also overestimate the receiver's
+ability to translate the codes on the fly.
+as is still true today: receiving is a more time consuming task
+than transmitting.
+
+1.2
+Assuming that a torch code is displayed for a minimum of 30 seconds,
+the torch telegraph transmits a choice of 1 out of 25 (between 4
+and 5 bits of information), giving a speed of roughly 0.15 bits/sec.
+Chappe's telegraph transmitted a choice of 1 out of 128 every 15 to 20
+seconds, giving a transmission speed of roughly 0.5 bits/sec.
+On Polybius' telegraph the 15 characters of the message
+``protocol failure'' would take 15x30 seconds or 7.5 minutes to transmit...
+(Note that a code for the space was not available.)
+On Chappe's system the 16 characters (space included) would be
+transmitted in 4 minutes, assuming that no predefined code
+was assigned to either the word `protocol' or the word `failure.'
+(As far as we know, there wasn't.)
+
+1.3
+Removing the redundancy in messages increases the chance that a
+single transmission error would make a large part of a message
+inrecognizable.  It could cause a lot of extra traffic from receiver
+back to sender, asking for retransmissions, and additional transmissions
+of messages.  The same tradeoff is still valid on today's communication
+channels (see Chapter 3).
+
+1.4
+The signalman at A had to make sure that not one but two
+trains would leave the tunnel, before he admitted the third.
+The two trains could reach signalman B in approximately 2 minutes.
+At 25 symbols per minute, that would allow the two signalmen
+to exchange roughly 50 characters of text.
+A could have signaled: "two trains now in tunnel - how many left?"
+for a total of 42 characters.
+Assuming that B would have answered eventually "one train left,"
+that would still leave A puzzling if B had really understood his
+message, and if so, where the second train could possibly be.
+Considering also that signalman A had been on duty for almost
+18 hours when the accident occured, it is not entirely certain
+that he could have succesfully resolved the protocol problem.
+Note that he still would have had to `invent' part of the protocol
+for resolving the problem in real-time.
+
+1.5
+Replace the message `train in tunnel' with `increment the number of
+trains in the tunnel by one.'  Similarly, replace the message `tunnel
+is clear' by `decrement the number of trains in the tunnel by one.'
+The message `is tunnel clear' becomes `how many trains are in the
+tunnel?' with the possible responses spelled out with numerals 0 to 9.
+Either signalman can increment or decrement the number.
+The rule of the tunnel is invariantly that the number of trains in
+the tunnel is either zero or one, and only one signalman may transmit
+at a time. (To resolve conflicts on access to the transmission line,
+one could simply give one of the signalmen a fixed priority.)
+
+1.6
+A livelock would result.  Assuming that the semaphore operators would
+quickly enough recognize the livelock, it is still an open question
+what they would (should) do to recover properly from such an occurence.
+
+1.7
+One possible scenario, observed by Jon Bentley in real life, is that
+two connections are made, and both parties are charged for the call.
+Clearly, a dream come true for the telephone companies.
+
+2.1
+Service - the simplex transfer of arbitrary messages from a designated
+sender to a designated receiver.
+
+Assumptions about the environment - sufficient visibility and small enough
+distance to make and accurate detection (and counting) of torches possible
+for both sender and receiver.  There seems to be an implicit assumption of
+an error-free channel.  There is also the implicit assumption that the
+receiver will always be able to keep up with the sender and will not get
+out of sync with the symbols that have to be decoded.
+
+Vocabulary - 24 characters from the Greek alphabet, plus two control messages
+(the start of text message and its acknowledgement).
+
+Encoding - each character, and each control message, is encoded into two
+numbers, both between 1 and 5.
+Since there are 26 distinct messages and only 5x5=25 distinct codes, some
+ambiguity is unavoidable.
+
+Procedure rules - minimal.  Apparently there was only a single handshake
+at the start of the transmission.  All other interactions (end of transmission,
+error recovery, flow control) were undefined and would have had to be
+improvised in the field.  There is also no resolution of a potential conflict
+at the start of transmission (assuming that both parties could decide to
+start sending at the same time).
+
+2.2
+The procedure rules can include a poll message once per
+complete page - interrogating the printer about it's status
+(confirming that it is online and confirming that it
+is not out of paper - both conditions that can change from
+one page to the next).  Note that the procedure rules must
+also guarantee that no more than one user can use the printer
+at a time.
+
+2.3
+Service - establishing a voice connection between two subscribers
+of a phone system. (Let's conveniently ignore multi-party connections,
+or faxes and modems.)
+
+Assumptions about environment - the phone system is infinitely
+available and error-free (sic).
+
+Vocabulary - off-hook, on-hook, dial 0 ... dial 9 (ignore star and sharp).
+Dial-tone, busy-tone, ring-tone.  All messages listed here are control
+messages - the `data' of the protocol is encoded in the voice message.
+(For completeness then we could list `voice' as a separate message in the
+vocabulary, without attempting to formalize it's `encoding.')
+
+Encoding - lifting the receiver, lowering the receiver,
+pushing one of 10 labeled buttons.
+
+Informal procedure rules -  Go off-hook, if no dial-tone is returned
+go on-hook and repeat a random amount of time later.
+If there is a dial-tone, push the sequence of buttons that identify the
+required destination to the phone system.
+If a busy-tone is returned in this interval, go on-hook, wait a random
+amount of time, and repeat from the start.
+If a ring-tone is returned - the call has been established - wait a
+random amount of time, go on-hook.
+
+Note that the random wait period after a busy signal makes it less likely
+that a `Lovers' Paradox' can be created (cf. Exercise 1.7).
+To be complete, the phone systems behavior should also be listed.
+Be warned that the latter is not a trivial exercise....
+
+2.4
+The revised version is the famous alternating bit protocol, see Chapter 4.
+
+2.5
+The receiver can then determine where a message (should) end by
+counting the number of bytes it receives, following the header.
+It does not have to scan for a pre-defined message terminator.
+
+2.6
+For isntance, a character stuffed protocol always transmits an integral
+number of bytes.  A bit stuffed protocol carries slightly less overhead.
+
+2.7
+See Bertsekas and Gallager, [1987, p. 78-79].
+
+2.8
+More detailed sample assignments for software projects such as
+this one are available from the author (email to gerard@research.att.com).
+
+3.1
+The code rate is 0.2.  Protection against bursts is limited
+to errors affecting maximally 2 out of the 5 bytes.
+At 56 Kbits/sec that means bursts smaller than 0.28 msec.
+
+3.3
+Does the crc need to be protected by a crc?
+
+3.4
+In many cases English sentences are redundant enough that
+forward error correction is possible.  Any real conversation,
+though, contains many examples of feedback error correction
+to resolve ambiguities.
+To stick with the example - if the sentence ``the dog run'' is
+received, the original version (i.e., one or more dogs) cannot be
+determined without feedback error control.
+
+3.5
+(a) - the checksum is 6 bits wide.
+(b) - the original data is equal to the first n-6 bits of the code word
+(6 bits in this case).
+(c) - there were no transmission errors other than possible multiples
+of the generator polynomial itself.
+
+3.6
+The standard example is that of the voyager space craft near
+the planet Jupiter receiving a course adjustment from earth.
+A retransmission of the message would mean hours delay and invalidate
+the original commands.
+If the return channel has a high probability of error (e.g., a low
+power transmitter on board the spacecraft, sending out a very weak
+signal back to earth), the chances that a retransmission request would
+reach the earth intact may also be unacceptably low.
+
+3.8
+It is impossible to reduce a non-zero error rate to zero.
+The probability of error can be brought arbitrarily close to zero,
+at the expense of transmission speed, but it cannot reach zero.
+The scheme suggested would violate this principle and therefore
+should be placed in the same category as perpetuum mobiles and time-travel.
+
+3.9
+Fletcher's algorithm can be classified as a systematic block code.
+
+4.2
+The alternating bit protocol does not protect against
+duplication errors or reordering errors.
+Duplication errors persist (duplicate messages do not dissapear
+but generate duplicate acks etc, for the duration of the session.)
+Reordering can cause erroneous data to be accepted.
+
+4.5
+Too short a timeout creates duplicate messages.
+The duplicates lower the throughput for the remainder of the session.
+Too long a timeout increases idle-time and lowers the
+throughput.
+
+4.6
+Ignore duplicate acks.
+
+4.8
+See Bertsekas and Gallager [1987, pp. 28-29].
+
+4.9
+In at least one case (when the receiver is one full window of
+messages behind the sender) there is a confusion case where
+the receiver cannot tell if an incoming message is a repeat
+from W messages back, or a new message.
+
+4.10
+Store the data in buffer[n%W] where W is window size.
+
+4.11
+Use time-stamps and restrict the maximum life time of
+a message.  Note however that time-stamps are just another
+flavor of sequence numbers and they would have to be selected
+from a sufficiently large window.
+For 32 bit sequence numbers one message transmission
+per micro-second would recycle the number in 71 minutes.
+For 64 bit sequence numbers, the number recycles
+at the same transmission speed in 500,000 years.
+
+4.12
+Alpha controls the rate of adaption to changes in
+network performance.
+Beta controls the allowed variance in response time.
+(It estimates the load variance of the remote host.)
+
+4.13
+Most importantly, all assumptions about the environment,
+specifically of the tranmission channel used, are missing completely.
+
+4.14
+The message could be received again and cause a duplicate acceptance.
+
+5.1
+An assignment is always executable.  The variable b would be set
+to the value 0.
+
+5.2
+If the receive is executable on the first attempt to execute
+the statement, the message would be received, and the condition
+would be false (since the `executability' value of the receive is
+non-zero).  The statement would block, and would be repeated.
+If the receive is (finally) non-executable, the receive fails,
+but the condition becomes true and executable.
+For all clarity: this is not valid Promela syntax.  In Promela
+the rule is that the evaluation of a condition must always be
+completely side-effect free.
+
+5.3
+
+/***** Factorial - without channels *****/
+
+int par[16];
+int done[16];
+int depth;
+
+proctype fact()
+{      int r, n, m;
+
+       m = depth;
+       n = par[m];
+       if
+       :: (n <= 1) -> r = 1
+       :: (n >= 2) ->
+               depth = m + 1;
+                       par[m+1] = n-1;
+                       run fact();
+                       done[m+1];
+                       r = par[m+1];
+               depth = m;
+               r = r*n
+       fi;
+       par[m] = r;
+       printf("Value: %d\n", par[m]);
+       done[m] = 1
+}
+
+init
+{      depth = 0;
+       par[0] = 12;
+       run fact();
+       done[0];
+       printf("value: %d\n", par[0])
+       /* factorial of 12: 12*11*10....*2*1 = 479001600 */
+}
+
+/***** Ackermann's function *****/
+
+short  ans[100];
+short done[100];       /* synchronization */
+
+proctype ack(short a, b, c)
+{
+       if
+       :: (a == 0) ->
+               ans[c] = b+1
+       :: (a != 0) ->
+               done[c+1] = 0;
+               if
+               :: (b == 0) ->
+                       run ack(a-1, 1, c+1)
+               :: (b != 0) ->
+                       run ack(a, b-1, c+1);
+                       done[c+1];      /* wait */
+                       done[c+1] = 0;
+                       run ack(a-1, ans[c+1], c+1)
+               fi;
+               done[c+1];      /* wait */
+               ans[c] = ans[c+1]
+       fi;
+       done[c] = 1
+}
+init
+{
+       run ack(3, 3, 0);
+       done[0];        /* wait */
+       printf("ack(3,3) = %d\n", ans[0])
+}
+
+5.10
+
+Here, as an inspiration, is another sort program, performing
+a tree-sort.
+
+/**** Tree sorter ****/
+
+mtype = { data, eof };
+
+proctype seed(chan in)
+{      byte num, nr;
+
+       do
+       :: (num < 250) -> num = num + 5
+       :: (num >   3) -> num = num - 3
+       :: in!data,num
+       :: (num > 200) -> in!eof,0 -> break
+       od
+}
+
+init {
+       chan in[1] of { byte, byte };
+       chan rgt [1] of { byte, byte };
+       byte n;
+
+       run seed(in);
+       in?data,n;
+       run node(n, rgt, in);
+       do
+       :: rgt?eof,0 -> printf("\n"); break
+       :: rgt?data,n -> printf("%d, ", n)
+       od
+       
+}
+
+proctype node(byte hold; chan up, down)
+{      chan lft [1] of { byte, byte };
+       chan rgt [1] of { byte, byte };
+       chan ret [1] of { byte, byte };
+       byte n; bit havergt, havelft;
+
+       do
+       :: down?data,n ->
+               if
+               :: (n >  hold) ->
+                       if
+                       :: ( havelft) -> lft!data,n
+                       :: (!havelft) -> havelft=1;
+                               run node(n, ret, lft)
+                       fi
+               :: (n <= hold) ->
+                       if
+                       :: ( havergt) -> rgt!data,n
+                       :: (!havergt) -> havergt=1;
+                               run node(n, ret, rgt)
+                       fi
+               fi
+       :: down?eof,0 -> break
+       od;
+       if
+       :: (!havergt) -> skip
+       :: ( havergt) -> rgt!eof,0;
+               do
+               :: ret?data,n -> up!data,n
+               :: ret?eof,0 -> break
+               od
+       fi;
+       up!data,hold;
+       if
+       :: (!havelft) -> skip
+       :: ( havelft) -> lft!eof,0;
+               do
+               :: ret?data,n -> up!data,n
+               :: ret?eof,0 -> break
+               od
+       fi;
+       up!eof,0
+}
+
+5.13
+Promela is a validation modeling language, not an implementation language.
+Why does a civil engineer not use steel beams in wooden bridge models?
+
+6.1
+The assertion can be placed inside the critical section.
+The simplest way is as follows (rewritten with some features
+from the more recent versions of Spin):
+
+       mtype = { p, v }
+       
+       chan sema[0] of { mtype };
+       byte cnt;
+       
+       active proctype dijkstra()      /* 1 semaphore process */
+       {       do
+               :: sema!p -> sema?v
+               od
+       }
+       active [3] proctype user()      /* 3 user processes */
+       {
+               sema?p;
+               cnt++;
+               assert (cnt == 0 || cnt == 1);  /* critical section */
+               cnt--;
+               sem!v
+               skip   /* non-critical section */
+       }
+
+6.2
+To check the truth of the invariant
+for every reachable state, one can write simply:
+
+       never { do :: assert(invariant) od }
+
+Or to match an invalid behavior by reaching the
+end of the never claim, without assertions:
+
+       never
+       {       do
+               ::  (invariant) /* things are fine, the invariant holds */
+               :: !(invariant) -> break        /* invariant fails - match */
+               od
+       }
+
+Note that semi-colons (or arrows) in never claims match system transitions,
+(i.e., each transition in the system must be matched by a move in the
+never claim;  the claim does not move independently).
+
+6.5
+Using accept labels, for instance:
+
+       proctype A()
+       {       do
+               :: x = true;
+                       t = Bturn;
+                       (y == false || t == Aturn);
+                       ain = true;
+       CS:             skip;   /* the critical section */
+                       ain = false;
+                       x = false
+               od
+       }
+       ... and simularly for proctype B()
+
+       never {
+               do
+               :: skip         /* allow arbitrary initial execution */
+               :: !A[1]@CS -> goto accept1
+               :: !B[2]@CS -> goto accept2
+               od;
+       accept1:
+               do :: !A[1]@CS od       /* process 1 denied access forever */
+       accept2:
+               do :: !B[2]@CS od       /* process 2 denied access forever */
+       }
+
+
+6.6.a
+       never {
+               do
+               :: skip /* after an arbitrary number of steps */
+               :: p -> break
+               od;
+       accept:
+               do
+               :: p    /* can only match if p remains true forever */
+               od
+       }
+
+6.6.b
+For instance:
+       never {
+               do
+               :: assert(q || p)       /* "!q implies p" */
+               od
+       }
+
+6.6.c
+       never {    /* <> (p U q) */
+               do
+               :: skip /* after an arbitrary number of steps */
+               :: p -> break   /* eventually */
+               od;
+               do
+               :: p            /* p remains true */
+               :: q -> break   /* at least until q becomes true */
+               od
+               /* invalid behavior is matched if we get here */
+       }
+
+The translation has been automated, and is standard in Spin version 2.7
+and later (Spin option -f).
+
+6.7
+A research problem -- there are no easy answers.
+
+6.8
+       assert(0)
+is an immediate violation in both finite or infinite execution sequences,
+and is a safety property.
+
+       accept: do :: skip od
+
+is only a violation for an infinite execution sequence, and is a liveness
+property (i.e., requires a nested depth-first search for acceptance
+cycles). The safety property can be proven more effieciently.
+Other than this, the two properties are equivalent;
+
+7.1
+Layers 3 to 5 and layer 7.
+
+7.2
+At the sender: first checksumming, then byte stuffing and framing.
+At the receiver: first unstuffing and de-framing, then checksum
+verification.
+
+7.3
+Rate control is placed at the layer that handles the units it
+refers too (for bit rates, it is the physical layer - for packets
+it would be the layer that produces packets, etc.).
+Dynamic flow control belongs in the flow control module.
+
+7.13
+The one-bit solution will no longer work.
+
+8.1
+The dash is used as a don't care symbol - any valid symbol
+could replace it without changing the validity of the specification.
+The epsilon is a null-element, i.e. it represents the absence
+of a symbol (the empty set).
+
+8.7
+No, the run and chan operators are defined to be unexecutable
+when an (implementation dependent) bound is reached.
+
+9.2
+No.
+
+9.5
+More states, up to a predefined bound only.  Fewer states, yes.
+
+9.6
+No, the IUT could be arbitrarily large.
+
+9.8
+It can no longer detect transfer errors.
+
+10.2
+The computational complexity will make an interactive
+solution impossible for all but the simplest
+applications.
+
+11.3
+Missing from the program text is that variable j is
+initialized to 1 minus the value of i.
+
+12.1
+Note that the number of states to be searched by a validator on
+such a protocol would multiply by the range of the time count...
+
+13.1
+If done right, the changes will be minimal (say 10 to 20 lines
+of source).
+The memory requirements will very quickly make validations
+effectively impossible.
diff --git a/trunk/verif/Spin/Doc/Book91_samples_bundle b/trunk/verif/Spin/Doc/Book91_samples_bundle
new file mode 100755 (executable)
index 0000000..b039b20
--- /dev/null
@@ -0,0 +1,1769 @@
+# To unbundle, sh this file
+echo README 1>&2
+sed 's/.//' >README <<'//GO.SYSIN DD README'
+-Readme
+-------
+-The files in this set contain the text of examples
+-used in the Design and Validation of Computer
+-Protocols book.  The name of each file corresponds to the
+-page number in the book where the example appears in its
+-most useful version.  The overview below gives a short
+-descriptive phrase for each file.
+-
+-Description           Page Nr = Filename
+------------             ------------------
+-hello world   =       p95.1
+-tiny examples =       p94 p95.2 p96.1 p97.1 p97.2 p101 p102 p104.1
+-useful demos  =       p99 p104.2 p105.2 p116 p248
+-mutual excl.  =       p96.2 p105.1 p117 p320
+-Lynch's prot. =       p107 p312
+-alternatin bit        =       p123
+-chappe's prot.        =       p319
+-
+-Large runs
+-----------
+-ackerman's fct        =       p108    # read info at start of the file
+-
+-Pftp Protocol
+--------------
+-upper tester  =       p325.test       # not runnable
+-flow control l.       =       p329 p330
+-session layer =       p337.pftp.ses p342.pftp.ses1 p347.pftp.ses5
+-all pftp      =       App.F.pftp - plus 8 include files
+-
+-See also the single file version of pftp in: Test/pftp
+-
+-General
+--------
+-Use these examples for inspiration, and to get quickly
+-acquainted with the language and the Spin software.
+-All examples - except p123 - can be used with both version
+-1 and version 2 of SPIN. (p123 was modifed for versoin 2.0
+-to use the new syntax for remote referencing).
+-If you repeat the runs that are listed in the book for
+-these examples, you should expect to get roughly the same
+-numbers in the result - although in some cases there may
+-be small differences that are due to changes in bookkeeping.
+-
+-For instance, for p329, the book (Spin V1.0) says
+-on pg. 332, using a BITSTATE run, that there are:
+-      90845 + 317134 + 182425 states (stored + linked + matched)
+-Spin V2.0 reports the numbers:
+-      90837 + 317122 + 182421 states (stored + atomic + matched)
+-and when compiled for partial order reduction (-DREDUCE):
+-      74016 + 203616 + 104008 states (stored + atomic + matched)
+-
+-If you repeat a BITSTATE run, of course, by the nature of the
+-machine dependent effect of hashing, you may get different
+-coverage and hash-factors for larger runs.  The implementation
+-of the hash functions has also been improved in version 2.0,
+-so the numbers you see will likely differ. The numbers, though,
+-should still be in the same range as those reported in the book.
+-
+-The last set of file (prefixed App.F) is included for completeness.
+-As explained in the book: don't expect to be able to do an
+-exhaustive verification for this specification as listed.
+-In chapter 14 it is illustrated how the spec can be broken up
+-into smaller portions that are more easily verified.
+-
+-Some Small Experiments
+------------------------
+-Try:
+-      spin p95.1              # small simulation run
+-
+-      spin -s p108            # bigger simulation run, track send stmnts
+-
+-      spin -a p312            # lynch's protocol - generate verifier
+-      cc -o pan pan.c         # compile it for exhaustive verification
+-      pan                     # prove correctness of assertions etc.
+-      spin -t -r -s p312      # display the error trace
+-
+-now edit p312 to change all three channel declarations in init
+-to look like: ``chan AtoB = [1] of { mtype byte }''
+-and repeat the above four steps.
+-note the improvement in the trace.
+-
+-      spin -a p123            # alternating bit protocol - generate verifier
+-      cc -o pan pan.c         # compile it for exhaustive verification
+-      pan -a                  # check violations of the never claim
+-      spin -t -r -s p123      # display the error trace
+-
+-for more intuitive use of all the above options: try using the
+-graphical interface xspin, and repeat the experiments.
+//GO.SYSIN DD README
+echo App.F.datalink 1>&2
+sed 's/.//' >App.F.datalink <<'//GO.SYSIN DD App.F.datalink'
+-/*
+- * Datalink Layer Validation Model
+- */
+-
+-proctype data_link()
+-{     byte type, seq;
+-
+-end:    do
+-      :: flow_to_dll[0]?type,seq ->
+-              if
+-              :: dll_to_flow[1]!type,seq
+-              :: skip /* lose message */
+-              fi
+-      :: flow_to_dll[1]?type,seq ->
+-              if
+-              :: dll_to_flow[0]!type,seq
+-              :: skip /* lose message */
+-              fi
+-      od
+-}
+//GO.SYSIN DD App.F.datalink
+echo App.F.defines 1>&2
+sed 's/.//' >App.F.defines <<'//GO.SYSIN DD App.F.defines'
+-/*
+- * Global Definitions
+- */
+-
+-#define LOSS          0       /* message loss   */
+-#define DUPS          0       /* duplicate msgs */
+-#define QSZ           2       /* queue size     */
+-
+-mtype = {
+-      red, white, blue,
+-      abort, accept, ack, sync_ack, close, connect,
+-      create, data, eof, open, reject, sync, transfer,
+-      FATAL, NON_FATAL, COMPLETE
+-      }
+-
+-chan use_to_pres[2] = [QSZ] of { byte };
+-chan pres_to_use[2] = [QSZ] of { byte };
+-chan pres_to_ses[2] = [QSZ] of { byte };
+-chan ses_to_pres[2] = [QSZ] of { byte, byte };
+-chan ses_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_ses[2] = [QSZ] of { byte, byte };
+-chan dll_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_dll[2] = [QSZ] of { byte, byte };
+-chan ses_to_fsrv[2] = [0] of { byte };
+-chan fsrv_to_ses[2] = [0] of { byte };
+//GO.SYSIN DD App.F.defines
+echo App.F.flow_cl 1>&2
+sed 's/.//' >App.F.flow_cl <<'//GO.SYSIN DD App.F.flow_cl'
+-/*
+- * Flow Control Layer Validation Model
+- */
+-
+-#define true  1
+-#define false 0
+-
+-#define M     4       /* range sequence numbers   */
+-#define W     2       /* window size: M/2         */
+-
+-proctype fc(bit n)
+-{     bool    busy[M];        /* outstanding messages    */
+-      byte    q;              /* seq# oldest unacked msg */
+-      byte    m;              /* seq# last msg received  */
+-      byte    s;              /* seq# next msg to send   */
+-      byte    window;         /* nr of outstanding msgs  */
+-      byte    type;           /* msg type                */
+-      bit     received[M];    /* receiver housekeeping   */
+-      bit     x;              /* scratch variable        */
+-      byte    p;              /* seq# of last msg acked  */
+-      byte    I_buf[M], O_buf[M];     /* message buffers */
+-
+-      /* sender part */
+-end:  do
+-      :: atomic {
+-         (window < W  && len(ses_to_flow[n]) >  0
+-                      && len(flow_to_dll[n]) < QSZ) ->
+-                      ses_to_flow[n]?type,x;
+-                      window = window + 1;
+-                      busy[s] = true;
+-                      O_buf[s] = type;
+-                      flow_to_dll[n]!type,s;
+-                      if
+-                      :: (type != sync) ->
+-                              s = (s+1)%M
+-                      :: (type == sync) ->
+-                              window = 0;
+-                              s = M;
+-                              do
+-                              :: (s > 0) ->
+-                                      s = s-1;
+-                                      busy[s] = false
+-                              :: (s == 0) ->
+-                                      break
+-                              od
+-                      fi
+-              }
+-      :: atomic {
+-              (window > 0 && busy[q] == false) ->
+-              window = window - 1;
+-              q = (q+1)%M
+-         }
+-#if DUPS
+-      :: atomic {
+-              (len(flow_to_dll[n]) < QSZ
+-               && window > 0 && busy[q] == true) ->
+-              flow_to_dll[n]! O_buf[q],q
+-         }
+-#endif
+-      :: atomic {
+-              (timeout && len(flow_to_dll[n]) < QSZ
+-               && window > 0 && busy[q] == true) ->
+-              flow_to_dll[n]! O_buf[q],q
+-         }
+-
+-      /* receiver part */
+-#if LOSS
+-      :: dll_to_flow[n]?type,m /* lose any message */
+-#endif
+-      :: dll_to_flow[n]?type,m ->
+-              if
+-              :: atomic {
+-                      (type == ack) ->
+-                      busy[m] = false
+-                 }
+-              :: atomic {
+-                      (type == sync) ->
+-                      flow_to_dll[n]!sync_ack,m;
+-                      m = 0;
+-                      do
+-                      :: (m < M) ->
+-                              received[m] = 0;
+-                              m = m+1
+-                      :: (m == M) ->
+-                              break
+-                      od
+-                 }
+-              :: (type == sync_ack) ->
+-                      flow_to_ses[n]!sync_ack,m
+-              :: (type != ack && type != sync && type != sync_ack)->
+-                      if
+-                      :: atomic {
+-                              (received[m] == true) ->
+-                                      x = ((0<p-m   && p-m<=W)
+-                                      ||   (0<p-m+M && p-m+M<=W)) };
+-                                      if
+-                                      :: (x) -> flow_to_dll[n]!ack,m
+-                                      :: (!x) /* else skip */
+-                                      fi
+-                      :: atomic {
+-                              (received[m] == false) ->
+-                                      I_buf[m] = type;
+-                                      received[m] = true;
+-                                      received[(m-W+M)%M] = false
+-                       }
+-                      fi
+-              fi
+-      :: (received[p] == true && len(flow_to_ses[n])<QSZ
+-                              && len(flow_to_dll[n])<QSZ) ->
+-              flow_to_ses[n]!I_buf[p],0;
+-              flow_to_dll[n]!ack,p;
+-              p = (p+1)%M
+-      od
+-}
+//GO.SYSIN DD App.F.flow_cl
+echo App.F.fserver 1>&2
+sed 's/.//' >App.F.fserver <<'//GO.SYSIN DD App.F.fserver'
+-/*
+- * File Server Validation Model
+- */
+-
+-proctype fserver(bit n)
+-{
+-end:  do
+-      :: ses_to_fsrv[n]?create ->     /* incoming */
+-              if
+-              :: fsrv_to_ses[n]!reject
+-              :: fsrv_to_ses[n]!accept ->
+-                      do
+-                      :: ses_to_fsrv[n]?data
+-                      :: ses_to_fsrv[n]?eof -> break
+-                      :: ses_to_fsrv[n]?close -> break
+-                      od
+-              fi
+-      :: ses_to_fsrv[n]?open ->               /* outgoing */
+-              if
+-              :: fsrv_to_ses[n]!reject
+-              :: fsrv_to_ses[n]!accept ->
+-                      do
+-                      :: fsrv_to_ses[n]!data -> progress: skip
+-                      :: ses_to_fsrv[n]?close -> break
+-                      :: fsrv_to_ses[n]!eof -> break
+-                      od
+-              fi
+-      od
+-}
+//GO.SYSIN DD App.F.fserver
+echo App.F.pftp 1>&2
+sed 's/.//' >App.F.pftp <<'//GO.SYSIN DD App.F.pftp'
+-/*
+- * PROMELA Validation Model - startup script
+- */
+-
+-#include "App.F.defines"
+-#include "App.F.user"
+-#include "App.F.present"
+-#include "App.F.session"
+-#include "App.F.fserver"
+-#include "App.F.flow_cl"
+-#include "App.F.datalink"
+-
+-init
+-{     atomic {
+-        run userprc(0); run userprc(1);
+-        run present(0); run present(1);
+-        run session(0); run session(1);
+-        run fserver(0); run fserver(1);
+-        run fc(0);      run fc(1);
+-        run data_link()
+-      }
+-}
+//GO.SYSIN DD App.F.pftp
+echo App.F.present 1>&2
+sed 's/.//' >App.F.present <<'//GO.SYSIN DD App.F.present'
+-/*
+- * Presentation Layer Validation Model
+- */
+-
+-proctype present(bit n)
+-{     byte status, uabort;
+-
+-endIDLE:
+-      do
+-      :: use_to_pres[n]?transfer ->
+-              uabort = 0;
+-              break
+-      :: use_to_pres[n]?abort ->
+-              skip
+-      od;
+-
+-TRANSFER:
+-      pres_to_ses[n]!transfer;
+-      do
+-      :: use_to_pres[n]?abort ->
+-              if
+-              :: (!uabort) ->
+-                      uabort = 1;
+-                      pres_to_ses[n]!abort
+-              :: (uabort) ->
+-                      assert(1+1!=2)
+-              fi
+-      :: ses_to_pres[n]?accept,0 ->
+-              goto DONE
+-      :: ses_to_pres[n]?reject(status) ->
+-              if
+-              :: (status == FATAL || uabort) ->
+-                      goto FAIL
+-              :: (status == NON_FATAL && !uabort) ->
+-progress:             goto TRANSFER
+-              fi
+-      od;
+-DONE:
+-      pres_to_use[n]!accept;
+-      goto endIDLE;
+-FAIL:
+-      pres_to_use[n]!reject;
+-      goto endIDLE
+-}
+//GO.SYSIN DD App.F.present
+echo App.F.session 1>&2
+sed 's/.//' >App.F.session <<'//GO.SYSIN DD App.F.session'
+-/*
+- * Session Layer Validation Model
+- */
+-
+-proctype session(bit n)
+-{     bit toggle;
+-      byte type, status;
+-
+-endIDLE:
+-      do
+-      :: pres_to_ses[n]?type ->
+-              if
+-              :: (type == transfer) ->
+-                      goto DATA_OUT
+-              :: (type != transfer)   /* ignore */
+-              fi
+-      :: flow_to_ses[n]?type,0 ->
+-              if
+-              :: (type == connect) ->
+-                      goto DATA_IN
+-              :: (type != connect)    /* ignore */
+-              fi
+-      od;
+-
+-DATA_IN:              /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!create;
+-      do
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_flow[n]!reject,0;
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              ses_to_flow[n]!accept,0;
+-              break
+-      od;
+-                      /* 2. Receive the data, upto eof */
+-      do
+-      :: flow_to_ses[n]?data,0 ->
+-              ses_to_fsrv[n]!data
+-      :: flow_to_ses[n]?eof,0 ->
+-              ses_to_fsrv[n]!eof;
+-              break
+-      :: pres_to_ses[n]?transfer ->
+-              ses_to_pres[n]!reject(NON_FATAL)
+-      :: flow_to_ses[n]?close,0 ->    /* remote user aborted */
+-              ses_to_fsrv[n]!close;
+-              break
+-      :: timeout ->           /* got disconnected */
+-              ses_to_fsrv[n]!close;
+-              goto endIDLE
+-      od;
+-                      /* 3. Close the connection */
+-      ses_to_flow[n]!close,0;
+-      goto endIDLE;
+-
+-DATA_OUT:             /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!open;
+-      if
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              skip
+-      fi;
+-                      /* 2. initialize flow control */
+-      ses_to_flow[n]!sync,toggle;
+-      do
+-      :: atomic {
+-              flow_to_ses[n]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-         }
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      od;
+-      toggle = 1 - toggle;
+-                      /* 3. prepare remote file fsrver */
+-      ses_to_flow[n]!connect,0;
+-      if
+-      :: flow_to_ses[n]?reject,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?connect,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(NON_FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?accept,0 ->
+-              skip
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      fi;
+-                      /* 4. Transmit the data, upto eof */
+-      do
+-      :: fsrv_to_ses[n]?data ->
+-              ses_to_flow[n]!data,0
+-      :: fsrv_to_ses[n]?eof ->
+-              ses_to_flow[n]!eof,0;
+-              status = COMPLETE;
+-              break
+-      :: pres_to_ses[n]?abort ->      /* local user aborted */
+-              ses_to_fsrv[n]!close;
+-              ses_to_flow[n]!close,0;
+-              status = FATAL;
+-              break
+-      od;
+-                      /* 5. Close the connection */
+-      do
+-      :: pres_to_ses[n]?abort         /* ignore */
+-      :: flow_to_ses[n]?close,0 ->
+-              if
+-              :: (status == COMPLETE) ->
+-                      ses_to_pres[n]!accept,0
+-              :: (status != COMPLETE) ->
+-                      ses_to_pres[n]!reject(status)
+-              fi;
+-              break
+-      :: timeout ->
+-              ses_to_pres[n]!reject(FATAL);
+-              break
+-      od;
+-      goto endIDLE
+-}
+//GO.SYSIN DD App.F.session
+echo App.F.user 1>&2
+sed 's/.//' >App.F.user <<'//GO.SYSIN DD App.F.user'
+-/*
+- * User Layer Validation Model
+- */
+-
+-proctype userprc(bit n)
+-{
+-      use_to_pres[n]!transfer;
+-      if
+-      :: pres_to_use[n]?accept -> goto Done
+-      :: pres_to_use[n]?reject -> goto Done
+-      :: use_to_pres[n]!abort  -> goto Aborted
+-      fi;
+-Aborted:
+-      if
+-      :: pres_to_use[n]?accept -> goto Done
+-      :: pres_to_use[n]?reject -> goto Done
+-      fi;
+-Done:
+-      skip
+-}
+//GO.SYSIN DD App.F.user
+echo p101 1>&2
+sed 's/.//' >p101 <<'//GO.SYSIN DD p101'
+-#define msgtype 33
+-
+-chan name = [0] of { byte, byte };
+-
+-/* byte name;         typo  - this line shouldn't have been here */
+-
+-proctype A()
+-{     name!msgtype(124);
+-      name!msgtype(121)
+-}
+-proctype B()
+-{     byte state;
+-      name?msgtype(state)
+-}
+-init
+-{     atomic { run A(); run B() }
+-}
+//GO.SYSIN DD p101
+echo p102 1>&2
+sed 's/.//' >p102 <<'//GO.SYSIN DD p102'
+-#define a 1
+-#define b 2
+-
+-chan ch = [1] of { byte };
+-
+-proctype A() { ch!a }
+-proctype B() { ch!b }
+-proctype C()
+-{     if
+-      :: ch?a
+-      :: ch?b
+-      fi
+-}
+-init { atomic { run A(); run B(); run C() } }
+//GO.SYSIN DD p102
+echo p104.1 1>&2
+sed 's/.//' >p104.1 <<'//GO.SYSIN DD p104.1'
+-#define N    128
+-#define size  16
+-
+-chan in    = [size] of { short };
+-chan large = [size] of { short };
+-chan small = [size] of { short };
+-
+-proctype split()
+-{     short cargo;
+-
+-      do
+-      :: in?cargo ->
+-              if
+-              :: (cargo >= N) -> large!cargo
+-              :: (cargo <  N) -> small!cargo
+-              fi
+-      od
+-}
+-init {        run split() }
+//GO.SYSIN DD p104.1
+echo p104.2 1>&2
+sed 's/.//' >p104.2 <<'//GO.SYSIN DD p104.2'
+-#define N    128
+-#define size  16
+-
+-chan in    = [size] of { short };
+-chan large = [size] of { short };
+-chan small = [size] of { short };
+-
+-proctype split()
+-{     short cargo;
+-
+-      do
+-      :: in?cargo ->
+-              if
+-              :: (cargo >= N) -> large!cargo
+-              :: (cargo <  N) -> small!cargo
+-              fi
+-      od
+-}
+-proctype merge()
+-{     short cargo;
+-
+-      do
+-      ::      if
+-              :: large?cargo
+-              :: small?cargo
+-              fi;
+-              in!cargo
+-      od
+-}
+-init
+-{     in!345; in!12; in!6777; in!32; in!0;
+-      run split(); run merge()
+-}
+//GO.SYSIN DD p104.2
+echo p105.1 1>&2
+sed 's/.//' >p105.1 <<'//GO.SYSIN DD p105.1'
+-#define p     0
+-#define v     1
+-
+-chan sema = [0] of { bit };
+-
+-proctype dijkstra()
+-{     do
+-      :: sema!p -> sema?v
+-      od      
+-}
+-proctype user()
+-{     sema?p;
+-      /* critical section */
+-      sema!v
+-      /* non-critical section */
+-}
+-init
+-{     atomic {
+-              run dijkstra();
+-              run user(); run user(); run user()
+-      }
+-}
+//GO.SYSIN DD p105.1
+echo p105.2 1>&2
+sed 's/.//' >p105.2 <<'//GO.SYSIN DD p105.2'
+-proctype fact(int n; chan p)
+-{     int result;
+-
+-      if
+-      :: (n <= 1) -> p!1
+-      :: (n >= 2) ->
+-              chan child = [1] of { int };
+-              run fact(n-1, child);
+-              child?result;
+-              p!n*result
+-      fi
+-}
+-init
+-{     int result;
+-      chan child = [1] of { int };
+-
+-      run fact(7, child);
+-      child?result;
+-      printf("result: %d\n", result)
+-}
+//GO.SYSIN DD p105.2
+echo p107 1>&2
+sed 's/.//' >p107 <<'//GO.SYSIN DD p107'
+-mtype = { ack, nak, err, next, accept }
+-
+-proctype transfer(chan in, out, chin, chout)
+-{     byte o, i;
+-
+-      in?next(o);
+-      do
+-      :: chin?nak(i) -> out!accept(i); chout!ack(o)
+-      :: chin?ack(i) -> out!accept(i); in?next(o); chout!ack(o)
+-      :: chin?err(i) -> chout!nak(o)
+-      od
+-}
+-init
+-{     chan AtoB = [1] of { byte, byte };
+-      chan BtoA = [1] of { byte, byte };
+-      chan Ain  = [2] of { byte, byte };
+-      chan Bin  = [2] of { byte, byte };
+-      chan Aout = [2] of { byte, byte };
+-      chan Bout = [2] of { byte, byte };
+-
+-      atomic {
+-              run transfer(Ain, Aout, AtoB, BtoA);
+-              run transfer(Bin, Bout, BtoA, AtoB)
+-      };
+-      AtoB!err(0)
+-}
+//GO.SYSIN DD p107
+echo p108 1>&2
+sed 's/.//' >p108 <<'//GO.SYSIN DD p108'
+-/***** Ackermann's function *****/
+-
+-/*    a good example where a simulation run is the
+-      better choice - and verification is overkill.
+-
+-      1. simulation
+-              -> straight simulation (spin p108) takes
+-              -> approx. 6.4 sec on an SGI R3000
+-              -> prints the answer: ack(3,3) = 61
+-              -> after creating 2433 processes
+-
+-      note: all process invocations can, at least in one
+-      feasible execution scenario, overlap - if each
+-      process chooses to hang around indefinitely in
+-      its dying state, at the closing curly brace.
+-      this means that the maximum state vector `could' grow
+-      to hold all 2433 processes or about 2433*12 bytes of data.
+-      the assert(0) at the end makes sure though that the run
+-      stops the first time we complete an execution sequence
+-      that computes the answer, so the following suffices:
+-
+-      2. verification
+-              -> spin -a p108
+-              -> cc -DVECTORSZ=2048 -o pan pan.c
+-              -> pan -m15000
+-              -> which completes in about 5 sec
+- */
+-
+-proctype ack(short a, b; chan ch1)
+-{     chan ch2 = [1] of { short };
+-      short ans;
+-
+-      if
+-      :: (a == 0) ->
+-              ans = b+1
+-      :: (a != 0) ->
+-              if
+-              :: (b == 0) ->
+-                      run ack(a-1, 1, ch2)
+-              :: (b != 0) ->
+-                      run ack(a, b-1, ch2);
+-                      ch2?ans;
+-                      run ack(a-1, ans, ch2)
+-              fi;
+-              ch2?ans
+-      fi;
+-      ch1!ans
+-}
+-init
+-{     chan ch = [1] of { short };
+-      short ans;
+-
+-      run ack(3, 3, ch);
+-      ch?ans;
+-      printf("ack(3,3) = %d\n", ans);
+-      assert(0)       /* a forced stop, (Chapter 6) */
+-}
+//GO.SYSIN DD p108
+echo p116 1>&2
+sed 's/.//' >p116 <<'//GO.SYSIN DD p116'
+-byte state = 1;
+-
+-proctype A()
+-{     (state == 1) -> state = state + 1;
+-      assert(state == 2)
+-}
+-proctype B()
+-{     (state == 1) -> state = state - 1;
+-      assert(state == 0)
+-}
+-init { run A(); run B() }
+//GO.SYSIN DD p116
+echo p117 1>&2
+sed 's/.//' >p117 <<'//GO.SYSIN DD p117'
+-#define p     0
+-#define v     1
+-
+-chan sema = [0] of { bit };   /* typo in original `=' was missing */
+-
+-proctype dijkstra()
+-{     do
+-      :: sema!p -> sema?v
+-      od      
+-}
+-byte count;
+-
+-proctype user()
+-{     sema?p;
+-      count = count+1;
+-      skip;   /* critical section */
+-      count = count-1;
+-      sema!v;
+-      skip    /* non-critical section */
+-}
+-proctype monitor() { assert(count == 0 || count == 1) }
+-init
+-{     atomic {
+-              run dijkstra(); run monitor();
+-              run user(); run user(); run user()
+-      }
+-}
+//GO.SYSIN DD p117
+echo p123 1>&2
+sed 's/.//' >p123 <<'//GO.SYSIN DD p123'
+-/* alternating bit - version with message loss */
+-
+-#define MAX   3
+-
+-mtype = { msg0, msg1, ack0, ack1 };
+-
+-chan  sender  =[1] of { byte };
+-chan  receiver=[1] of { byte };
+-
+-proctype Sender()
+-{     byte any;
+-again:
+-      do
+-      :: receiver!msg1;
+-              if
+-              :: sender?ack1 -> break
+-              :: sender?any /* lost */
+-              :: timeout    /* retransmit */
+-              fi
+-      od;
+-      do
+-      :: receiver!msg0;
+-              if
+-              :: sender?ack0 -> break
+-              :: sender?any /* lost */
+-              :: timeout    /* retransmit */
+-              fi
+-      od;
+-      goto again
+-}
+-
+-proctype Receiver()
+-{     byte any;
+-again:
+-      do
+-      :: receiver?msg1 -> sender!ack1; break
+-      :: receiver?msg0 -> sender!ack0
+-      :: receiver?any /* lost */
+-      od;
+-P0:
+-      do
+-      :: receiver?msg0 -> sender!ack0; break
+-      :: receiver?msg1 -> sender!ack1
+-      :: receiver?any /* lost */
+-      od;
+-P1:
+-      goto again
+-}
+-
+-init { atomic { run Sender(); run Receiver() } }
+-
+-never {
+-      do
+-      :: skip /* allow any time delay */
+-      :: receiver?[msg0] -> goto accept0
+-      :: receiver?[msg1] -> goto accept1
+-      od;
+-accept0:
+-      do
+-      :: !Receiver[2]@P0      /* n.b. new syntax of remote reference */
+-      od;
+-accept1:
+-      do
+-      :: !Receiver[2]@P1
+-      od
+-}
+//GO.SYSIN DD p123
+echo p248 1>&2
+sed 's/.//' >p248 <<'//GO.SYSIN DD p248'
+-proctype fact(int n; chan p)
+-{     int result;
+-
+-      if
+-      :: (n <= 1) -> p!1
+-      :: (n >= 2) ->
+-              chan child = [1] of { int };
+-              run fact(n-1, child);
+-              child?result;
+-              p!n*result
+-      fi
+-}
+-init
+-{     int result;
+-      chan child = [1] of { int };
+-
+-      run fact(12, child);
+-      child?result;
+-      printf("result: %d\n", result)
+-}
+//GO.SYSIN DD p248
+echo p312 1>&2
+sed 's/.//' >p312 <<'//GO.SYSIN DD p312'
+-#define MIN   9       /* first data message to send */
+-#define MAX   12      /* last  data message to send */
+-#define FILL  99      /* filler message */
+-
+-mtype = { ack, nak, err }
+-
+-proctype transfer(chan chin, chout)
+-{     byte o, i, last_i=MIN;
+-
+-      o = MIN+1;
+-      do
+-      :: chin?nak(i) ->
+-              assert(i == last_i+1);
+-              chout!ack(o)
+-      :: chin?ack(i) ->
+-              if
+-              :: (o <  MAX) -> o = o+1        /* next */
+-              :: (o >= MAX) -> o = FILL       /* done */
+-              fi;
+-              chout!ack(o)
+-      :: chin?err(i) ->
+-              chout!nak(o)
+-      od
+-}
+-
+-proctype channel(chan in, out)
+-{     byte md, mt;
+-      do
+-      :: in?mt,md ->
+-              if
+-              :: out!mt,md
+-              :: out!err,0
+-              fi
+-      od
+-}
+-
+-init
+-{     chan AtoB = [1] of { byte, byte };
+-      chan BtoC = [1] of { byte, byte };
+-      chan CtoA = [1] of { byte, byte };
+-      atomic {
+-              run transfer(AtoB, BtoC);
+-              run channel(BtoC, CtoA);
+-              run transfer(CtoA, AtoB)
+-      };
+-      AtoB!err,0      /* start */
+-}
+//GO.SYSIN DD p312
+echo p319 1>&2
+sed 's/.//' >p319 <<'//GO.SYSIN DD p319'
+-#define true  1
+-#define false 0
+-
+-bool busy[3];
+-
+-chan   up[3] = [1] of { byte };
+-chan down[3] = [1] of { byte };
+-
+-mtype = { start, attention, data, stop }
+-
+-proctype station(byte id; chan in, out)
+-{     do
+-      :: in?start ->
+-              atomic { !busy[id] -> busy[id] = true };
+-              out!attention;
+-              do
+-              :: in?data -> out!data
+-              :: in?stop -> break
+-              od;
+-              out!stop;
+-              busy[id] = false
+-      :: atomic { !busy[id] -> busy[id] = true };
+-              out!start;
+-              in?attention;
+-              do
+-              :: out!data -> in?data
+-              :: out!stop -> break
+-              od;
+-              in?stop;
+-              busy[id] = false
+-      od
+-}
+-
+-init {
+-      atomic {
+-              run station(0, up[2], down[2]);
+-              run station(1, up[0], down[0]);
+-              run station(2, up[1], down[1]);
+-
+-              run station(0, down[0], up[0]);
+-              run station(1, down[1], up[1]);
+-              run station(2, down[2], up[2])
+-      }
+-}
+//GO.SYSIN DD p319
+echo p320 1>&2
+sed 's/.//' >p320 <<'//GO.SYSIN DD p320'
+-#define true  1
+-#define false 0
+-#define Aturn false
+-#define Bturn true
+-
+-bool x, y, t;
+-bool ain, bin;
+-
+-proctype A()
+-{     x = true;
+-      t = Bturn;
+-      (y == false || t == Aturn);
+-      ain = true;
+-      assert(bin == false);   /* critical section */
+-      ain = false;
+-      x = false
+-}
+-
+-proctype B()
+-{     y = true;
+-      t = Aturn;
+-      (x == false || t == Bturn);
+-      bin = true;
+-      assert(ain == false);   /* critical section */
+-      bin = false;
+-      y = false
+-}
+-
+-init
+-{     run A(); run B()
+-}
+//GO.SYSIN DD p320
+echo p325.test 1>&2
+sed 's/.//' >p325.test <<'//GO.SYSIN DD p325.test'
+-proctype test_sender(bit n)
+-{     byte type, toggle;
+-
+-      ses_to_flow[n]!sync,toggle;
+-      do
+-      :: flow_to_ses[n]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-      :: timeout ->
+-              ses_to_flow[n]!sync,toggle
+-      od;
+-      toggle = 1 - toggle;
+-
+-      do
+-      :: ses_to_flow[n]!data,white
+-      :: ses_to_flow[n]!data,red -> break
+-      od;
+-      do
+-      :: ses_to_flow[n]!data,white
+-      :: ses_to_flow[n]!data,blue -> break
+-      od;
+-      do
+-      :: ses_to_flow[n]!data,white
+-      :: break
+-      od
+-}
+-proctype test_receiver(bit n)
+-{
+-      do
+-      :: flow_to_ses[n]?data,white
+-      :: flow_to_ses[n]?data,red -> break
+-      od;
+-      do
+-      :: flow_to_ses[n]?data,white
+-      :: flow_to_ses[n]?data,blue -> break
+-      od;
+-end:  do
+-      :: flow_to_ses[n]?data,white
+-      od
+-}
+//GO.SYSIN DD p325.test
+echo p327.upper 1>&2
+sed 's/.//' >p327.upper <<'//GO.SYSIN DD p327.upper'
+-proctype upper()
+-{     byte s_state, r_state;
+-      byte type, toggle;
+-
+-      ses_to_flow[0]!sync,toggle;
+-      do
+-      :: flow_to_ses[0]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-      :: timeout ->
+-              ses_to_flow[0]!sync,toggle
+-      od;
+-      toggle = 1 - toggle;
+-
+-      do
+-      /* sender */
+-      :: ses_to_flow[0]!white,0
+-      :: atomic {
+-              (s_state == 0 && len (ses_to_flow[0]) < QSZ) ->
+-              ses_to_flow[0]!red,0 ->
+-              s_state = 1
+-         }
+-      :: atomic {
+-              (s_state == 1 && len (ses_to_flow[0]) < QSZ) ->
+-              ses_to_flow[0]!blue,0 ->
+-              s_state = 2
+-         }
+-      /* receiver */
+-      :: flow_to_ses[1]?white,0
+-      :: atomic {
+-              (r_state == 0 && flow_to_ses[1]?[red]) ->
+-              flow_to_ses[1]?red,0 ->
+-              r_state = 1
+-         }
+-      :: atomic {
+-              (r_state == 0 && flow_to_ses[1]?[blue]) ->
+-              assert(0)
+-         }
+-      :: atomic {
+-              (r_state == 1 && flow_to_ses[1]?[blue]) ->
+-              flow_to_ses[1]?blue,0;
+-              break
+-         }
+-      :: atomic {
+-              (r_state == 1 && flow_to_ses[1]?[red]) ->
+-              assert(0)
+-         }
+-      od;
+-end:
+-      do
+-      :: flow_to_ses[1]?white,0
+-      :: flow_to_ses[1]?red,0 -> assert(0)
+-      :: flow_to_ses[1]?blue,0 -> assert(0)
+-      od
+-}
+//GO.SYSIN DD p327.upper
+echo p329 1>&2
+sed 's/.//' >p329 <<'//GO.SYSIN DD p329'
+-/*
+- * PROMELA Validation Model
+- * FLOW CONTROL LAYER VALIDATION
+- */
+-
+-#define LOSS          0       /* message loss   */
+-#define DUPS          0       /* duplicate msgs */
+-#define QSZ           2       /* queue size     */
+-
+-mtype = {
+-      red, white, blue,
+-      abort, accept, ack, sync_ack, close, connect,
+-      create, data, eof, open, reject, sync, transfer,
+-      FATAL, NON_FATAL, COMPLETE
+-      }
+-
+-chan ses_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_ses[2] = [QSZ] of { byte, byte };
+-chan dll_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_dll[2];
+-
+-#include "App.F.flow_cl"
+-#include "p327.upper"
+-
+-init
+-{
+-      atomic {
+-        flow_to_dll[0] = dll_to_flow[1];
+-        flow_to_dll[1] = dll_to_flow[0];
+-        run fc(0); run fc(1);
+-        run upper()
+-      }
+-}
+//GO.SYSIN DD p329
+echo p330 1>&2
+sed 's/.//' >p330 <<'//GO.SYSIN DD p330'
+-/*
+- * PROMELA Validation Model
+- * FLOW CONTROL LAYER VALIDATION
+- */
+-
+-#define LOSS          0       /* message loss   */
+-#define DUPS          0       /* duplicate msgs */
+-#define QSZ           2       /* queue size     */
+-
+-mtype = {
+-      red, white, blue,
+-      abort, accept, ack, sync_ack, close, connect,
+-      create, data, eof, open, reject, sync, transfer,
+-      FATAL, NON_FATAL, COMPLETE
+-      }
+-
+-chan ses_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_ses[2] = [QSZ] of { byte, byte };
+-chan dll_to_flow[2] = [QSZ] of { byte, byte };
+-chan flow_to_dll[2];
+-
+-#include "App.F.flow_cl"
+-#include "p327.upper"
+-
+-init
+-{
+-      atomic {
+-        flow_to_dll[0] = dll_to_flow[1];
+-        flow_to_dll[1] = dll_to_flow[0];
+-        run fc(0); run fc(1);
+-        run upper()
+-      }
+-}
+//GO.SYSIN DD p330
+echo p337.defines2 1>&2
+sed 's/.//' >p337.defines2 <<'//GO.SYSIN DD p337.defines2'
+-/*
+- * PROMELA Validation Model
+- * global definitions
+- */
+-
+-#define QSZ           2       /* queue size     */
+-
+-mtype = {
+-      red, white, blue,
+-      abort, accept, ack, sync_ack, close, connect,
+-      create, data, eof, open, reject, sync, transfer,
+-      FATAL, NON_FATAL, COMPLETE
+-      }
+-
+-chan use_to_pres[2] = [QSZ] of { mtype };
+-chan pres_to_use[2] = [QSZ] of { mtype };
+-chan pres_to_ses[2] = [QSZ] of { mtype };
+-chan ses_to_pres[2] = [QSZ] of { mtype, byte };
+-chan ses_to_flow[2] = [QSZ] of { mtype, byte };
+-chan ses_to_fsrv[2] = [0] of { mtype };
+-chan fsrv_to_ses[2] = [0] of { mtype };
+-chan flow_to_ses[2];
+//GO.SYSIN DD p337.defines2
+echo p337.fserver 1>&2
+sed 's/.//' >p337.fserver <<'//GO.SYSIN DD p337.fserver'
+-/*
+- * File Server Validation Model
+- */
+-
+-proctype fserver(bit n)
+-{
+-end:  do
+-      :: ses_to_fsrv[n]?create ->     /* incoming */
+-              if
+-              :: fsrv_to_ses[n]!reject
+-              :: fsrv_to_ses[n]!accept ->
+-                      do
+-                      :: ses_to_fsrv[n]?data
+-                      :: ses_to_fsrv[n]?eof -> break
+-                      :: ses_to_fsrv[n]?close -> break
+-                      od
+-              fi
+-      :: ses_to_fsrv[n]?open ->               /* outgoing */
+-              if
+-              :: fsrv_to_ses[n]!reject
+-              :: fsrv_to_ses[n]!accept ->
+-                      do
+-                      :: fsrv_to_ses[n]!data -> progress: skip
+-                      :: ses_to_fsrv[n]?close -> break
+-                      :: fsrv_to_ses[n]!eof -> break
+-                      od
+-              fi
+-      od
+-}
+//GO.SYSIN DD p337.fserver
+echo p337.pftp.ses 1>&2
+sed 's/.//' >p337.pftp.ses <<'//GO.SYSIN DD p337.pftp.ses'
+-/*
+- * PROMELA Validation Model
+- * Session Layer
+- */
+-
+-#include "p337.defines2"
+-#include "p337.user"
+-#include "App.F.present"
+-#include "p337.session"
+-#include "p337.fserver"
+-
+-init
+-{     atomic {
+-        run userprc(0); run userprc(1);
+-        run present(0); run present(1);
+-        run session(0); run session(1);
+-        run fserver(0); run fserver(1);
+-        flow_to_ses[0] = ses_to_flow[1];
+-        flow_to_ses[1] = ses_to_flow[0]
+-      }
+-}
+//GO.SYSIN DD p337.pftp.ses
+echo p337.session 1>&2
+sed 's/.//' >p337.session <<'//GO.SYSIN DD p337.session'
+-/*
+- * Session Layer Validation Model
+- */
+-
+-proctype session(bit n)
+-{     bit toggle;
+-      byte type, status;
+-
+-endIDLE:
+-      do
+-      :: pres_to_ses[n]?type ->
+-              if
+-              :: (type == transfer) ->
+-                      goto DATA_OUT
+-              :: (type != transfer)   /* ignore */
+-              fi
+-      :: flow_to_ses[n]?type,0 ->
+-              if
+-              :: (type == connect) ->
+-                      goto DATA_IN
+-              :: (type != connect)    /* ignore */
+-              fi
+-      od;
+-
+-DATA_IN:              /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!create;
+-      do
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_flow[n]!reject,0;
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              ses_to_flow[n]!accept,0;
+-              break
+-      od;
+-                      /* 2. Receive the data, upto eof */
+-      do
+-      :: flow_to_ses[n]?data,0 ->
+-              ses_to_fsrv[n]!data
+-      :: flow_to_ses[n]?eof,0 ->
+-              ses_to_fsrv[n]!eof;
+-              break
+-      :: pres_to_ses[n]?transfer ->
+-              ses_to_pres[n]!reject(NON_FATAL)
+-      :: flow_to_ses[n]?close,0 ->    /* remote user aborted */
+-              ses_to_fsrv[n]!close;
+-              break
+-      :: timeout ->           /* got disconnected */
+-              ses_to_fsrv[n]!close;
+-              goto endIDLE
+-      od;
+-                      /* 3. Close the connection */
+-      ses_to_flow[n]!close,0;
+-      goto endIDLE;
+-
+-DATA_OUT:             /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!open;
+-      if
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              skip
+-      fi;
+-                      /* 2. initialize flow control *** disabled
+-      ses_to_flow[n]!sync,toggle;
+-      do
+-      :: atomic {
+-              flow_to_ses[n]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-         }
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      od;
+-      toggle = 1 - toggle;
+-                      /* 3. prepare remote file fsrver */
+-      ses_to_flow[n]!connect,0;
+-      if
+-      :: flow_to_ses[n]?reject,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?connect,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(NON_FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?accept,0 ->
+-              skip
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      fi;
+-                      /* 4. Transmit the data, upto eof */
+-      do
+-      :: fsrv_to_ses[n]?data ->
+-              ses_to_flow[n]!data,0
+-      :: fsrv_to_ses[n]?eof ->
+-              ses_to_flow[n]!eof,0;
+-              status = COMPLETE;
+-              break
+-      :: pres_to_ses[n]?abort ->      /* local user aborted */
+-              ses_to_fsrv[n]!close;
+-              ses_to_flow[n]!close,0;
+-              status = FATAL;
+-              break
+-      od;
+-                      /* 5. Close the connection */
+-      do
+-      :: pres_to_ses[n]?abort         /* ignore */
+-      :: flow_to_ses[n]?close,0 ->
+-              if
+-              :: (status == COMPLETE) ->
+-                      ses_to_pres[n]!accept,0
+-              :: (status != COMPLETE) ->
+-                      ses_to_pres[n]!reject(status)
+-              fi;
+-              break
+-      :: timeout ->
+-              ses_to_pres[n]!reject(FATAL);
+-              break
+-      od;
+-      goto endIDLE
+-}
+//GO.SYSIN DD p337.session
+echo p337.user 1>&2
+sed 's/.//' >p337.user <<'//GO.SYSIN DD p337.user'
+-/*
+- * User Layer Validation Model
+- */
+-
+-proctype userprc(bit n)
+-{
+-      use_to_pres[n]!transfer;
+-      if
+-      :: pres_to_use[n]?accept -> goto Done
+-      :: pres_to_use[n]?reject -> goto Done
+-      :: use_to_pres[n]!abort  -> goto Aborted
+-      fi;
+-Aborted:
+-      if
+-      :: pres_to_use[n]?accept -> goto Done
+-      :: pres_to_use[n]?reject -> goto Done
+-      fi;
+-Done:
+-      skip
+-}
+//GO.SYSIN DD p337.user
+echo p342.pftp.ses1 1>&2
+sed 's/.//' >p342.pftp.ses1 <<'//GO.SYSIN DD p342.pftp.ses1'
+-/*
+- * PROMELA Validation Model
+- * Session Layer
+- */
+-
+-#include "p337.defines2"
+-#include "p337.user"
+-#include "App.F.present"
+-#include "p337.session"
+-#include "p337.fserver"
+-
+-init
+-{
+-      atomic {
+-        run userprc(0); run userprc(1);
+-        run present(0); run present(1);
+-        run session(0); run session(1);
+-        run fserver(0); run fserver(1);
+-        flow_to_ses[0] = ses_to_flow[1];
+-        flow_to_ses[1] = ses_to_flow[0]
+-      };
+-      atomic {
+-              byte any;
+-              chan foo = [1] of { byte, byte };
+-              ses_to_flow[0] = foo;
+-              ses_to_flow[1] = foo
+-      };
+-end:  do
+-      :: foo?any,any
+-      od
+-}
+//GO.SYSIN DD p342.pftp.ses1
+echo p343.claim 1>&2
+sed 's/.//' >p343.claim <<'//GO.SYSIN DD p343.claim'
+-never {
+-      skip;   /* match first step of init (spin version 2.0) */
+-      do
+-      :: !pres_to_ses[0]?[transfer]
+-      && !flow_to_ses[0]?[connect]
+-      :: pres_to_ses[0]?[transfer] ->
+-              goto accept0
+-      :: flow_to_ses[0]?[connect] ->
+-              goto accept1
+-      od;
+-accept0:
+-      do
+-      :: !ses_to_pres[0]?[accept]
+-      && !ses_to_pres[0]?[reject]
+-      od;
+-accept1:
+-      do
+-      :: !ses_to_pres[1]?[accept]
+-      && !ses_to_pres[1]?[reject]
+-      od
+-}
+//GO.SYSIN DD p343.claim
+echo p347.pftp.ses5 1>&2
+sed 's/.//' >p347.pftp.ses5 <<'//GO.SYSIN DD p347.pftp.ses5'
+-/*
+- * PROMELA Validation Model
+- * Session Layer
+- */
+-
+-#include "p337.defines2"
+-#include "p347.pres.sim"
+-#include "p347.session.prog"
+-#include "p337.fserver"
+-
+-init
+-{     atomic {
+-        run present(0); run present(1);
+-        run session(0); run session(1);
+-        run fserver(0); run fserver(1);
+-        flow_to_ses[0] = ses_to_flow[1];
+-        flow_to_ses[1] = ses_to_flow[0]
+-      }
+-}
+//GO.SYSIN DD p347.pftp.ses5
+echo p347.pres.sim 1>&2
+sed 's/.//' >p347.pres.sim <<'//GO.SYSIN DD p347.pres.sim'
+-/*
+- * PROMELA Validation Model
+- * Presentation & User Layer - combined and reduced
+- */
+-
+-proctype present(bit n)
+-{     byte status;
+-progress0:
+-      pres_to_ses[n]!transfer ->
+-      do
+-      :: pres_to_ses[n]!abort;
+-progress1:    skip
+-      :: ses_to_pres[n]?accept,status ->
+-                      break
+-      :: ses_to_pres[n]?reject,status ->
+-              if
+-              :: (status == NON_FATAL) ->
+-                      goto progress0
+-              :: (status != NON_FATAL) ->
+-                      break
+-              fi
+-      od
+-}
+//GO.SYSIN DD p347.pres.sim
+echo p347.session.prog 1>&2
+sed 's/.//' >p347.session.prog <<'//GO.SYSIN DD p347.session.prog'
+-/*
+- * Session Layer Validation Model
+- */
+-
+-proctype session(bit n)
+-{     bit toggle;
+-      byte type, status;
+-
+-endIDLE:
+-      do
+-      :: pres_to_ses[n]?type ->
+-              if
+-              :: (type == transfer) ->
+-                      goto progressDATA_OUT
+-              :: (type != transfer)   /* ignore */
+-              fi
+-      :: flow_to_ses[n]?type,0 ->
+-              if
+-              :: (type == connect) ->
+-                      goto progressDATA_IN
+-              :: (type != connect)    /* ignore */
+-              fi
+-      od;
+-
+-progressDATA_IN:              /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!create;
+-      do
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_flow[n]!reject,0;
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              ses_to_flow[n]!accept,0;
+-              break
+-      od;
+-                      /* 2. Receive the data, upto eof */
+-      do
+-      :: flow_to_ses[n]?data,0 ->
+-progress:     ses_to_fsrv[n]!data
+-      :: flow_to_ses[n]?eof,0 ->
+-              ses_to_fsrv[n]!eof;
+-              break
+-      :: pres_to_ses[n]?transfer ->
+-              ses_to_pres[n]!reject(NON_FATAL)
+-      :: flow_to_ses[n]?close,0 ->    /* remote user aborted */
+-              ses_to_fsrv[n]!close;
+-              break
+-      :: timeout ->           /* got disconnected */
+-              ses_to_fsrv[n]!close;
+-              goto endIDLE
+-      od;
+-                      /* 3. Close the connection */
+-      ses_to_flow[n]!close,0;
+-      goto endIDLE;
+-
+-progressDATA_OUT:             /* 1. prepare local file fsrver */
+-      ses_to_fsrv[n]!open;
+-      if
+-      :: fsrv_to_ses[n]?reject ->
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: fsrv_to_ses[n]?accept ->
+-              skip
+-      fi;
+-                      /* 2. initialize flow control *** disabled
+-      ses_to_flow[n]!sync,toggle;
+-      do
+-      :: atomic {
+-              flow_to_ses[n]?sync_ack,type ->
+-              if
+-              :: (type != toggle)
+-              :: (type == toggle) -> break
+-              fi
+-         }
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      od;
+-      toggle = 1 - toggle;
+-                      /* 3. prepare remote file fsrver */
+-      ses_to_flow[n]!connect,0;
+-      if
+-      :: flow_to_ses[n]?reject,status ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?connect,0 ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(NON_FATAL);
+-              goto endIDLE
+-      :: flow_to_ses[n]?accept,0 ->
+-              skip
+-      :: timeout ->
+-              ses_to_fsrv[n]!close;
+-              ses_to_pres[n]!reject(FATAL);
+-              goto endIDLE
+-      fi;
+-                      /* 4. Transmit the data, upto eof */
+-      do
+-      :: fsrv_to_ses[n]?data ->
+-              ses_to_flow[n]!data,0
+-      :: fsrv_to_ses[n]?eof ->
+-              ses_to_flow[n]!eof,0;
+-              status = COMPLETE;
+-              break
+-      :: pres_to_ses[n]?abort ->      /* local user aborted */
+-              ses_to_fsrv[n]!close;
+-              ses_to_flow[n]!close,0;
+-              status = FATAL;
+-              break
+-      od;
+-                      /* 5. Close the connection */
+-      do
+-      :: pres_to_ses[n]?abort         /* ignore */
+-      :: flow_to_ses[n]?close,0 ->
+-              if
+-              :: (status == COMPLETE) ->
+-                      ses_to_pres[n]!accept,0
+-              :: (status != COMPLETE) ->
+-                      ses_to_pres[n]!reject(status)
+-              fi;
+-              break
+-      :: timeout ->
+-              ses_to_pres[n]!reject(FATAL);
+-              break
+-      od;
+-      goto endIDLE
+-}
+//GO.SYSIN DD p347.session.prog
+echo p94 1>&2
+sed 's/.//' >p94 <<'//GO.SYSIN DD p94'
+-byte state = 2;
+-
+-proctype A() { (state == 1) -> state = 3 }
+-
+-proctype B() { state = state - 1 }
+-
+-/* added: */
+-init { run A(); run B() }
+//GO.SYSIN DD p94
+echo p95.1 1>&2
+sed 's/.//' >p95.1 <<'//GO.SYSIN DD p95.1'
+-init { printf("hello world\n") }
+//GO.SYSIN DD p95.1
+echo p95.2 1>&2
+sed 's/.//' >p95.2 <<'//GO.SYSIN DD p95.2'
+-proctype A(byte state; short set)
+-{     (state == 1) -> state = set
+-}
+-
+-init { run A(1, 3) }
+//GO.SYSIN DD p95.2
+echo p96.1 1>&2
+sed 's/.//' >p96.1 <<'//GO.SYSIN DD p96.1'
+-byte state = 1;
+-
+-proctype A() { (state == 1) -> state = state + 1 }
+-
+-proctype B() { (state == 1) -> state = state - 1 }
+-
+-init { run A(); run B() }
+//GO.SYSIN DD p96.1
+echo p96.2 1>&2
+sed 's/.//' >p96.2 <<'//GO.SYSIN DD p96.2'
+-#define true  1
+-#define false 0
+-#define Aturn 1
+-#define Bturn 0
+-
+-bool x, y, t;
+-
+-proctype A()
+-{     x = true;
+-      t = Bturn;
+-      (y == false || t == Aturn);
+-      /* critical section */
+-      x = false
+-}
+-proctype B()
+-{     y = true;
+-      t = Aturn;
+-      (x == false || t == Bturn);
+-      /* critical section */
+-      y = false
+-}
+-init { run A(); run B() }
+//GO.SYSIN DD p96.2
+echo p97.1 1>&2
+sed 's/.//' >p97.1 <<'//GO.SYSIN DD p97.1'
+-byte state = 1;
+-proctype A() { atomic { (state == 1) -> state = state + 1 } }
+-proctype B() { atomic { (state == 1) -> state = state - 1 } }
+-init { run A(); run B() }
+//GO.SYSIN DD p97.1
+echo p97.2 1>&2
+sed 's/.//' >p97.2 <<'//GO.SYSIN DD p97.2'
+-proctype nr(short pid, a, b)
+-{     int res;
+-
+-atomic        {       res = (a*a+b)/2*a;
+-              printf("result %d: %d\n", pid, res)
+-      }
+-}
+-init { run nr(1,1,1); run nr(1,2,2); run nr(1,3,2) }
+//GO.SYSIN DD p97.2
+echo p99 1>&2
+sed 's/.//' >p99 <<'//GO.SYSIN DD p99'
+-proctype A(chan q1)
+-{     chan q2;
+-
+-      q1?q2;
+-      q2!123
+-}
+-
+-proctype B(chan qforb)
+-{     int x;
+-
+-      qforb?x;
+-      printf("x = %d\n", x)
+-}
+-
+-init
+-{     chan qname[2] = [1] of { chan };
+-      chan qforb = [1] of { int };
+-
+-      run A(qname[0]);
+-      run B(qforb);
+-
+-      qname[0]!qforb
+-}
+//GO.SYSIN DD p99
diff --git a/trunk/verif/Spin/Doc/V1.Updates b/trunk/verif/Spin/Doc/V1.Updates
new file mode 100755 (executable)
index 0000000..fdd9715
--- /dev/null
@@ -0,0 +1,358 @@
+Update History of the SPIN Version 1.0 sources
+==============================================
+
+==== Version 1.0 - January 1991 ====
+
+The version published in the first printing of
+``Design and Validation of Computer Protocols''
+is nominally SPIN Version 1.0.
+The notes below describe all modifications to that
+source that were made between January 1991 and
+December 1994 (when the distribution switched to
+Spin Version 2.0, see V2.Updates).
+
+==== Version 1.1 - April 1991 ====
+
+1. (4/6/91)
+a queue with a single field of type bool is now mapped onto
+an unsigned char to avoid compilers mapping it onto unsigned int.
+2. (4/7/91)
+variables are now sorted by type in the statevector (more compact
+and thus improves hashing)
+3. (4/7/91)
+improved handling of atomic move (removes a statespace-intercept
+bug for initial process with id=0)
+4. (5/22/91)
+allow multiple labels per statement, without needing skip-fillers
+5. (6/11/91)
+fixed bug in reassigning labels in pan.t 
+6. (7/30/91)
+- added proc_skip[] and q_skip[] arrays to pan sources
+  the creation of processes and queues was not always
+  reversible due to word-alignment errors... [caused sv_restor() error]
+- removed Have_claim from sched.c; the adjustment of pids was incorrect
+- a remote ref to a non-existing pid is now always 0, and does not
+  cause a dummy global variable to be created by default with -t...
+  (chages in vars.c and sched.c)
+7. (8/1/91)
+- fixed a potentially infinite cycle in walk_sub()
+8. (8/7/91)
+- fixed bug: couldn't complete rendez-vous inside atomic sections
+9. (8/22/91)
+- lookup(s) failed to check a match on globals when
+  performing a local lookup of names; caused guided simulations
+  to report type clashes.
+
+==== Version 1.2 - August 1991 ====
+
+1. (9/11/91)
+- added traps to check for uninitialized channels in pan.c
+- added descriptive statement strings into transition matrix
+  which are now reported with unreached code etc.
+2. (1/7/92)
+- removed bug: no state should be stored in mid-rv.
+  note that a rv need not complete and matching
+  on the mid state of an unsuccessful rv may cause
+  missing errors (a rv may legally not complete in
+  some cases, without causing deadlock, and not in others).
+  the change also reduces the number of states stored.
+3. (1/11/92)
+- made printout for R different from r in mesg.c
+
+==== Version 1.3 - January 1992 ==== [current USL Toolchest version]
+
+1. 3/6/92
+- bug fixed in usage of -l with rendez-vous (forgot "if (boq==-1)") pangen1.h
+2. 4/10/92
+- converted to new hstore with sorted linked lists (roughly 10% faster)
+3. 6/3/92
+- remote variables were not promoted to (int) before referral in expressions
+  updated Errata with some warnings (e.g., about modeling system invariants
+  in the presence of timeouts, and using the wrong number of parameters in
+  receives)
+- updated makefile with hint for yacc-flags
+4. 6/10/92
+- spin now returns the number of parse errors found upon exit from main
+- yyin is now declared extern in main
+- srand is now declared void in spin.h
+5. 7/4/92
+- added pan options -d and -d -d to printout the internal state tables
+  pan will no longer report structurally unreachable states as
+  dynamically unreachable
+- added warning when spec is modified since pan.trail written
+- solved a trail problem when user guess pids which are offset by claim
+- print proper process numbers for spin -t when a claim is running
+- fixed error in lookup of _p values (it's a local var not global)
+- improved claim checking with geoffrey browns claim stuttering semantics
+
+==== Version 1.4 - July 1992 ====
+
+1. 7/8/92
+- replaced emalloc with a dedicated emalloc/malloc/free package; this
+  is six times faster on pftp.ses1 example compared to sysV library malloc
+2. 7/12/92
+- added default array bounds checking (except for remote references)
+  makes validations a little slower (say 5% - 10%), but is safer, and
+  the user can override it by compiling: cc -DNOBOUNDCHECK pan.c
+3. 8/26/92
+- improved the acceptance cycle detection method with a new algorithm
+  due to Patrice Godefroid, that works in both bitstate and exhaustive
+  search mode (the old version worked only in exhaustive mode)
+  time and space complexity of the new algorithm is the same as that for
+  non-progress cycle detection algorithm (at worst twice that of a straight search)
+  the method is functionally the same as the earlier method due to Courcoubetis,
+  Vardi, Wolper, and Yannakakis (CAV'90), but uses the 2-bit demon trick from
+  the non-progress cycle detector to distinguish between 1st and 2nd search.
+- fixed a buglet in lex.l that catenated strings printed on a single line
+  (thanks Alan Wenban for catching it)
+4. 12/11/92
+- intermediate states in atomic sequences were not stored in standard search
+  mode, but stored when a never claim was defined - that was unnecessary, and
+  has now been avoided.  behavior doesn't change, but memory consumption in
+  exhaustive mode is now reduced somewhat.
+- the acceptance cycle detection algorithm would initiate its second search
+  from an accepting state within a never claim, even when the system was
+  inside an atomic sequence - it could therefore produce non-existing cycles.
+  has been fixed (both fixes thanks to Patrice Godefroid and Didier Pirrotin)
+
+==== Version 1.5 - January 1993 ====
+
+1.5.0
+- an option -V was added both to spin itself and to the analyzers
+  generated by spin to print the source version number.
+- a compiler directive VERBOSE was added to the generated analyzers
+  to assist the user in understanding how the depth-first searches
+  are performed.  to invoke the extra printouts compile
+  the source as cc -DVERBOSE pan.c (plus any other directives you may
+  be using, such as -DBITSTATE or -DMEMCNT=23)
+- a small bug-fix was added to avoid a misplaced compiler directive
+  (in BITSTATE mode, in the absence of accept labels in the model, there
+  could be a compiler error that is now avoided)
+- somewhat improved error reporting.
+- several more important runtime options for the generated analyzers
+  were added:
+  1    an explicit runtime option -a to invoke the search for
+       acceptance cycles.  until now this used to happen by default
+       unless you specified an explicit -l option for a search for
+       non-progress cycles.  from now on a search for cycles
+       always has to be specified explicitly as either -a or -l.
+  2    a runtime option -f to modify the search for cycles under
+       `weak fairness.'   it works for both -a (acceptance cycles)
+       and for -l (non-progress cycles), and is independent of the
+       search mode (full state storage or bitstate hashing)
+       using -f may increase the time-complexity of a search, but
+       it does not alter the space requirements
+- specifying -f without either -a or -l would have no effect, so it
+  is considered an error.
+- you cannot combine options -a and -l
+- you can always combine -a with a never claim, but
+- you cannot combine -l with a never claim.
+- a harmless glitch in the setting of tau values for atomic moves
+  was fixed - it should not alter the behavior of the analyzers
+- another small fix in the reporting of unreachable code (previous versions
+  of spin could forget to report some of the states)
+- remember: to search for acceptance cycles, you always must
+  specify option -a now (or -f -a if restricted to fair cycles)
+
+=
+1.5.1 - 2/23/93
+- the acceptance cycle detector now starts the search for an acceptance
+  cycle after any move, whether in the claim or in the system
+  (until now, it only did so after a system move - which did not cover
+   all cases correctly, specifically for cases that are covered by the
+   claim stutter semantics, and for cases where acceptance cycles are only
+   defined inside the claim, and not in the system)
+1.5.2 - 3/1/93
+- the change from 1.5.1 was incorrect - a search from acceptence cycles
+  starts after system moves, or after stutter-claim moves, but not
+  for other claim moves (a stutter claim move is used to cycle the claim
+  in valid and invalid endstates - it triggers an error report if the claim
+  can cycle through an accept state in this case - it should not trigger
+  error reports in any other case)
+1.5.3 - 3/19/93
+- spin now catches SIGPIPE signals, and exits when it sees one.
+  added an option -X to use stdout instead of stderr for all error messages
+  (these upgrades are in preparation for an X-interface to spin)
+1.5.4 - 4/15/93
+- in simulation mode spin didn't always flag it as an error if an array-name
+  was used as a formal parameter in a proctype declaration (spin -a always
+  reports it correctly) - the error report is now given
+- added Xspin to the distribution as bundle4 - an X-interface to spin based
+  on the (public domain) toolkit Tcl/Tk from the university of berkeley.
+1.5.5 - 4/21/93
+- fixed an error in fair_cycle(); the original algorithm omitted to set
+  the correct value in a pointer to the current process during the fairness
+  checks - the result was that fairness calls were not always accurate.
+- some small improvements in the Xspin interface (call it XSPIN version 1.0.1)
+- improvement in sched.c - to match the assignemnts of pids to those of the validator
+1.5.6 - 5/21/93
+- another error in fair_cycle; code inserted for the detection of self-loops
+  was incorrect; it has been omitted.
+  non-fair cycles that can become fair *only* by the inclusion of a dummy
+       "do :: skip od"
+  loop in one of the processes may be missed in a verification using the -f flag.
+  since such busy-looping constructs are not (or should not be) used in Promela
+  anyway, this should not create problems
+- changed the data-types used in the hash-functions - to secure portability
+  of SPIN to 64 bit machines.
+1.5.7 - 7/1/93
+- fixed a subtle error that happens when a remote variable is used deeply nested inside
+  the index of another remote variable (array)
+- also fixed a spurious error report on array bound checking in such cases
+- both cases should be rare enough that it didn't bite anyone - they affected only
+  simulation mode
+1.5.8 - 10/1/93
+- made it an error to place a label at the first statement of a sub-sequence.
+  spin's optimization strategy (to speed up searches) can defeat such an
+  unconventional label placement easily, which can cause problems in remote references.
+  the rule is (and has actually always been) that constructs such as
+       do              if              atomic {
+       :: L: a = 1     :: L: a = 1             L: a = 1
+       od              fi              }
+  should be written as:
+       L: do           L: if           L: atomic {
+          :: a = 1        :: a = 1             a = 1
+          od              fi              }
+  the rule is now enforced.  to make it easier, the above message is printed if the
+  label is accidentily misplaced, in the heat of design...
+  note that the first state of a subsequence equals the state of the enclosing
+  construct (e.g., the start state of each option in a do-structure is the very
+  same state as the start state of the do-structure itself)
+1.5.9 - 11/17/93
+ A small error in the management of rendez-vous status during the search had
+ slipped in on 9/11/91.  finally caught and removed.
+1.5.10 - 11/19/93
+-spin attempts to optimize goto and break statements by removing them from
+ the transition matrix wherever possible.  this has no visible effect, other
+ then achieving an extra speedup of the validation.
+ in a small number of cases, though, the labels must be preserved
+ one such case is when a goto or break carries a progress, end, or accept label.
+ in that case the jump is preserved (that case was always treated correctly).
+ another case, that was overlooked so far, is when the label in front of a goto
+ is used in a remote reference, such as P[pid]:label.  the use is dubious, but
+ cannot be excluded. in 1.5.10 this case has been added to the exceptions - where
+ the gotos are not removed from the matrix.
+-also fixed: the never claim no longer steps in the middle of a rendez-vous handshake
+ (it was correctly observed by a user that it shoudln't - since its really atomic)
+-also fixed: the initial state of a newly started process in the simulator
+ now always matches that of the validator (same optimization steps are done)
+ the avoids some cases of lost trails in guided simulations
+1.5.11 - 2/1/94
+-the fix from 1.5.10 works by inserting a dummy skip statement in between
+ a label and the statement that follows it (a goto in this case)
+ that calls for an extra statement, with a unique state number
+ the extra state numbers weren't counted in the allocation of memory for the
+ transition matrix - which could cause some peculiar behavior in the (luckily)
+ few cases where this improvement kicked in.  it's fixed in this release.
+-another improvement, that had been waiting in the wings for a chance to make it
+ into the released version - is that the timeout variable is now testable inside
+ never claims (that wasn't true before).
+1.5.12 - 1/20/94
+-added a random number generator - compliments of Thierry Cattel.
+ as an alternative to the badly performing standard routines provided 
+ on most systems.  should improve simulations - affects nothing else.
+1.5.13 - 3/27/94
+-small improvement in handling of syntax errors in parser.
+-added clarifications to the file `roadmap' in bundle3
+-added manual.ps to the distribution
+1.5.14 - 4/22/94
+-until now you had to turn on message loss (-m) explicitly when following
+ a backtrace (using spin -t) from a system that was generated with message
+ loss enabled (i.e., with spin -a -m).  that is easy to forget.  spin -t no
+ longer explicitly requires the -m flag in these cases, to avoid confusion.
+ it is still valid to use -m in combination with -t, but not required.
+1.5.15 - 5/20/94
+-removed small bug from sched.c (the simulator) that could prevent a process
+ from being deleted correctly from the run queue when the last two processes die.
+1.5.16 - 6/3/94
+-if a goto jump inside an atomic sequence jumped to the last statement of the
+ sequence, spin would get confused and mark that jump as non-atomic
+ version 1.5.16 handles this case correctly
+-added an error production to the grammar - to improve syntax error reporting
+1.5.17 - 7/15/94
+-a remote reference to a non-existing variable could result in a core-dump
+ during guided simulations;  fixed in this version.
+1.5.18 - 8/1/94
+-during simulation a remote reference to a previously unused local variable
+ from another process would return the default 0 value - instead of the initial
+ value of such a variable.  this caused the behavior of validator and simulator
+ to differ in such cases (in the validator all variables are always created and
+ initialized upon process creation - in the simulator variables are created and
+ initialized in a `lazy' fashion: upon the first reference.
+ this is now fixed so that the simulator's behavior is now no different from
+ the validator: refering to a previously unused variable of a running process
+ returns its initial value - as it should.
+
+==== Version 1.6 - August 1994 ====
+
+1.6.0 - 8/5/94
+-Important improvement - Please Read!
+-it was always a problem to get ``mtype'' names used inside messages to
+ be distinguished properly from other integers in (guided) simulations.
+ the rule used so far was that if a message field held a ``constant''
+ it was interpreted and printed as an mtype name, and else as a value.
+
+ starting with version 1.6 this is handled better as follows:
+ if you declare a message field to have type ``mtype'' it is ALWAYS printed
+ as a symbolic name, never as a value. 
+ for example, you can now declare a channel as:
+       chan sender = [12] of { mtype, byte, short, chan, mtype };
+ so that the first and last field are always printed symbolically as a name,
+ never as a value.  only bits, bytes, shorts, and ints, are now printed
+ as values.
+ make good note of the change:  you will almost always want to use mtype
+ declarations for at least some of the fields in any channel declaration.
+ the new functionality greatly increases the clarity of tracebacks with spin -t
+
+-new compile time option cc -DPEG pan.c - to force the runtime analyzer to
+ gather statistics about how often each transition (the bracketed number in
+ the pan -d output) is executed.
+
+1.6.1 - 8/16/94
+-added a declaration of procedure putpeg, to avoid a compiler warning
+-made sure that booleans such as q?[msg] can be used in any combination
+ in assert statements (until now spin could insert newlines that spoiled
+ printfs on debugging output)
+
+1.6.2 - 8/20/94
+-tightened the parser to reject expressions inside receive statements.
+ so far these were silently accepted (incorrectly) - and badly translated
+ into pan.[mb] files.  the fields in a receive statement can legally only
+ contain variable-names or constants (mtypes).  variables are set, and
+ constant fields are matched in the receive.
+-cleaned up the enforcement of the MEMCNT parameter (the compile time parameter
+ that is used to set a physical memory limit at 2**MEMCNT bytes)
+ we now check *before* allocating a new chunk of memory whether this will
+ exceed the limit - instead of *after* having done so - as was the case so far.
+ gives a better report on which memory request caused memory to run out.
+
+1.6.3 - 8/27/94
+-the simulator failed to recognize remote label references properly.
+ has been fixed in sched.c.
+-the validator failed to report blocking statements inside atomic sequences
+ when a never claim was present - it defaulted to claim stutter instead.
+ it now correctly reports the error.
+
+1.6.4 - 9/18/94
+-in rare cases, an accept cycle could be missed if it can only be closed
+ by multiple claim stutter moves through a sequence of distinct claim states
+ this now works as it should.
+-added some helpful printfs that are included when the -DVERBOSE and -DDEBUG
+ compile time flags are used on pan.c's
+
+1.6.5 - 10/19/94
+-the mtype field of message queues wasn't interpreted correctly in
+ in the printout of verbose simulation runs (the field was printed
+ numerically instead of symbolically).
+
+1.6.6 - 11/15/94
+ minor fix in procedure call of new_state - to avoid compiler complaints
+ about use of an ANSI-isms in an otherwise pre-ANSI-C source.
+ (version 2.0 - see below) is completely ANSI/POSIX standard and will not
+ compile with pre-ANSI compilers.  version 1.6.6 is the last
+ version of SPIN that does not make this requirement.
+
+12/24/94
+ Version 1.6.6 is the last update of Spin Version 1.
+ The distribution will switch to Spin Version 2.0, and
+ all further updates will be documented in: Doc/V2.Updates.
diff --git a/trunk/verif/Spin/Doc/V2.Updates b/trunk/verif/Spin/Doc/V2.Updates
new file mode 100755 (executable)
index 0000000..bfca262
--- /dev/null
@@ -0,0 +1,1163 @@
+Distribution Update History of the SPIN sources
+===============================================
+
+==== Version 2.0 - 1 January 1995 ====
+
+The version published in the first printing of
+``Design and Validation of Computer Protocols''
+is nominally SPIN Version 1.0.
+
+SPIN version 2.0 includes a partial order reduction
+mode and many extensions and revisions that are
+documented in the file Doc/WhatsNew.ps of the
+distribution.  This file lists all updates
+made to these sources after the first release.
+
+===== 2.0.1 - 7 January 1995 ====
+
+An automatic shell script `upgrades' in the main
+SPIN directory will be maintained from now on.
+For all future updates it will suffice to retrieve
+just the upgrades file, and execute it in the Src
+directory to apply all changes.  The tar file will
+of course be kept up to date at all times as well.
+
+Changes in this update:
+1. MEMCNT can now grow larger than 2^31 - for those
+   happy users that have a machine with more than
+   a Gigabyte of main memory.
+   (N.B. this fix was made and distributed before the
+   upgrades file was started - so this one change isn't
+   available in that way)
+2. Change in the lexical analyzer to accept redundant
+   text at the end of preprocessor directives, that
+   some versions of cpp may produce.
+
+===== 2.0.2 - 10 January 1995 ====
+
+Two small updates to pangen1.h to avoid problems on
+some systems when (1) compiling pan.c with profiling
+enabled, or (2) when using the new predefined function
+enabled() in combination with partial order reduction.
+
+===== 2.0.3 - 12 January 1995 ====
+
+At request, added a printout of the mapping from label
+names as used in the Promela source to state numbers as
+used in the verifier to spin option -d.
+to see just this new part of the listing, say:
+       spin -d spec | grep "^label"
+first column is the keyword "label"
+second column is the name of the label
+third column is the state number assigned
+last column is the name of the proctype in which the
+label is used.
+the same state numbers and transitions are
+also used by the verifier, and can be printed as
+before with:
+       spin -a spec; cc -o pan pan.c; pan -d
+
+===== 2.0.4 - 14 January 1995 ====
+
+With the introduction of `else' a new opportunity for
+silly syntax mistakes is created.  it is all too tempting
+to write:
+       if
+       :: condition ->
+               more
+       :: else
+               something
+       fi
+and forgot the statement separator that is required between
+the `else' and `something'
+this likely typo is easy to recognize, and is silently
+repaired and accepted by the new lexical analyzer.
+
+===== 2.0.5 - 17 January 1995 ====
+
+transition labels for send and receive operations
+now preserve all the information from the source text
+(i.e., the symbolic names for all message parameters used).
+
+===== 2.0.6 - 27 January 1995 ====
+
+two fixes, both caught by Roberto Manione and Paola:
+- deeply nested structures (more than two levels)
+  could give syntax errors, and
+- the transition label of an `else' statement wasn't
+  always printed correctly in the traces.
+
+===== 2.0.7 - 2 February 1995 ====
+
+- another fix of the implementation of data structures
+  to make references of deeply nested structure work
+  the way they should
+- removed suboptimal working of safety marking of
+  atomic sequences.  reductions are now slightly
+  larger in some cases.
+- improved boundary checking of array indexing also
+  slightly (made it more efficient for some cases)
+
+===== 2.0.8 - 7 February 1995 ====
+
+- adjusted line number counting slightly in spinlex.c
+  to avoid annoying off-by-one errors.
+
+===== 2.0.9 - 9 February 1995 ====
+
+- removed a bug in the transition structures that are
+  generated for d_steps. (small fix in pangen2.h)
+
+===== 2.1 - 15 February 1995 ====
+
+- removed two errors in the implementation of d_steps:
+   one was related to the treatment of `else' during verification
+   another related to the execution of d_steps in guided simulations
+- improved the treatment of rendez-vous in SPIN verbose printings
+   improves match with xspin; avoids misinterpretation of pids
+- made mtype fields be interpreted uniformly in all SPIN modes
+- added message sequence charts in xspin
+- removed stutter-closedness checks from pangen2.h (no change
+  in functionality, just replaced a dubious check with a more
+  precise descriptive warning)
+
+===== 2.1.1 - 17 February 1995 ====
+
+- instantiated channels declared inside typedefs weren't
+  properly initialized
+
+===== 2.2 - 19 February 1995 ====
+
+- main extension of functionality:
+  added an interactive simulation mode (both in xspin and in spin itself)
+  that will be described at greater length in Newsletter #4.
+  also improved some of the printouts for verbose simulation runs.
+
+- added a precompiler directive -DREACH to force exploration of
+  all states reachable within N execution steps from the initial
+  system state, when the search is deliberately truncated with -mN.
+  normally such a truncated search does not give that guarantee.
+  (note that if a state at level N-1 is also reachable from the
+  initial state within 1 execution step, but it is reached via the
+  longer path first in the DFS - then all successors via the shorter
+  path would normally not be explored, because they succeed a
+  previously visited state. with -DREACH we remember the depth at
+  which a state was visited, and consider it unvisited when encountered
+  on a shorter path.  not compatible with BITSTATE - for the obvious
+  reason (no room to store the depth counts).
+
+- fixed a bug in pangen[24].c that could cause an internal consistency check
+  in the runtime verifiers to fail, and cause the run to terminate with
+  the error `sv_save failed'
+
+===== 2.2.1 - 23 February 1995 ====
+
+- small refinements to interactive simulation mode (xspin and spin)
+
+===== 2.2.2 - 24 February 1995 ====
+
+- added missing prototype in 2.2.1, and fix parameter mistake in a
+  function that was added in 2.2.1
+
+===== 2.2.3 -  3 March 1995 ====
+
+- bug fix in implementation of d_step (dstep.c)
+  and some mild improvements in error reporting
+
+===== 2.2.4 -  9 March 1995 ====
+
+- made sure process numbers assigned by simulator
+  are always the same as those assigned by the verifier
+- by request: added a binary exclusive-or operator ('^')
+
+===== 2.2.5 -  14 March 1995 ====
+
+- removed error in treatment of `else' during random simulation.
+  `else' was incorrectly considered to be executable also
+  in the middle of a rendez-vous handshake. no more.
+
+===== 2.2.6 -  21 March 1995 ====
+
+- made sure that variable declarations are reproduced in
+  the pan.c sources in the same order as they are given
+  in the original promela specification.  this matters
+  in cases where new variables are initialized with each
+  others values.
+- better error handling when a reference is made erroneously
+  to an assumed element of an undeclared structure
+
+===== 2.2.7 -  23 March 1995 ====
+
+- catches more cases of blocking executions inside d_step
+  sequences
+- better handling of timeout, when using both blocking
+  atomic sequences and never claims.  the behavior of the
+  simulator and the verifier didn't always match in these
+  cases.  it does now.
+
+===== 2.2.8 -  30 March 1995 ====
+
+- inside dstep sequences `else' wasn't translated correctly
+
+===== 2.2.9 -  12 April 1995 ====
+
+- removed a mismatch between spin and xspin in dataflow output
+- clarified the scope of dataflow checks spin's -? response
+- fixed a typo that could confuse pid assignments when -DNOCLAIM is used
+- improved some of spin's outputs a little for xspin's benefit
+
+===== 2.2.10 -  18 April 1995 ====
+
+- removed a redundancy in the creation of channel templates
+  during the generation of a verifier with spin option -a
+
+===== 2.3.0 -  19 April 1995 ====
+
+- an extension of functionality.  until now the simulator would execute
+  a receive test (for instance: q?[var1,var2] ) erroneously with
+  side-effects, possibly altering the values of the variables.
+  any boolean condition in Promela, however, must be side-effect free
+  and therefore the verifier had the correct implementation (no value
+  transfers in a test of executability of this type)
+  michael griffioen noted that the poll of a message in a channel was
+  nonetheless usefull.  this leads to a new type of operation in Promela.
+  pending more thorough documentation, here's an example of
+  each of the existing ones:
+
+  A.   q?var1,const,var2       - fifo receive (constants must be matched)
+                                 if successful, the message is removed
+                                 from the channel
+  B.   q??var1,const,var       - random receive (as A., but from any slot
+                                 that has a matching message, checked in
+                                 fifo order) if successful, the message is
+                                 removed from the channel
+  C.   q?[var1,const,var2]     - boolean test of executability of type A receive.
+  D.   q??[var1,const,var2]    - boolean test of executability of type B receive.
+  E.   q?<var1,const,var2>     - fifo poll, exactly as A, but the message is
+                                 not removed from the channel
+  F.   q??<var1,const,var2>    - random receive poll, exactly as B, but message
+                                 not removed from the channel
+
+  there are still only two different ways to test the executability of a
+  receive operation without side-effects (be it a normal receive or a poll
+  operation)
+  the two new operations of type E and F allow one to retrieve the contents
+  of a message from a channel, without altering the state of the channel.
+  all constant fields must of course still be matched, and if no variables
+  are present, an operation of type E has the same effect as one of type C.
+  (and similarly for types F and D)
+
+===== 2.3.1 -  20 April 1995 ====
+
+- slightly more conservative treatment for the change from 2.2.10
+  some redundancy is caused by the spec, and now flagged as warnings.
+  using a \ 5typedef structure that contains an initialized channel in
+  a formal parameter list, for instance, is always reduncant and uses
+  up channel templates in the verifier - without otherwise doing harm,
+  but there is a limit (255) to the number of templates that can exist.
+  the limit is now also checked and a warning is given when it is exceeded.
+
+===== 2.3.2 -  25 April 1995 ====
+
+- adjustment of output format of guided simulation to match a recent
+  change in Xspin (better tracking of printfs in MSC's)
+
+===== 2.3.3 -  29 April 1995 ====
+
+- bit or bool variables cannot be hidden - this is now reported as a
+  syntax error if attempted
+- the reporting of the options during interactive simulations is
+  improved - mysterious options, such as [ATOMIC] are now avoided better
+
+===== 2.3.4 -  1 May 1995 ====
+
+- added the keyword D_proctype as an alternative to proctype to
+  indicate that all the corresponding processes are expected to
+  be deterministic.  the determinism is not enforced, but it is
+  checked by the verifier.  no other difference exists.  a simulation
+  will not pick up violations of this requirement.
+
+===== 2.3.5 -  13 May 1995 ====
+
+- the check for enforcing determinism (2.3.4) was not placed
+  correctly.  it is now.
+
+===== 2.3.6 -  18 May 1995 ====
+
+- removed bug in code generation for arrays of bools
+- moved a debug-printf statement
+
+===== 2.3.7 -  18 May 1995 ====
+
+- removed bug in testing enabledness of run statements
+  during interactive simulations
+
+===== 2.3.8 -  19 May 1995 ====
+
+- small change in bitstate mode.  the verifier checks if a
+  new state is previously visited, or appears on the dfs stack.
+  (information about presence in the stack is only needed to
+   enforce the partial order reduction rules)
+  in both cases (in bitstate mode) the check is done via hashing
+  into a bitarray; with the array for the statespace much larger
+  than the one for the stack.
+  so far, if either match succeeded, the search was truncated.
+  any match in the stack-array that is combined with no-match in
+  the statespace array, however, is necessarily caused by a
+  hash-collision (i.e., is a false match) and can be discarded.
+  the coverage of bitstate runs should improve slightly by this
+  change.  nothing else will be affected.
+
+===== 2.4.0 -  22 May 1995 ====
+
+- new functionality: there is a new option to SPIN that
+  can be used in guided simulations (that is: in combination
+  with the option -t, when following a error trail produced
+  by one of the verifiers generated by SPIN)
+  for very lengthy trails, it can take a while to reach an
+  interesting point in the sequence.  by adding the option
+  -jN one can now skip over the first N steps in the trail
+  (more precisely: supress the printing during those steps)
+  and quickly get to the interesting parts.
+  for instance:
+       spin -t -p -g -l -v -j1000 spec
+  skips the first 1000 steps and prints the rest.
+  caveat: if there are fewer than 1000 steps in the trail,
+  only the last state of the trail gets printed.
+- avoiding some more redundant printouts during guided simulations
+  will also help to speed up the browsing of error trails with XSPIN
+- the extension is supported in the new version of XSPIN as well
+- the new version of XSPIN also supports BREAKPOINTS during
+  all types of simulation
+  breakpoints are supported via the MSC printf statements
+  *    including a printf that starts with the prefix "MSC: "
+       in a Promela Model will cause the remainder of the line
+       printed to be included as a box inside the MSC charts
+       maintined by XSPIN.
+  *    if the remainder of such a line contains the capitalized word
+       BREAK, the simulator will pause at that line and wait for
+       the user to reactivate the run (single step or run)
+
+===== 2.4.1 -  4 June 1995 ====
+
+- added runtime option -e to verifiers produced by SPIN.
+  with this option all errors encountered during the verification
+  are saved in a trail file - up to the limit imposed by -cN
+  (the default is one trail).  the first trail has the extension .trail,
+  as before (which is also the only extension expected right now under
+  the guided simulation option -t of SPIN). subsequent trails have
+  extensions .trail1, .trail2, ... etc.
+  use this option in combination with -cN
+       using -c5 -e will produce the first 5 trails,
+       using -c0 -e will produce all trails.
+- modified Xspin to work also with the new Tcl7.4/Tk4.0, which is now
+  in beta release.  the changes should not affect the working under
+  the current version Tcl7.3/Tk3.6
+- there is now a file called `version_nr' in the directory /netlib/spin
+  on the distribution server.  the file contains just the version
+  number from the currently distributed SPIN sources (avoids having to
+  download larger files to find out if anything changed)
+- added runtime option -hN to choose another than the default hash-function
+  (useful in bitstate mode.  N must be an integer between 1 and 32)
+- improved the implementation of the new runtime option -s (for selecting
+  single-bit hashing instead of the default double-bit hashing)
+  especially useful in combination with -hN for sequential multihashing
+  techniques (iterative approximation of exhaustive searches for very large
+  problem sizes)
+- starting with this version of Xspin there will also be a separate upgrades
+  script to keep the Tcl/Tk files up to date.
+
+===== 2.4.2 -  11 June 1995 ====
+
+- so far, variables were created and initialized in the simulator
+  as late as possible:  upon the first reference.  a variable that
+  is never referenced was therefore never created - which is some
+  sense of economy.  however, if the local is initialized with an
+  expression that includes references to other variables (local or
+  global) then those other variables might well change value before
+  the first reference to the initialized local is made - and thus
+  the local might obtain an unexpected initial value.
+  the error was caught by Thierry Cattel - and lazy variable creation
+  is now abandoned.  the verifier is unaffected by this fix -- it
+  already id the right thing (instant creation of all locals on process
+  initialization).
+- channels deeply hidden inside structures were not properly logged
+  in the partial order reduction tables.  it could cause an abort of
+  a verification run with the mysterious error "unknown q_id, q_cond."
+  it works properly now.  error caught by Greg Duval.
+- made a small change in output format (comments only) for remote
+  references
+- made the new runtim option -e (from version 2.4.1) also accessible
+  from within XSPIN
+- changed the MSC canvas in the simulation mode of XSPIn to no longer
+  be self-scrolling (it defeated any attempt from the user to select
+  other portions of the MSC to ponder, other than the tail, during a
+  run).  also made the message transfer arrows wider - and added an
+  option to replace the symbolic step numbers in the MSC's with source
+  text.
+
+===== 2.5 -  7 July 1995 ====
+
+Fixes
+- values of rendez-vous receives were printed incorrectly in printouts
+  of spin simulation runs - this could confuse xspin; the symptom was that
+  some rendez-vous send-recv arrows were not drawn in the MSC displays.
+- rendez-vous operations that guarded escapes did not always execute
+  properly in random simulations.
+- in xspin, the boxes produced by an MSC printf could lose its text
+  after the cursor would pass over it - that's no longer the case
+- the use of a remote references used to disable the partial order
+  reduction algorithm.  instead, such references now automatically label
+  the transition that enters or exits from the corresponding process state
+  as unsafe.  this suffices to preserve the use of the partial order
+  reduction.  (proposed by Ratan Nalumasu.)
+
+Small Changes
+- added a print line in verbose output for process creations - as well
+  as process terminations.  it will be used in a future version of xspin.
+- made all xspin verification run timed - the user+system time info
+  appears in the xspin logs
+- on aborted verification runs, xspin will now also print the partial
+  information gathered up to the point of the abort
+- slightly changed the way aborts are handled in xspin
+- never claims containing assignments (i.e., side-effects) can be useful
+  in some cases.  spin will still generate warnings, but allows the user
+  to ignore them (i.e., the exit status of spin is no longer affected)
+- in simulation mode - xspin now pays attention to filenames and will not
+  try to hilight lines in files that are not visible in the main text window
+- added compile-time directive -DNOFAIR to allow compilation of a verifier
+  if it is known that the weak-fairness option will not be used -- this
+  avoids some memory overhead, and runs slightly faster.
+  the fastest run can be obtained by compiling -DNOCOMP -DNOFAIR (turning
+  off the state compression and the weak fairness related code)
+  the most memory frugal run (apart from the effects of -DREDUCE) can be
+  obtained by compiling with just -DNOFAIR (and leaving compression turned
+  on by default)  note that memory consumed also goes up with the value
+  provided for the -m option (the maximum depth of the stack)
+- added a file Doc/Pan.Directives with an overview of all user definable
+  compile-time directives of the above type.
+
+Extension
+- added a mechanism to define process priorities for use during random
+  simulations - to make high priority processes more likely to execute
+  than low priority processes.
+  as alternatives to the standard:
+       run pname(...)
+       active proctype pname() { ... }
+  you may now add a numeric execution priority:
+       run pname(...) priority N
+  and/or
+       active proctype pname() priority N
+  (with N a number >= 1)
+  the default execution priority is 1; a higher number indicates a
+  higher priority.  for instance, a priority 10 process is 10x more
+  likely to execute than a priority 1 process, etc.
+  the priority specified at the proctype declaration only affects the
+  processes that are initiated through the `active' prefix
+  a process instantiated with a run statement always gets the priority
+  that is explicitly or implicitly specified there (the default is 1).
+  the execution priorities have no effect during verification, guided,
+  or interactive simulation.
+- added an example specification file (Test/priorities) to verify the
+  correct operation of the execution priorities
+
+===== 2.5.1 -  12 July 1995 ====
+
+- some tweaks to correct the last update (a simulation run could
+  fail to terminate - and xspin could fail to detect the zero exit
+  status of spin after warning messages are printed)
+
+===== 2.6 -  16 July 1995 ====
+
+- added a new option for executable verifiers - to compute the effective
+  value range of all variables during executions.
+  the option is enabled by compiling pan.c with the directive -DVAR_RANGES
+  values are tracked in the range 0..255 only - to keep the memory
+  and runtime overhead introduced by this feature reasonable.
+  (the overhead is now restricted to roughly 40 bytes per variable -
+   it would increase to over 8k per variable if extended to the full
+   range of 16-bit integers)
+- a new option in the validation panel to support the above extension
+  was added
+- xspin now supports compile-time option -DNOFAIR to produce faster
+  verifiers when the weak fairness option is not selected
+- added an example in directory Test to illustrate dynamic creation
+  of processes (Test/erathostenes)
+- removed an error message that attempted to warn when a data structure
+  that contained an initialized channel was passed to a process as a
+  formal parameter.  it leads to the creation of a redundant channel,
+  but is otherwise harmless.
+- changed the data types of some option flags from int to short
+
+===== 2.6.1 -  18 July 1995 ====
+
+- option -jN (introduced in version 2.4.0) -- to skip the verbose
+  printouts for the first N execution steps -- now also works in
+  random simulation mode.
+  only process creations and terminations are still always printed
+- channel names are no longer included in the -DVAR_RANGES output
+  at least not by default (see version 2.6 - above)
+  to still include them, generate the verifier in verbose mode
+  as ``spin -a -v spec'' instead of the default ``spin -a spec''
+- predefined variable _last was not quite implemented correctly
+  in the verifier (the error was harmless, but if you tried to write
+  specifications that included this construct, you may have had
+  more trouble than necessary getting it to work properly)
+
+===== 2.7.Beta -  24 July 1995 ====
+
+Fixes
+- when an atomic sequence blocks, the process executing that sequence
+  loses control, and another process can run.  when all processes block,
+  the predefined variable 'timeout' becomes true, and all processes again
+  get a chance to execute.  if all processes still block - we have reached
+  an end-state (valid or invalid, depending on how states are labeled).
+  until now, timeout was allowed to become true before an atomically
+  executing process could lose control - this is not strictly conform the
+  semantics given above, and therefore no longer possible.
+- it is now caught as a runtime error (in verification) if an attempt
+  is made to perform a rendez-vous operation within a d_step sequence.
+- it is also caught as an error if a 'timeout' statement is used inside
+  a d_step sequence (it may be used as the first statement only)
+- an else statement that appears jointly with i/o statements in
+  a selection structure violates the rules of a partial order
+  reduction.  a warning is now included if this combination is seen, both
+  at compile-time and at run-time.  the combination should probably be
+  prevented alltogether since its semantics are also not always clear.
+- one more correction to the implementation of 'else' inside dsteps
+  to avoid a possibly unjustified error report during verification
+- a previously missed case of the appearance of multiple 'else' statements
+  in selection structures is now caught and reported
+- fixed a missing case were process numbers (_pid's) did not match
+  between a verification run and a guided simulation run. (if a never
+  claim was used, there could be an off-by-one difference.)
+- rendez-vous operations are now offered as a choice in interactive
+  simulation mode only when they are executable - as they should be
+- the introduction of active proctypes in 2.5 introduced an obscure
+  line-number problem (after the first active proctype in a model
+  that contains initialized local vars, the line numbers could be
+  off). it's fixed in this version.
+
+Extensions
+- The main extension added in this release is the inclusion of an
+  algorithm, due to Gerth, Peled, Wolper and Vardi, for the translation
+  from LTL formulae into Promela never claims.  The new options are
+  supported both in SPIN directly, and from XSPIN's interface.
+
+- added the option to specify an enabling condition for each
+  proctype.  the syntax is as follows:
+        proctype name(...) provided ( expression )
+        {
+                ...
+        }
+  where the expression is a general side-effect free expression
+  that may contain constants, global variables, and it may contain
+  the predefined variables timeout and _pid, but not other local
+  variables or parameters, and no remote references.
+
+  the proctype may be declared active or passive.  no enabling
+  conditions can be specified on run statements unfortunately.
+  the provided clauses take effect both during simulation runs
+  and during verification runs.
+
+- extended XSPIN with a barchart that can give a dynamic display
+  of the relative fraction of the system execution that is used by
+  each process.  modified the layout of the Simulation option panel,
+  to make some of the runtime display panels optional.
+
+- added a <Clear> button to most text windows (to clear the contents
+  of the display)
+
+- added <Larger> and <Smaller> scaling buttons to canvas displays
+  (that is: the FSM view displays and the MSC display).  the buttons
+  show up when the image is complete (e.g., when the message sequence
+  chart has been completed) - so that it can be scaled to size as a
+  whole.
+
+- added new <Help> buttons, with matching explanations, to most display
+  panels - and updated and extended the help menus.
+
+===== 2.7 -  3 August 1995 ====
+
+- fixed possible memory allignment problem on sun sytems
+- several fine tunings of xspin
+- made it possible to let the vectorsize get larger than 2^15 bytes
+  to support very large models
+- a provided clause has no effect inside d_step sequences, but it
+  is looked at during atomic sequences.  this rule is now enforced
+  equally in simulation and validation.
+- the use of enabled() and pc_value() outside never claims now triggers
+  a warning instead of an error message (i.e., it is now accepted).
+  in models with synchronous channels, the use of enabled() still makes
+  verification impossible (both random and interactive simulations will
+  work though)
+- added an option to `preserve' a message sequence chart across
+  simulation runs (by default, all remnants of an old run are removed)
+
+===== 2.7.1 -  9 August 1995 ====
+
+- removed bug in the code that implements the compile time directive
+  to verifier source -DNOFAIR, which was introduced in version 2.5,
+  (and picked up starting with version 2.6 also via xspin).
+
+===== 2.7.2 -  14 August 1995 ====
+
+- the LTL formula parser accidentily swapped the arguments of U and V
+  operators.  it does it correctly now.  the associativity of U and
+  V now defaults to left-associative.
+- arithmetic on channel id's was so far silently condoned.
+  it is now flagged as an error.  it is still valid to say: c = d,
+  if both c and d are declared as chan's, but d may no longer be
+  part of an expression.
+- unless operators now distribute properly to (only) the guard of
+  d_step sequences (but not into the body of the d_step).
+
+===== 2.7.3 -  15 August 1995 ====
+
+- tweek in implementation of provided clauses - to make it possible
+  to use `enabled()' inside them.
+
+===== 2.7.4 -  25 September 1995 ====
+
+- fixed a small omission in the implementation of dsteps
+- allowed `else' to be combined with boolean channel references
+  such as len and receive-poll
+- added some compiler directives for agressively collapsing
+  the size of state vectors during exhaustive explorations.
+  this option is still experimental
+- made some cosmetic changes in the look and feel of xspin
+
+===== 2.7.5 -  7 October 1995 ====
+
+- the value returned by a run statement triggered and
+  unwarranted error report from spin, if assigned to a variable
+- xspin didn't offer all possible choices in the menus, when
+  used in interactive simulation mode
+- somewhat more careful in closing file descriptors once they
+  are no longer needed (to avoid running out on some systems)
+- some small cosmetic changes in xspin (smaller arrows in the
+  message sequence chart - to improve readability)
+
+===== 2.7.6 -  8 December 1995 ====
+
+- added a compiler directive PC to allow for compiling the
+  SPIN sources for a PC.  (this is only needed in the makefile
+  for spin itself - not for the pan.? files.)
+  if you generate a y.tab.c file with yacc on a standard Unix
+  machine, you must replace every occurrence of y.tab.[ch]
+  with y_tab.[ch] in all the spin sources as well before compiling.
+  some of the source file names also may need to be shortened.
+- some syntax errors reported by spin fell between the cracks
+  in xspin simulations.  they are now correctly reported in the
+  simulation window and the log window.
+- in interactive simulation mode - typing `q' is now a recognized
+  way to terminate the session
+- option -jN (skip output for the first N steps) now also works
+  for interactive simulations.  the first N steps are then as in
+  a random simulation.
+- FSMview in xspin is updated to offer also the statemachine
+  view for never claims - and to suppress the one for an init
+  segment, if none is used
+- fixed a bug in implementation of hidden structures - some of
+  the references came out incorrectly in the pan.c code
+
+===== 2.7.7 -  1 February 1996 ====
+
+- made it possible to combine the search for acceptance cycles
+  with one for non-progress cycles, to find cycles with at least
+  one accepting state and no progress states.
+  the combined search is compatible with -f (weak fairness).
+  [note added at 2.8.0 -- this wasn't completely robust, and
+   therefore undone in 2.8.0]
+- added the explicit choice for the specification of a positive
+  or a negative property in LTL interface to xspin
+- fixed a bug in the ltl translator (it failed to produce the correct
+  automaton for the right-hand side of an until-clause, if that clause
+  contained boolean and-operators)
+- in non-xspin mode, process states are now identified as <endstates>
+  (where applicable) in the simulation trails
+- it is now flagged as an error if a `run' statement is used
+  inside a d_step sequence
+- added two new options ( -i and -I ) for the generated verifiers
+  (pan -i / pan -I).  recommended compilation of pan.c is with -DREACH
+  for exhaustive mode (-DREACH has no effect on BITSTATE mode).
+  option -i will search for the shortest path to an error.
+  the search starts as before - but when an error is found, the
+  search depth (-m) is automatically truncated to the length of that
+  error sequence - so that only shorter sequences can now be
+  found.  the last sequence generated will be the shortest one possible.
+  option -I is more aggressive:  it halves the search depth
+  whenever an error is found, to try to generate one that is at most
+  half the length of the last generated one.
+  if no errors are found at all, the use of -i or -I has no effect on
+  the coverage of search performed (but the effect of using -DREACH
+  is an increase in memory and time used, see the notes at version 2.2).
+
+===== 2.7.8 -  25 February 1996 ====
+
+Extensions
+- a new runtime option on the verifiers produced by Spin is -q
+  it enforces stricter conformance to what is promised in the book.
+  by default, the verifiers produced by Spin require each process to have
+  either terminated or be in a state labeled with an endstate-label, when
+  the system as a whole terminates.   the book says that for such a state
+  to be valid also all channels must be empty.  option -q enforces that
+  stricter check (which is not always necessary).  the option was suggested
+  by Pim Kars of Twente Univ., The Netherlands.
+- `mtype' is now a real data-type, that can be used everywhere a `bit'
+  `byte' `short' or `int' data-type is valid.
+  variables of type `mtype' can be assigned symbolic values from the range
+  declared in mtype range definitions (i.e.: mtype = { ... }; ).
+  the value range of an mtype variable (global or local) remains equal
+  to that of a `byte' variable (i.e., 0..255).
+  for instance:
+       mtype = { full, empty, half_full };
+       mtype glass = empty;
+  the extension was suggested by Alessandro Cimatti, Italy.
+- the formfeed character (^L or in C-terms: \f) is now an acceptable
+  white space character -- this makes it easier to produce printable
+  promela documents straight from the source (also suggested by Cimatti).
+- a new predefined and write-only (scratch) variable is introduced: _
+  the variable can be assigned to in any context, but it is an error to
+  try to read its value. for instance:
+       q?_,_,_;        /* to remove a message from q */
+       _ = 12;         /* assign a value to _ (not very useful) */
+  the value of _ is not stored in the state-vector
+  it may replace the need for the keyword `hidden' completely
+  the syntax was suggested by Norman Ramsey (inspired by Standard ML)
+
+Fixes
+- the FSM-view mode in xspin wasn't very robust, especially when moving
+  nodes, or changing scale.  it should be much better now.  button-1 or
+  button-2 can move nodes around.  click button-1 at any edge to see
+  its edge label (it no longer comes up when you hover over the edge -
+  the magic point was too hard to find in many cases).
+- fixed bug in processing of structure names, introduced in 2.7.5, caught
+  by Thierry Cattel, France.
+- trying to pass an array hidden inside a structure as a parameter
+  to a process (in a run statement) was not caught as a syntax error
+- trying to pass too many parameters in same also wasn't caught
+- in interactive mode, the menus provided by xspin were sometimes
+  incorrect for interactions in a rendez-vous system, caught by Pim Kars.
+
+===== 2.8.0 -  19 March 1996 ====
+
+- new version of the Spin sources that can be compiled, installed, and
+  used successfully on PC systems running Windows95.
+  (Because of remaining flaws in the latest Tcl/Tk 7.5/4.1 beta 3
+   release, Xspin will not run on Windows 3.1 systems.  Spin itself
+   however will work correctly on any platform.)
+  to compile, you'll need the public domain version of gcc and yacc for PCs,
+  (see README.spin under Related Software, for pointers on where to
+  get these if you don't already have them)
+
+  to use Spin on a PC, compile the Spin sources with directive -DPC
+  (if you have no `make' utitility on the PC, simply execute the
+  following three commands to obtain a spin.exe
+       byacc -v -d spin.y
+       gcc -DPC *.c -o spin
+       coff2exe spin
+  alternatively, use the precompiled spin.exe from the distribution
+  (contained in the pc_spin280.zip file)
+
+- small extension of xspin - lines with printf("MSC: ...\n") show up
+  in xspin's graphical message sequence chart panel. the colors can now
+  also be changed from the default yellow to red green or blue,
+  respectively, as follows;
+       printf("MSC: ~R ...\n")
+       printf("MSC: ~G ...\n")
+       printf("MSC: ~B ...\n")
+  (suggested by Michael Griffioen, The Netherlands)
+- small changes to improve portability and ANSI compliance of the C code
+- compile-time option -DREDUCE (partial order reduction) is now the
+  default type of verification.  both spin and xspin now use this default.
+  to compile a verifier without using reduction, compile -DNOREDUCE
+- missed case of syntax check for use of _ as lvalue corrected
+- missed case of printing mtype values in symbolic form also corrected
+- printfs no longer generate output during verification runs
+  (this was rarely useful, since statements are executed in DFS search
+  order and maybe executed repeatedly in seemingly bewildering order)
+  a compile time directive -DPRINTF was added to suppress this change
+  (this may be useful in debugging, but in little else)
+  this relies on stdarg.h being available on your system - if not, compile
+  Spin itself with -DPRINTF, and the new code will not be added.
+
+===== 2.8.1 -  12 April 1996 ====
+
+- we found a case where the partial order reduction method
+  introduced in Spin version 2.0 was not compatible with
+  the nested depth-first search method that Spin uses for
+  cycle detection (i.e., runtime options -a and -l)
+  the essence of the problem is that reachability properties
+  are affected by the so-called `liveness proviso' from the
+  partial order reduction method.  this `liveness proviso'
+  acted on different states in the 1st and in the 2nd dfs,
+  which could affect the basic reachability properties of states.
+  the problem is corrected in 2.8.1.  as a side-effect of this
+  upgrade, a few other problems with the implementation of the
+  nested depth first searches were also corrected.  in some cases
+  the changes do cause an increase of memory requirements.
+  a new compiler directive -DSAFETY is added to make sure that
+  more frugal verifiers can be produced if liveness is not required.
+- other fixes - one small fix of interactive simulation mode -
+  some small fixes to avoid compiler warnings in tl_parse.c -
+  a fix in pangen3.h to avoid a compile-time error for a few
+  cases of index bound-checking. small fixes in tl_buchi and
+  tl_trans to correct treatment of "[]true" and "[]false"
+- cosmetic changes to the xspin tcl/tk files
+
+===== 2.8.2 -  19 April 1996 ====
+
+- revised Doc/WhatsNew.ps to match the extensions in the
+  current version of the software
+- one more change to the algorithm for acceptance cycle detection
+- changed filenames for multiple error-trails (to ease use on PCs)
+  from spec.trail%d to spec%d.trail
+- some small changes to improve portability
+
+===== 2.8.3 -  23 April 1996 ====
+
+- corrected a missed optimization in the new acceptance cycle detection
+  algorithm from 2.8.[12]
+- corrected a problem with blocking atomic sequences in pangen1.h
+- added a predefined function predicate np_
+  the value of np_ is true if the system is in a non-progress state
+  and false otherwise.  (claim stutter doesn't count as non-progress.)
+  np_ can only be used inside never claims, and if it is used all
+  transitions into and out of progress states become visible/global
+  under the partial order reduction
+- background:
+  the intended purpose of np_ is to support a more efficient check
+  for the existence of non-progress cycles. (the efficient check we
+  had was lost with the changes from 2.8.[12])  instead of the default
+  check with runtime option -l, a more efficient method (under partial
+  order reduction) is to use the never claim:
+       never {
+               /* non-progress: <>[] np_ */
+               do
+               :: skip
+               :: np_ -> break
+               od;
+       accept: do
+               :: np_
+               od
+       }
+  and to perform a standard check for acceptance cycles (runtime
+  option -a) -- the partial order reduction algorithm can optimize
+  a search for the existence of acceptance cycles much better than
+  one for non-progress cycles.
+  a related advantage of searching for non-progress cycles with an
+  LTL property is that the LTL formula (<>[] np_) can easily be
+  combined with extra LTL properties, to built more sophisticated
+  types of searches.
+
+===== 2.8.4 -  25 April 1996 ====
+
+- cycles are closed at a different point in the dfs with the change from
+  2.8.[12], as a result, the cycle-point was no longer accurate - which
+  could be confusing.  fixed
+- all moves through progress states and accepting states within the program
+  are visible under the partial order reduction rules.  it is unlikely that
+  one would use extra accept labels in a program, if an LTL property or a
+  never claim with accept labels is used, but just in case, this is covered.
+
+===== 2.8.5 -  7 May 1996 ====
+
+- process creation and process deletion are global actions
+  they were incorrectly labeled as safe/local actions for the
+  purposes of partial order reduction.  they are global, because
+  the execution of either one can change the executability of
+  similar actions in other processes
+- didn't catch as an error when too many message parameters are
+  specified in a receive test q?[...] (in verifications).
+  it was reported in all other cases, just not for queue tests
+  (the simulator reported it correctly, when flag -r is used)
+- peculiar nestings of array and non-array structure elements
+  could generate incorrect code
+- with fairness enabled (-f), cycles were sometimes closed at the
+  wrong place in the runtime verifiers.
+- a variable initialized with itself could cause spin to go into
+  an infinite loop.  the error is now caught properly.
+
+===== 2.8.6 -  17 May 1996 ====
+
+- timeout's weren't always marked as global actions in partial
+  order reductions - they are now -- this can cause a small increase
+  in the number of reached states during reduced searches
+- fixed error that could cause a coredump on a remote reference
+  during guided simulations (reported by Joe Lin, Bellcore)
+- improved the efficiency of partial order search for acceptance
+  cycles in bitstate mode. (for non-progress cycles, though, we still
+  can't take much advantage of reduction during bitstate searches)
+- fixed the error that caused the extent of a cycle not to be
+  marked correctly in bitstate mode (the trails were always correct,
+  but the cycle point was sometimes placed incorrectly)
+- fixed error that could cause non-existent acceptance cycles to
+  be produced in bitstate mode (hopefully the last aftershock from
+  the correction of the cycle detection method in version 2.8.1)
+
+===== 2.9.0 -  14 July 1996 ====
+
+- Important Change:
+  Spin now contains a predefined never claim template that captures
+  non-progress as a standard LTL property (it is the template described
+  under the notes for 2.8.3 above)
+  this made it possible to unify the code for -a and -l;  it brings
+  option -l (non-progress cycle detection) within the same automata
+  theoretic framework as -a;  and it secures full compatibility of
+  both options -a and -l with partial order reduced searches.
+
+  compiled versions of pan.c now support *either* -a *or* -l, not both
+
+  by default, the verifiers check for safety properties and standard
+  buchi acceptance (option -a).
+  to search for non-progress cycles (i.e., to *replace* option -a with
+  option -l), compile the verifier with the new directive -DNP
+- Xspin 2.9.0 supports this change, and makes it invisible to the user.
+
+- the state vector length is now added explicitly into the state vector.
+  in virtually all cases this is redundant, but it is safer.
+  it can optionally be omitted from the state vector again (saving
+  4 bytes of overhead per state) with the new compiler directive -DNOVSZ
+
+- the verifiers didn't allow a d_step sequence to begin with a
+  rendez-vous receive operation.  that's now fixed.
+
+- change in the as-yet non-documented mode for extra agressive
+  state compressions (added in version 2.7.4, not enabled yet for
+  normal use - more information on this mode will come later)
+
+- assignments to channel variables can violate xr/xs assertions.
+  there is now a check to catch such violations
+
+- updated the PC executable of xspin for the newer current version of
+  gcc - updated the readme files to match the above changes
+
+- added the code for handling the Next Operator from LTL.  the code is
+  not yet enabled (to enable it, compile the sources with -DNXT added).
+  note that when partial order reduction is used this operator cannot
+  be used.  we'll figure out the appropriate warnings and then enable
+  the code (i.e., when you use it, you must compile pan.c with -DNOREDUCE).
+- in the process of this update, we also caught a bug in the translation
+  of LTL formulae into never claims (affecting how the initial state of
+  the claim was encoded).  the implementation has meanwhile been subjected
+  to a more thorough check of the correctness of the translation -- using
+  another model checker (cospan) as a sanity check. (both model checkers
+  have passed the test)
+
+===== 2.9.1 -  16 September 1996 ====
+
+- no major changes - some purification and minor fixes
+- updated email address for bug reports to bell-labs.com in
+  all source files
+- disallowed remote references inside d_step sequences
+  (the verifier has no problem, but the simulator may
+  resolve these differently can cause strange guided
+  simulation results)
+- provided some missing arguments to a routine in pangen1.c
+  that could trigger compile time errors before
+- improved the COLLAPSE modes to be slightly more frugal
+- added explicit casts from shorts to ints to avoid warnings
+  of some compilers...  also fixed a possible bad reference
+  to the stack if an error is found in the first execution step
+- fixed a case where the cycle-extent wasn't set correctly
+  (found by stavros tripakis)
+- write and rewrite just a single trail-file for options -[iI]
+  (instead of numbered trails)
+- fixed a bug in weak fairness cycle detection that had crept
+  in with the overhaul from version 2.8
+- fixed order of variable initialization in simulator (can
+  make a difference if a local variable is initialized with
+  the value of a parameter, which should now work correctly)
+- expanded the number of options accessible through Xspin
+
+===== 2.9.2 -  28 September 1996 ====
+
+- with a -c0 flag, the 2.9.1 verifiers would still stop at the
+  first error encountered, instead of ignoring all errors.
+  has been corrected (-c0 means: don't stop at errors)
+- corrected the instructions and the numbers in Test/README.tests
+  for the current version of spin (for leader and pftp there are
+  some small differences)
+
+===== 2.9.3 -  5 October 1996 ====
+
+- added a function eval() to allow casting a variable name into
+  a constant value inside receive arguments.  this makes it possible
+  to match a message field with a variable value, as in
+       q?eval(_pid),par2,par3
+  until now, only constant values could be matched in this way.
+  note that in the above example the value of _pid does not change,
+  but it guarantees that the receive is unexecutable unless the first
+  message parameter is equal to the value of variable _pid
+  eval() can be used for any message field - the argument must be a
+  (local or global) variable reference (not be a general expression).
+- in the process, discovered that global references inside the parameter
+  list of send or receive statements would not be detected for the
+  marking of safe and unsafe statements for the partial order reduction.
+  this is now corrected - it may lead to a small increase in the number
+  of reachable states under partial order reduction
+
+===== 2.9.4 -  4 November 1996 ====
+
+- the order of initialization of parameters and local variables after
+  a process instantiation was incorrect in the verifier - this could
+  be noticed when a local var was instantiated with a formal parameter
+  inside the variable declaration itself (the verifier failed to do this).
+- added a missing case for interpreting eval() in run.c (see 2.9.3)
+- removed possible erroneous behavior during interactive simulations
+  when a choice is made between multiple rendez-vous handshakes
+- added SVDUMP compiler directive and some extra code to allow for the
+  creation of a statespace dump into a file called sv_dump
+- added an option in Xspin to redraw the layout of an FSM-view using
+  the program 'dot' -- the option automatically enables itself if xspin
+  notices that 'dot' is available on the host system (an extra button
+  is created, giving the redraw option)
+
+===== 2.9.5 -  18 February 1997 ====
+
+- thoroughly revised -DCOLLAPSE -- it can now be used without
+  further thought to reduce memory requirements of an exhaustive run
+  by up to 80-90% without loss of information.  the price is an
+  increase in runtime by 2x to 3x.
+- added new compiler directives -DHYBRID_HASH and -DCOVEST
+  (both for experimental use, see the Pan.Directives file)
+- renamed file sv_dump (see 2.9.4) to 'spec'.svd, for compatibility
+  with PCs
+- removed spin's -D option (dataflow).  it was inaccurate, and
+  took up more source code than warranted (300 lines in main.c and
+  another 60 or so in Xspin)
+
+===== 2.9.6 - 20 March 1997 ====
+
+- bug fix -- for vectorsizes larger than 1024 the generated
+  code from 2.9.5 contained an error in the backward execution
+  of the transition for send operations.  (this did not
+  affect the verification unless a compiler directive -DVECTORSZ=N
+  with N>1024 was used -- which triggered an error-report)
+- sometimes one may try typing 'pan -h' instead of 'pan -?'
+  to get the options listing of the verifiers.  this now gives
+  the expected response.
+- previous versions of the spin Windows95 executable in pc_spin*.zip
+  were compiled as 16-bit executable -- the current version is a
+  32-bit executable.  the newer versions of tcl/tk actually care
+  about the difference and will hang if you try to do a simulation
+  run with one of the older spin executables installed...
+- discrepancy in the stats on memory use reported at the end of a
+  bitstate run corrected.
+- new xspin295 file that corrects a problem when xspin is used on
+  unix systems with a file name argument (it reported an undeclared
+  function).
+
+===== 2.9.7 - 18 April 1997 ====
+
+- spin now recognizes a commandline option -P that can be used to
+  define a different preprocessor.  the default behavior on Unix
+  systems corresponds to:
+       spin -P/lib/cpp [..other options..] model
+  and on solaris systems:
+       spin -P/usr/ccs/lib/cpp [..other options..] model
+  (note, these two are the defaults, so these are just examples)
+  use this option to define your own preprocessor for Promela++ variants
+- bitstate mode can be made to hash over compressed state-vectors
+  (using the byte-masking method).  this can improve the coverage
+  in some cases. to enable, use -DBCOMP
+- -DSVDUMP (see 2.9.4) now also works in -DBITSTATE mode
+- added compiletime option -DRANDSTORE=33 to reduce the probability of
+  storing the bits in the hasharray in -DBITSTATE mode to 33%
+  give an integer value between 0 and 99 -- low values increase
+  the amount of work done (time complexity) roughly by the reverse
+  of the probability (i.e., by 5x for -DRANDSTORE=20), but they also
+  increase the effective coverage for oversized systems. this can be
+  useful in sequential bitstate hashing to improve accumulative coverage.
+- combined the 3 readme-files into a single comprehensive README.
+
+===== 3.0.0 - 29 April 1997 ====
+
+- new additions to Spin's functionality that motivates upping the
+  version number to 3.0:
+
+       1. a new BDD-like state compression option based on
+          the storage of reachable states in an automaton,
+          combined with a checkpoint/recovery option for long runs.
+          for the automata based compression, compiled -DMA=N
+               with N the maximum length of the statevector in bytes
+               expected (spin will complain if you guess too low)
+          for checkpointing, compile -DW_XPT
+               to get a checkpoint file written out every multiple
+               of one million states stored
+          for restarting a run from a checkpoint file, compile -DR_XPT
+
+       2. addition of "event trace" definitions. for a description
+          see Section 4 of the extended WhatsNew.ps
+
+       3. addition of a columnated simulation output mode
+          for raw spin that mimicks the view one could so
+          far only obtain with through the intermediacy of
+          xspin. to use, say:
+               spin -c spec (or spin -t -c spec)
+          there is one column per running process.  message send
+          or receive events that cannot be associated with a process
+          for any reason are printed in column zero.
+
+       4. addition of a Postscript output option to spin.
+          this can be used to create a postscript file for a message
+          flow of a simulation, without needing the intervention of
+          xspin (which can be slow).
+               spin -M spec
+          generates the message flow in file spec.ps
+          also supported is:
+               spin -t -M spec
+          to convert an error trail into postscript form.
+
+       5. addition of the ability in Xspin to automatically
+          track variable values -- by prefixing their declaration
+          in Promela with the keyword "show", e.g. "show byte cnt;"
+          also added: automatic tracking of the state changes in
+          the never claim, if present, during guided simulations
+          (i.e., when inspecting an error.trail produced by the
+          verifier)
+
+       6. addition of an option to convert LTL formula stored in files.
+
+       7. Xspin is now compatible with Windows95 and WindowsNT
+
+smaller, changes
+       - spin generates hints when the data-type of a variable is
+         over-declared (i.e., it will detect the use of integers for
+         storing booleans etc.)
+       - the spin -d output for structure variables now includes the
+         name of the structure declaration (as the 3rd field, which
+         was unused in this case) to make the listings unambiguous.
+         [change from Frank Weil]
+       - spin -t can now take an argument.  without an argument
+               spin -t spec opens spec.trail
+               spin -t4 opens spec4.trail
+         (multiple trails are generated with runtime option
+               pan -c0 -e)
+       - bugfix: local channels were not always restored correctly to
+         their previous state on the reverse move of a process deletion
+         in the verification (i.e., the deletion of the process to which
+         those channels were local).
+       - bugfix: stutter moves were only done in the 2nd dfs, to close
+         cycles. this has to be done in both 1st and 2nd, to avoid missing
+         the valid stutter extension of some finite behaviors
+       - process death is now a conditionally safe action -- this partly
+         reverses a decision made in version 2.8.5.
+         the condition for safety is: this is the youngest process and
+         there are fewer than the max nr of processes running.  this means
+         that the action cannot enable any blocked run statements, although
+         it may enable more process deaths (i.e., of processes that now
+         become youngest).
+         it does imply that a process dies as quickly as possible.  allowing
+         them to also linger merely creates articifial execution scenarios
+         where the number of active processes can grow without bound.
+         compatibility with 2.8.5-2.9.7 on this issue can be forced by
+         compiling pan.c with -DGLOB_ALPHA
+       - atomics inside atomics or dsteps are now accepted by the parser,
+         and ignored.
+       - there is now a Syntax-Check option in Xspin
+         [suggested by Klaus Havelund]
+       - true and false are now predefined constants
+
+Subsequent updates will appear in a new file: V3.Updates
diff --git a/trunk/verif/Spin/Doc/V3.Updates b/trunk/verif/Spin/Doc/V3.Updates
new file mode 100755 (executable)
index 0000000..6bf770b
--- /dev/null
@@ -0,0 +1,925 @@
+Distribution Update History of the SPIN sources
+===============================================
+
+==== Version 3.0.0 - 12 August 1997 ====
+
+A new release, a new V3.Updates file.  See the end
+of the V2.Updates file for the main changes between
+the last version 2.9.7 and the new version 3.0.0.
+
+Spin Version 1 lasted from Jan. 1990 - Jan.   1995.
+Spin Version 2 lasted from Jan. 1995 - August 1997.
+
+The shell script upgrade2 will take any version of
+Spin between version 2.7 and 2.9 to version 3.0.
+Upgrades from 3.0 forward will appear in a new shell
+script upgrade3, to keep the file small.
+
+==== Version 3.0.1 - 19 August 1997 ====
+
+- on older PC's the hashing behavior could be substandard.
+  on those systems an int is often interpreted as a 16 bit,
+  instead of a 32-bit quantity.  the fix made is to declare
+  the relevant variables as long integers instead of plain
+  integers. there is no visible difference for other systems.
+- printf accidentily picked up a redundant newline in 3.0.0
+  it is gone again.
+- interactive use of spin models with rendez-vous statements
+  could get hung in some cases.
+
+==== Version 3.0.2 - 24 August 1997 ====
+
+- improved the fix for interactive use of rv's from 3.0.1
+- the parser now catches the use of 'run' to initialize
+  global variables as an error.
+- the parser now catches the use of any initializer on
+  a formal parameter in a proctype as an error.
+- addition of a new datatype to Promela: unsigned
+  usage:
+       unsigned name : 3;
+  declares 'name' to be a variable that can hold unsigned
+  values -- stored in 3 bits (i.e., values 0..7 inclusive).
+  values outside the declared range are truncated to the
+  range on assignments
+- d_step may now appear inside and atomic and vice versa
+- extra option -E to pass arguments to the C preprocessor
+  usage:
+       spin -E-Dfoo=faa filename
+  to redefined foo as faa in the filename
+       spin -Pmy_cpp -E-E filename
+  use my_cpp as the preprocessor (replacing cpp) and
+  pass it flag -E when it is called.
+
+==== Version 3.0.3 - 8 September 1997 ====
+
+- unsigned variables weren't cast correctly during
+  simulation runs --
+- warnings about variables being of too generous a type
+  are now only generated when the -v verbose option is set
+- extra warnings, on use of channels, are now also
+  generated with spin -v -- still more with spin -v -g 
+- can now pass directives to the preprocessor with a simpler
+  spin option -D..., e.g., spin -DLOSS=1 spec
+  the earluer -E-D... also still works
+- a few more additions to xspin303.tcl
+
+==== Version 3.0.4 - 25 October 1997 ====
+
+- now accepts truncated extensions of pan.trail
+  (often visible only as pan.tra) on PCs
+- now recognizes compiler directive __FreeBSD__
+- redundant include file <malloc.h> deleted from main.c
+- now properly initializes all channels hidden in typedef
+  structures
+- made it possible to generate structural views of the
+  promela model, but tracking channel uses (more to come)
+- added pc_zpp.c to the sources - used only on the pc
+
+==== Version 3.0.5 - 5 November 1997 ====
+
+- corrected bug in the builtin macro preprocessor of the
+  PC-version (only) of spin.  if the first literal match
+  of the macro source failed to be a valid replacement string,
+  no further matches were tried on that line
+- corrected bug in interactive simulation mode that could
+  cause a failure to return control to the user
+
+==== Version 3.0.6 - 16 December 1997 ====
+
+- a value that is truncated in an assignment to a variable
+  of a small type triggered an error message that sometimes
+  could cause xspin to miss a display update for the variable
+  values pannel.
+- on a -c flag spin was a little too talkative, assuming also
+  a -v verbose flag for the final detail printed at the end of
+  a simulation run.
+- fixed an error in the processing of logical OR in the presence
+  of the X operator in LTL formulae -- this only affected the
+  outcome of a translation if Spin was compiled with -DNXT
+  to enable the LTL next-time operator (this is not enabled by
+  default, because it jeopardizes compatibility with the partial
+  order reductions)
+- a check for non-progress, in combination with provided clauses
+  on proctypes, could fail. the omission was that the never claim
+  process searched for its own provided clause, which should in
+  this case default to true.
+- the restriction that the use of any provided clause voided the
+  partial order reduction was much too strict: it suffices to mark
+  all statements in only the proctype that is labeled with a
+  provided clause unsafe -- other processes are not affected.
+- added new Test/pathfinder example to the Test directory,
+  illustrating the use of provided clauses
+- the standard stutter extension on finite sequences is not
+  allowed to produce non-progress cycles, but in combination with
+  the weak-fairness option this erroneously could happen.
+  (stutter-extension on temporal claim matches is only applied
+  to standard acceptance properties, under runtime option -a)
+- there was an error in the implementation of weak fairness
+  that could cause the algorithm to miss matching acceptance or
+  non-progress cycles with weak-fairness enabled.  a small change
+  in the implementation of this option (incrementing the Choueka
+  counter values by 1) repairs this flaw.
+
+==== Version 3.0.7 - 18 December 1997 ====
+
+- the check on a self-loop, added in 3.0.6, unintentionally also
+  ruled out self-loops in never claims, which are harmless (e.g.,
+  to allow for a finite prefix of 'true' propositions).
+
+==== Version 3.0.8 - 2 January 1998 ====
+
+- with fairness enabled, a process was considered to be temporarily
+  blocked while other processes performed a rv handshake.  this
+  could cause a cycle to be reported as fair that normally would not
+  be considered as such. fairness rule 2 was updated to avoid this.
+- an assignment beginning a dstep sequence was incorrectly considered
+  to be executable in the middle of a rendezvous handshake in progress
+  elsewhere.
+
+==== Version 3.0.9 - 11 January 1998 ====
+
+- rendezvous communications lacked an arrow in the new postscript
+  output generated with spin option -M
+- new predefined channel name STDIN for reading a character from
+  the standard input as in:
+       chan STDIN;
+       short c;
+       do
+       :: STDIN?c ->
+               if
+               :: c == -1 -> /* EOF */
+                       break
+               :: else ->
+                       printf("%c", c)
+               fi
+       od
+- to match this, added support for recognizing character
+  symbols in Promela such as 'i', '\n', '\t', '\r', etc.
+- fixed the bug that prevented weak fairness from being
+  turned off during verifications.... (bug introduced in 3.0.8)
+- small improvements in error catching (mostly related to
+  illegal structure references)
+
+==== Version 3.1.0 - 27 January 1998 ====
+
+- all transitions from a local process state that is referenced
+  within the never claim (or ltl property) are now properly labeled
+  as unsafe in the partial order reduction
+- a d_step that appears at the last statement in a proctype no longer
+  generates an error in the simulator
+- the predefined variable _last is now updated correctly during the
+  verification process (thanks Pedro Merino for the examples)
+- weak fairness is now considered incompatible with partial order reduction
+  in models that contain rendezvous operations (thanks Dennis Dams for
+  the example that revealed this)
+
+==== Version 3.1.1 - 28 January 1998 ====
+
+- fixed a goof in pc_zpp.c -- only visible in the precompiled PC
+  version.  symptom: it would fail to expand some macros with the
+  builtin version of cpp.  in particular, it would fail on the
+  testcase: Test/leader from the distribution (thanks Mike Ferguson).
+
+==== Version 3.1.2 - 14 March 1998 ====
+
+- added a Cut/Copy/Paste meny to the text window of xspin version 3.1.2
+  (big convenience), plus a few smaller fixes
+- the verifiers generated by spin have two extra run-time options:
+       -E to ignore all invalid endstate errors
+       -A to ignore all assert() violations
+- added #include <strings.h> to pan.c
+- main in pan.c is now properly typed 'int' instead of 'void'
+- the following change, introduced in 2.9.0, was unnecessary
+       - assignments to channel variables can violate xr/xs assertions.
+         there is now a check to catch such violations
+  the check is removed:
+  when an xr channel variable is assigned to, it's old value is simply lost.
+  it was the old value (operations on the channel that the value pointed
+  to) that the xr/xs assertion applied to, not to the variable name as such.
+  operations on the new channel id that the variable now points to
+  are subject to the same xr/xs claims as the old one did.
+- new argument to spin:
+       spin -N claimfile ... promelaspec
+  reads the never claim from 'claimfile'
+  (the main filename 'promelaspec' is always the last argument)
+- new argument to spin
+       spin -C promelaspec
+  prints some channel access info on stdout, useful for producing
+  a structural view of the system
+  (used to be an added output in spin -v)
+- fixed bug in pan.c that caused some states created during claim stutter
+  from not being removed from the dfs stack.  should rarely have occured.
+- all the above extensions are supported in Xspin 3.1.2
+- redesigned Xspin's LTL properties management dialogue panel
+- fixed problem with hanging of long simulations on pc's
+  (a buffer overflow problem internal to windows95/nt)
+
+==== Version 3.1.3 - 16 March 1998 ====
+
+- small bug fix in sym.c -- reported too many variables as
+  unused on a spin -a -v spec
+- small bug fix in xspin312.tcl -- replaced "else if" with "elseif"
+- both bugs reported by Theo Ruys within hours after the release of 3.1.2
+  thanks Theo!
+
+==== Version 3.2.0 - 7 April 1998 ====
+
+- a modest extension of the language:
+  there is now a procedure-like construct that should reduce the need
+  for macros.  Promela 'inline' functions preserve linenumber
+  references in simulations (at least, that's the idea).
+  an inline definition look like this (appearing outside all proctypes)
+
+       inline functionname(x, y) {
+               ...a promela fragment...
+       }
+
+  a call looks like this -- and can appear wherever a statement can appear:
+
+       functionname(4, a);
+
+  the replacement text is inlined by the parser, with proper parameter
+  matching and replacement.
+  inlines can be recursive (one inline can call another), but not cyclic.
+
+  there is still no local scope for variables.  this means that the scope
+  of any local variable declared is always the entire proctype body --
+  no matter where it is declared.
+  local variables may be declared at the start of an inline -- but such
+  variables have the same status as a local variable at the place of the call.
+
+- added an example to the Test directory, illustrating inlines (Test/abp)
+
+- timeout is no longer automatically enabled and available as a
+  user-selectable option during interactive simulation.  it could cause
+  counter-intuitive behavior, e.g. when the timeout was used in an unless-
+  escape
+- 'else' is now flagged as unexecutable when appropriate during interactive
+  simulations -- where possible it is offered as a choice so that an
+  execution can be forced in a given direction.
+- small fixes and fiddles with xspin
+
+==== Version 3.2.1 - 4 July 1998 ====
+
+- added compile time directive HC, for a version of Wolper's hash-compact
+  algorithm.  it can speed up the search, and reduce memory requirements,
+  with a relatively low probability of hash-collisions (or missed states).
+  this is a modification of exhaustive search where we store a 32-bit
+  hash-value in the hash-tables, as a compressed state vector.
+  the effective size of the compressed state-vector is the width of the
+  hash-table itself (controlled by the runtime -w parameter) plus 32 bits
+  (by default this is: 18+32 = 50 bits of information).
+  the hash-table entries have some additional overhead which pushes total
+  memory usage slightly higher -- but the memory reductions can be quite
+  substantial (depending, trivially, on the length of the state vector
+  without compression)
+  to enable: compile pan.c with -DHC (perferably combined with -DSAFETY)
+- fixed fgets problem discovered by Theo Ruys
+  (problem: newlines could accidentily be added to the input text)
+- fixed two bugs in dstep code generated in pan.c; improved error reporting
+- fixed bug in processing of include files, when an ltl claim is used
+
+==== Version 3.2.2 - 21 July 1998 ====
+
+- generalized the hash-compact implementation
+  by default (compiling pan.c with -DHC) 6 bytes are stored:
+  4 bytes from the first hash and 2 bytes from a second hash
+  this gives 32+16 = 48 bits of information, which should secure
+  a very low collision probability
+  alternatives are -DHC0 (for 32 bits) -DHC1 (for 40 bits) -DHC2 (48 bits)
+  and -DHC3 (56 bits).
+- reversed the order in which the transitions in a never claim are
+  generated -- this tends to shorten the counter-examples generated
+  (by putting the 'true' self-loops that at the end of the list, rather
+  than at the beginning).  Thanks to Dragan Bosnacki.
+- fixed a bug in xspin.tcl that could cause the application to hang
+  when used on a PC (e.g., any simulation of leader...).
+  (this synchronization bug was introduced in 3.1.4.)
+
+==== Version 3.2.3 - 1 August 1998 ====
+
+- an atomic that ends with a jump into another
+  atomic sequence, now connects correctly without
+  breaking atomicity
+- the choice of a rendezvous partner for send operations
+  wasn't random during simulations (when multiple targets
+  for the rendezvous are available).  it is now.
+- fix in xspin to avoid confusion between proctype names
+  with a common prefix, in rendering an automaton view
+- fix in pc_zpp.c for occasional incorrect comment processing
+  and incorrect #define processing (affected the PC version only)
+
+==== Version 3.2.4 - 10 January 1999 ====
+
+modifications:
+- replaced type "unsigned" in parameter to Malloc and emalloc
+  with "unsigned long long" to support 64 bit word size machines
+  (thanks to Judi Romijn's experiments at CWI)
+  (may not be recognized by non-ansi standard c-compilers)
+extensions:
+- added a runtime flag -J for both spin (simulations) and
+  for pan (verification runs), to specify that nested unless
+  clauses are to be evaluated in reverse order from the default
+  (to match java semantics of catch clauses) at the request
+  of Klaus Havelund.
+- added runtime flags -qN and -B for spin (simulations)
+  -q4 suppresses printing output related to queue 4
+  -B suppresses printing the final wrapups at the end of a run
+- added runtime flag -v for pan (verification) to add filenames
+  to linenumbers in the listings of unreached states (xspin does
+  not support these extensions yet)
+bug-fixes:
+- a very long source statement could overflow an internal
+  buffer in pan.c, upon the generation of a trail-file.
+  (thanks for Klaus Havelund's experiments with a java->spin
+   translator)
+- compilation with a vectorsize greater than 1024 could cause
+  the model checker to behave incorrectly in cases when receive
+  statements were used that received data into global variables
+  (instead of locals).  this now works correctly.
+- removed bug in the optimization code of the ltl-translation
+  algorithm -- it could remove untils in cases such as
+  p /\ (q U r) not only if p==r, but also if p appeared within r
+- line numbers could be inaccurate if #if 0 ... #endif directives
+  were used inside inline declarations.  corrected.
+- fixed a bug in ltl translation due to a failure to recognize
+  'true' to be part of any 'and' form -- should have been a rare
+  occurrence.
+- fixed a bug that affected the use of rendezvous statements in
+  the guard of an escape clause of an unless
+
+==== Version 3.3.0 - 1 June 1999 ====
+
+- rearranged code to share code for identical cases
+  in pan.m and pan.b -- this reduces the file sizes by up
+  to 60% and similarly reduces compilation times for pan.c
+- added pan.c compiler directive MEMLIM
+  compiling pan.c with -DMEMLIM=N will restrict memory use
+  to N Megabytes precisely;  this is an alternative to the
+  existing limit -DMEMCNT=N which restricts to 2^N bytes
+  and gives less precise control.
+- added new data declaration tag 'local' which can be used
+  wherever currently 'show' or 'hidden' can be used.
+  it allows one to identify global variables that are
+  effectively local (used by only 1 process) as data objects
+  of which manipulation is safe for partial order reductions.
+  there's no check for the validity of the tag during verification.
+- automatically hide unused or write-only variables
+  option can be turned off with spin option -o2
+- eval() (used in receive statements to turn a variable into
+  a constant value) can now contain an arbitrary expression,
+  instead of just a name (request of Victor Bos).
+- it is no longer an error to have multiple mtype definitions
+  (they are catenated internally)
+- more verbose error-trails during guided simulations - in verbose
+  mode it now includes explicit mention of never claim moves, if
+  a never claim is involved
+- added also an experimental option to generate code separately
+  for the main system and for the never claim - this makes
+  separate compilation possible.  the option will be finetuned
+  and documented once it has settled.  for the time being, they
+  are not listed in the usage listings.
+- also added, but not enabled, fledgling support for a bisimulation
+  reduction algorithm that might be applied to never claims to
+  reduce their size (inspired by work of Kousha Etessami),
+
+- bugfixes (the first two found by Wenhui Zhang):
+  - in fairness option (could miss a fair cycle)
+  - in implementation of the -DMA option (could incorrectly
+    claim an intersection of the 1st dfs stack an declare a
+    cycle when none existed)
+  - in the conversion of ltl formulae to automata (could
+    occassionaly fail to match common subexpressions)
+  - bug fix in the runtime code for random receive, fixed
+  - fixed execution of atomics during interactive simulation
+  - fixed possibly erroneous marking as 'dead' variables used
+    to index a structure variable array
+
+- during interactive simulation, to avoid confusion, choices
+  between different *escapes* on a statement are no longer offered
+  in user menus, but are now always resolved by the simulator
+- removed all uses of "long long" and replace with "long."
+  the former (temporarily used in 3.2.4) is not in ansi c,
+  and the latter will be interpreted correctly on 64bit machines
+  by a 64bit compiler.
+- added better support for 64bit machines -- avoiding deteriorated
+  performance of the hashing algorithms (courtesy Doug McIlroy)
+- the pc version could get the linenumber references wrong after
+  multiline comments - now repaired (courtesy Mike Ferguson)
+- removed bug in xspin.tcl that prevented the selection of
+  bitstate hashing from the ltl properties manager panel
+  (courtesy Theo Ruys)
+- added an option in xspin to exclude specific channels from the
+  msc displays (you have to know the channel number though)
+- fixes in the interactive simulation model (courtesy Judi Romijn)
+  - d_steps and atomics now always run to completion without
+  prompting the user for intermediate choices that could break
+  the atomicity (and the semantics rules).
+  - unless escapes no longer reach inside d_steps (they do reach
+  inside atomics)
+- merges sequences of safe or atomic steps -- a considerable speedup
+  this behavior can be disabled with spin option -o3
+- computes precondition for feasibility of rv - this option can be
+  enabled with spin option -o4 -- it seems of little use in practice
+- dataflow analysis -- can be disabled with spin option -o1
+- partial evaluation to remove dead edges from verification model
+  (i.e., with a constant 'false' guard)
+- added pan compile time option -DSC to enable new stack cycling option.
+  this will swap parts of deep stacks to a diskfile with only low overhead.
+  it needs no further user action to work -- the runtime -m flag
+  remains, but now simply sets the size of the part of the stack
+  that is in core (i.e., you need not set it explicitly unless you want to)
+- added pan compile time option -DLC to optinally use hashcompacted stackstates
+  during Bitstate runs. it is slower by about 20-30%, but in cases
+  where -DSC is used (very deep stacks) it can safe a lot of extra memory.
+  for this reason -DSC always enables -DLC by default
+
+==== Version 3.3.1 - 12 July 1999 ====
+
+- fix in pangen2.h, to avoid a null-pointer reference
+  in the automata preparation routines. it can occur in some cases
+  where progress labels are used in combination with p.o. reduction
+- fix for weak-fairness in combination with p.o. reduction and
+  unless/rendez-vous (courtesy Dragan Bosnacki)
+- fix to prevent an infinite cycle during the weak-fairness based
+  verifications. (when both the 2nd and the 1st dfs stacks are
+  intersected with a non-zero choueka counter value, the search
+  used to continue - instead this should be treated as a regular
+  stack match)
+- better feedback on spin -a when parts of the automaton are pruned
+  due to constant false guards
+- added spin option -w (extra verbose) to force all variable
+  values to be printed at every execution step during simulations
+
+==== Version 3.3.2 - 16 July 1999 ====
+
+- correcting an initially erroneous fix in 3.3.1 that prevented
+  compilation alltogether for sources generated through xspin. (...)
+  (it left a reference to counters used in the weak fairness algorithm
+   in the code that had to be suppressed if weak fairness isn't used)
+
+==== Version 3.3.3 - 21 July 1999 ====
+
+- fix in the new code for dataflow analysis. in some cases a core-dump
+  could result if a particular control-flow structure was encountered
+  (courtesy Klaus Havelund)
+- updated Xspin to 3.3.3 to deal with the new policy in 3.3 that printfs
+  during simulations are always indented by a number of tab-stops that
+  corresponds to the process number of the process that executes the
+  printf - this makes printfs from the same process line up in columns,
+  but it confused xspin.  (fix courtesy of Theo Ruys)
+
+==== Version 3.3.4 - 9 September 1999 ====
+
+- new pan option -T to prevent an existing trail file from being
+  overwritten (useful if you run multiple copies of pan with
+  bitstate hashing and different -w parameters, to optimize chances
+  of finding errors fast -- the first run to write the trail file
+  then wins)
+- small improvement in error reporting for use of special labels inside
+  atomic and d_step sequences
+- small portability change to avoid problems with some compilers (e.g.
+  the ones used on plan9)
+- increased some statically defined maxima (e.g. for the max length of
+  a single statement - now increased to 2K bytes to avoid problems with
+  machine generated Promela files)
+
+==== Version 3.3.5 - 28 September 1999 ====
+
+- two bug-fixes in the ltl->never claim conversion (with thanks to
+  Heikki Tauriainen for reporting them)
+- increase in some static buffer sizes to allow for long
+  (typically machine generated) variable names
+- removed some debugging printfs
+
+==== Version 3.3.6 - 23 November 1999 ====
+
+- two small extensions and 4 important bug fixes
+
+- added runtime option -t to pan;  using pan -tsuf will
+  cause error trails to be written into spec.suf instead of
+  spec.trail (which remains the default)
+- added a verbose output to the verification runs, to write
+  a line of output each time a new state in the never claim
+  is reached.  this helps keeping track of progress in long
+  running verifications -- and helps to avoid false positives
+  (i.e., when most states in the never claim are unreached,
+  which is a strong indication that the LTL formula that
+  produced the claim isn't related to real behavior of the
+  system)
+
+- bug fix in the fairness algorithm (-f flag during verification)
+  that could cause false error reports to be generated
+- bug fix in the stack cycling compile-time option to pan.c (-DSC)
+  which could cause erroneous behavior of the verifier
+  (both of these reported by Muffy Calder and Alice Miller)
+- bug fix in the generation of never claims from LTL -- missing
+  parentheses around subexpressions in a guard
+- fix to circumvent buggy behavior from gcc on Unix platforms
+  (its version of sbrk can return memory that is not properly
+   word aligned -- which causes memory faults in pan)
+
+==== Version 3.3.7 - 6 December 1999 ====
+
+- 3.3.6 introduced a bug that prevented the verifier code
+  from compiling unless fairness was enabled -- corrected in 3.3.7
+- fixed a minor problem with the as yet unadvertised separate
+  compilation option (compiling the program separately from
+  the claim to speed up verifications of multiple claims)
+- fixed a bug in the simulation code that could make the
+  simulator miss executing statements. it could lead to
+  misleading traces for errors. (thanks to an example by Pim Kars)
+
+==== Version 3.3.8 - 1 January 2000 ====
+
+- fixed a bug in the simulation code that caused no output
+  to appear, for instance, when the traceback is done with
+  a guided simulation for the Test/loops testfile -- fixed
+- fixed bug in the generation of ltl formula of the type:
+       <>[]p && []<>q && []<>r
+  traced to a mistake in the comparison of states in the
+  buchi automaton that could unjustly claim two states to
+  be identical even if they differed (reported by Hagiya)
+- added a cast to (double) for manipulation of MEMLIM to
+  avoid problems with some compilers
+- added a small optimization that rids the spec of repeated
+  sequential skip statements, or skips immediately following
+  printfs (these may be present in mechanically generated specs)
+
+==== Version 3.3.9 - 31 January 2000 ====
+
+- fixed several more bugs in the ltl -> buchi automata
+  conversion - found with a random testing method
+  described by Heikki Tauriainen. the method consists
+  of generating random ltl formula with a fixed number of
+  propositional symbols, with varying numbers of operators,
+  and generating random statespaces over the boolean
+  operands, up to preset maximum number of states.
+  we've done tests with three databases, consisting of:
+       - 27 handpicked standard ltl formulae with up to 4
+         operands
+       - 5356 random ltl formulae with up to 10 temporal
+         operators and up to 3 operands
+       - 20577 ltl formulae with up to 3 temporal operators
+         and up to 3 operands
+  each formula was tested for 25 randomly generated statespaces
+  with up to 50 global states.
+  we checked spin's automata generation method against an
+  independent implementation by kousha etessami, and verified
+  that each of the tests either failed with both tools or
+  passed with both tools -- any difference pointed to a bug
+  in one of the two tools.
+  the fixes in spin version 3.3.9 are mostly related
+  to the use of the X (next operator -- which is normally
+  disabled but can be enabled by compiling the spin sources
+  with the extra compiler directive -DNXT) and V (the dual
+  of U) in long formula.
+- used the opportunity to add in some more optimizations
+  that reduce the size of the automata that are produced
+  (which in many cases also speeds up the generation process).
+  the optimizations were inspired by kousha etessami's work.
+  (email: kousha@research.bell-labs.com)
+
+==== Version 3.3.10 - 15 March 2000 ====
+
+- this should be a final, stable release of spin
+  version 3.3, barring the unforeseen.
+  we'll move to 3.4.0 in a next round of extensions.
+
+- made the number of active processes a globally visible
+  read-only variable: _nr_pr
+  this makes it possible to start a process and then wait
+  for it to complete:
+       run A(); (_nr_pr == _pid+1);
+  useful for simulating function calls.
+- the appearance of a timeout in the guard of a d_step
+  sequence was treated as an error - it is not treated
+  as a warning. (in the guard a timeout is ok)
+- fixed rounding error in calculating the nr of bytes
+  to be stored in statevector with -DCOLLAPSE option.
+  in rare cases the roundoff error could result in
+  missed states when collapse was enabled. reported by
+  Dragan Bosnacki.
+- improved ltl->buchi automata conversion some more
+  to be described in an upcoming paper by kousha.
+- small update of xspin.tcl -- it failed to record spin
+  command line options in the advanced verification options
+  panel. reported by Theo Ruys.
+
+==== Version 3.4.0 - 14 August 2000 ====
+
+- fixed two remaining problems with the ltl conversion
+  algorithm, related to nested untils and the use of the next
+  operator (thanks again Heikki Tauriainen).
+- deals better with renaming files for preprocessing -- no
+  longer relies on temporary files residing on the same
+  filesystem as the working directory
+- added an alignment attribute for the State vector to force
+  gcc to align this structure on a wordboundary (on solaris
+  machines gcc apparently considers this optional).
+- fixed two problems in the use of trace-assertions (could
+  fail when tracking actions on rendezvous channels)
+- new xspin340.tcl that deals better with non-terminating
+  simulation runs on pcs.
+- added support for property-based slicing, to be documented.
+  one example in the Test directory illustrates its use: the
+  wordcount example.
+- added two examples (mobile[12]) that show how specifications
+  in the pi-calculus can be rendered in Promela (thanks Joachim
+  Parrow).
+
+==== Version 3.4.1 - 15 August 2000 ====
+
+- fixed problem with spin option -m -- it stopped working after
+  the upgrade to spin 3.3.0 a year ago. (Thanks Theo Ruys and Rui Hu).
+- minor twiddles to avoid some spurious warnings from gcc on pan_ast.c
+
+==== Version 3.4.2 - 28 October 2000 ====
+
+- release 3.4.1 had some windows carriage returns in some of the
+  source files, which unix compilers don't like - removed
+- two small fixes in the data dependency algorithm, e.g. to make sure
+  that an array index is never considered a def
+- made the allignment attribute on the State struct GCC specific
+  (which it is -- used only on Solaris)
+- the -o2 flag didn't work as advertised, fixed.
+- fix to prevent problems with too liberal use of sequence brackets
+  which could cause a coredump in some cases
+
+==== Version 3.4.3 - 22 December 2000 ====
+
+- small bug fixes, related to the use of {...} for plain sequences
+  (other than for atomic or d_step sequences), and the use of
+  enabled to refer to the running process in simulation mode
+
+==== Version 3.4.4 - 2 February 2001 ====
+
+- fix of the trace assertion code in pan.c (there was a problem
+  when trace assertions were used in combination with rv operations)
+- fix of marking of unreachable states (some reached states could
+  erroneously be reported as unreached in some cases)
+
+==== Version 3.4.5 - 8 March 2001 ====
+
+- one more bug found by Heikki Tauriainen - in the LTL -> Buchi
+  conversion algorithm. it was caused by an unjustified optimization
+  in tl_rewrt.c -- now commented out.
+
+==== Version 3.4.6 - 29 March 2001 ====
+
+- when using rendezvous channels, the compression mask was
+  not completely restored on backward moves during the search.
+  the correctness of the search was not affected, but the
+  number of reached states became larger than necessary
+  (up to twice as large as needed). bug fixed.
+  (found and reported by Vivek Shanbhag)
+
+==== Version 3.4.7 - 23 April 2001 ====
+
+- fixed a number of small bugs in xspin.tcl (now version 3.4.7)
+  (shaded out menu items were not enabled, errors on cancel of
+   simulation runs, etc.)
+- pruned the number of unreached states reported, by removing
+  reports for internal states (marked ".(goto)" or "goto :b3")
+- fixed bug in pid assignements on guided simulation for np-cycles
+
+==== Version 3.4.8 - 22 June 2001 ====
+
+- more small bug fixes
+  e.g., a problem with parameters on inline calls, if the name
+  of an actual parameter equals the name of another formal parameter
+  in the same inline; a typo in an 'attribute' annotation; some
+  missing parameters in rarely executed printf calls
+
+==== Version 3.4.9 - 1 October 2001 ====
+
+- two bug fixes:
+  - problem with xr/xs declarations for processes that can be
+  instatiated with multiple pids -- could lead to a coredump
+  - problem with treatment of merged statements in guided simulations.
+  could lead to a statement being printed twice when it only
+  occurred once.
+
+==== Version 3.4.10 - 30 October 2001 ====
+
+- two bug fixes:
+  - trace assertions were not working correctly, failing to
+  reliably generate matches for all channels within the scope
+  of an assertion. this was likely broken when statement merging
+  was first introduced in version 3.3
+  - added protection against the use of pids outside the valid
+  range in remote references (i.e., less than 0 or over 255)
+
+==== Version 3.4.11 - 17 December 2001 ====
+
+- a bevy of small bug fixes:
+- during verification, sorted send operations
+  (e.g., q!!m) were not reversed accurately, leading to
+  potentially inconsistent error trails
+- 'else' was not interpreted correctly when it appeared
+  as the first statement of a d_step
+- process death was not in all possible cases considered a safe
+  action, and thus could be deferred longer than necessary
+- collapse did not in all cases generate the best compression
+
+==== Version 3.4.12 - 18 December 2001 ====
+
+- correcting a dumn coding error in 3.4.11 that made the
+  pan.c source uncompilable..
+
+==== Version 3.4.13 - 31 January 2002 ====
+
+- new option -T, to suppress pid-dependent indenting of outputs
+- new datatype 'pid' for storing return values from run expressions
+
+- improved reporting of unreached states for models with inlines.
+- improved reporting of memory use for bitstate verification runs.
+- fewer unused vars in pan.c for common modes of compilation.
+- during simulation each line of output is now immediately flushed
+- new restrictions on the use of 'run': max 1 run operator per
+  expression, and run cannot be combined with other conditionals.
+  this secures that if a run expression fails, because the max nr
+  of procs would be exceeded, the expression as a whole will have
+  no side-effects.
+
+- corrected bug in treatment of parameters to inlines
+- corrected bug that showed up for some bizarre combinations
+  of constructs (d_step nested in atomic, embedded in loop)
+  sympton was that the spin parser would hang
+- the maximum number of processes during simulation is now
+  equal to that during verification (255) - to prevent
+  runaway simulations.  the exact number can be redefined
+  when spin is compiled, by adding a directive, e.g. -DMAXP=512
+  similarly the max nr of message channels during simulation
+  can be set by compiling spin with a directive, e.g. -DMAXQ=512
+  the bounds used during verification (255) cannot be changed.
+
+==== Version 3.4.14 - 6 April 2002 ====
+
+- added new spin option -uN to truncate a simulation run after
+  precisely N steps were taken.  in combination with option -jM
+  this can select step M to N from a very long simulation
+  (say guided or random);  example: spin -j10 -u20 spec
+  prints step 10 up to 20, but nothing else
+
+- corrected important bug introduced in 3.4.13 that caused a
+  core dump during verification runs. the bug was caused by
+  a poor attempt to correct reporting of unreached states
+  due to statement merging effects.
+
+- corrected compilation error for an unusual combination of
+  compiler directives
+
+==== Version 3.4.15 - 1 June 2002 ====
+
+- much improved hashfunctions, at the suggestion of Jan Hajek
+  from The Netherlands (the original implementor of the Approver
+  tool from the seventies).
+  this makes for better performance in both exhaustive searches
+  (fewer hashcollisions on standard hashtable, therefore often
+  faster), in bitstate and hashcompact searches (more coverage).
+  the old hashfunctions are reenabled if pan.c is compiled
+  with the new directive -DOHASH. the new functions are the default.
+- improved reports of unreachable states, in the presence of
+  statement merging.
+- small change in the indenting of printf output -- it now lines
+  up better with process columns in -c simulation output
+- fewer compiler warnings
+- some small fiddles with xspin to fix small problems
+- giving up on maintaining the upgrade3 scripts -- they get too
+  long and they do not seem to be used much
+
+==== Version 3.4.16 - 2 June 2002 ====
+
+- a bug slipped in in 3.4.15, bitstate verification failed
+- also increased the default memory limit on PCs to 64 Mb
+
+==== Version 3.4.17 - 19 September 2002 ====
+
+- added a function printm(x) to print the symbolic name of
+  an mtype constant.  this is equivalent to printf("%e", x),
+  but can be more convenient.
+- changed the structure of the never claim that is included
+  by default if pan.c is compiled for non-progress cycle
+  detection with directive -DNP
+  the change is to check first for a move to the accepting
+  state, rather than last.  this reduces the length of
+  error trails that are generated, matching the earlier
+  change made in version 3.2.2, thanks again to Dragan Bosnacki
+  for pointing this out.
+- rearranged the code for pan_ast.c so that it can be compiled
+  separately, rather than as an include file of pangen5.c
+- a bug had been hiding in the -DCOLLAPSE memory compression
+  option that could in rare cases lead to states being missed
+  during a verification
+  the bug could be avoided with the optional -DJOINPROCS.
+  it is now permanently fixed by extending the nr of bytes
+  stored somewhat (the type of each process is now stored
+  explicitly in the compressed statevector, to avoid the
+  confusion that can result if two processes of the same
+  contents but with different types could be created with
+  the same pid, but as alternative options from the same
+  state -- a case found by Remco van Engelen.
+  the fix increases memory use slightly in some case (around
+  10% in many test cases) but retains the greater part of
+  the memory compression benefit. if needed, the fix can
+  be disabled by compiling pan.c with -DNOFIX
+- pan_ast.c is now a separately compiled file, just like
+  all the others, instead of being #included into pangen5.c
+- more attempts to fix the accuracy of reachability reports
+
+==== Version 3.5.0 - 1 October 2002 ====
+
+- variable names starting with an underscore were mistreated
+  in the data flow analysis.
+- this is meant to be a stable release of spin version 3, with
+  minor changes in contact-information for the new spinroot.com
+  website for all documentation, workshop information and
+  newsletters.
+
+==== Version 3.5.1 - 11 November 2002 ====
+
+- bug in parsing of remote label references, could cause a
+  core-dump of spin -a
+- small additional improvements in reporting of unreachable
+  states - to more accurately take into account optimizations
+  made in the transition structure before verification starts
+- noted incompatability of combining -DREACH and -DMA
+
+==== Version 3.5.2 - 30 November 2002 ====
+
+- slightly improved line number references in reporting syntax
+  errors within d_steps
+- extension: remote references usually are written as:
+       proctypename[pid]@labelname
+  if there is only one instantiation of the proctype, then the
+  pid can more easily be figured out by Spin than by the user,
+  so it can, in these cases, now be omitted, making an anonymous
+  remote reference possible, as in:
+       proctypename@labelname
+  if there turn out to be multiple possible matches, Spin will
+  warn in simulation mode -- but not in verification mode.
+  (the additional check would probably be too consuming).
+- during the execution of a d_step, spin would by default
+  still print out every execution step in simulations (under
+  the -p option).  now it will only do so in verbose mode
+  (with also -v).
+- if the last step in an atomic sequence was a rendezvous
+  send operation, atomicity would not reliably move with
+  the handshake to the receiver.  this is fixed.
+- the simulator used a confused method to help the user out
+  if the pid of a process was guessed incorrectly in a remote
+  reference operation. this is now done more sanely:  if a
+  variable is used for the pid, the simulator now trusts that
+  it was set correctly -- the remote ref will simply fail with
+  an error warning if this is not the case.  if the user specified
+  the pid with a fixed constant, the simulator will now always
+  add 1 to the number if the presence of a never claim is detected.
+  (this is because behind the scenes the pid's will move up one
+  slot to accomodate the claim -- this is always hidden from the
+  user -- allowing the user to assume that pids always start at 0).
+
+==== Version 3.5.3 - 8 December 2002 ====
+
+- slightly better error reporting when the nr of pars in a send
+  or run statement differs from the nr declared
+- handling more cases of structure expansion (e.g., structure
+  reference inside other structure used as msg parameter)
+
+==== Version 4.0.0 - 1 January 2003 ====
+
+- Summary of the main changes that motivated the increase of the
+  main Spin version number from 3 to 4
+- added support for embedded C code, primarily to support
+  model extractors that can generate Spin models from C code
+  more easily now, but indirectly this extension also makes
+  all C data types and language elements available within
+  Spin models.  a powerful extension - but with few safeguards
+  against erroneous use. read the documentation carefully.
+- added a Breadth-First search option (compile pan.c with -DBFS)
+  this option works only for safety properties.  it often uses
+  more memory and more time than the standard Depth-First search
+  mode that Spin uses, but it can find the shortest possible
+  error-trails more easily than with the dfs.
+  cycle detection is hard with bfs, so it's not supported yet.
+  all state compression modes are supported (bitstate, collapse,
+  hash-compact, mininized automata, etc.)
+- a small number of bug fixes -- e.g., some unless constructs
+  gave compile-time errors in pan.c, some combinations of
+  compiler directives gave compiler errors, fewer unused vars
+  reported with some more rarely used combinations of compiler
+  directives.
+- slightly rearranged the makefiles -- there is now a separate
+  shell script (make_pc) for windows and a makefile for unix
+  (make_unix). there's also a script for compiling a debuggable
+  version of spin with gcc and gdb (make_gcc).
+  by default these scripts and makefiles now enable the LTL next
+  operator.
+- the call to sbrk() instead of malloc() on Unix is now no longer
+  the default -- it could cause large amounts of memory that on
+  Linux systems is pre-allocated to malloc, to be inaccessible.
+- on Windows PC's the compiler directive -DPC to compile pan.c
+  source is no longer needed (it is only needed to compiler spin
+  itself)
+
+All further updates will appear in the new file: V4.Updates
diff --git a/trunk/verif/Spin/Doc/V4.Updates b/trunk/verif/Spin/Doc/V4.Updates
new file mode 100755 (executable)
index 0000000..183ffa7
--- /dev/null
@@ -0,0 +1,654 @@
+Distribution Update History of the SPIN sources
+===============================================
+
+==== Version 4.0.0 - 1 January 2003 ====
+
+See the end of the V3.Updates file for the main changes
+between the last version 3.5.3 and version 4.0.0.
+A glimpse of the Spin update history since 1989:
+
+ Version 0: Jan. 1989 - Jan. 1990  5.6K lines: book version
+ Version 1: Jan. 1990 - Jan. 1995  7.9K lines: first version on netlib
+ Version 2: Jan. 1995 - Aug. 1997  6.1K lines: partial-order reduction
+ Version 3: Aug. 1997 - Jan. 2003 17.9K lines: bdd-like compression (MA)
+ Version 4: Jan. 2003 -           28.2K lines: embedded c-code, bfs
+
+==== Version 4.0.1 - 7 January 2003 ====
+
+- the rule that one cannot combine a run operator
+  in an expression with any other type of boolean
+  or arithmetic operator within the same expression
+  is now enforced.
+- bfs now produces the usual stats upon finding
+  and error; and it now supports the -e option.
+- extended bfs to deal also with safety properties
+  specified in never claims and trace assertions.
+  unlike the regular dfs search, the bfs search cannot
+  handle the use of atomic sequences inside never claims.
+  it will issue a warning, and will abort, if it sees this.
+  unless constructs, d_steps, etc. should all work also
+  within never claims
+  a warning is issued if accept labels are found inside
+  the never claim (to warn that the bfs search is restricted
+  to safety properties only).
+  the never claim does always work to restrict the search
+  space to the part that is covered by the claim.
+- fixed bug in simulation mode, where atomicity was not
+  always correctly preserved across rv actions from one
+  atomic chain to another (if the sender action was the
+  last statement in an atomic sequence) reported by Judi Romijn.
+- added the BFS option also in the advanced verification
+  options panel of xspin401.tcl
+
+==== Version 4.0.2 - 6 March 2003 ====
+
+- removed a long-standing bug in the marking of transitions
+  for partial order reduction:
+  the guard statement of an atomic or d_step sequence within
+  which a non-atomic,atomic,or d_step sequence is nested did
+  not always get the proper tag
+  if the tag assigned was local and it should have been global,
+  the p.o. reduction algorithm could make an invalid reduction.
+  such a case can indirectly be constructed if an atomic sequence
+  contains an call of an inline function as the first statement.
+  (this case was found by Bram de Wachter)
+- removed reliance on tmpnam() in main.c -- gcc complains about
+  it allowing a race condition on the use of the name returned.
+  we now use fixed local names for the temporary files.
+  there could be a problem now if two users run spin within the
+  same directory simultaneously -- but that problem already
+  exists with xspin as well (pan.tmp and pan.pre) and is
+  easily avoided. (if needed, we could add a locking mechanism
+  at some point, but this seems overkill for the time being.)
+- the -m option now works the same in breadth-first search as it
+  does in depth-first search.  there's less of a strict reason
+  to cutoff the search at the -m depth with bfs, since the
+  stack is not pre-allocated in this case; it grows dynamically.
+  by setting -m to a very large number, one can therefore just
+  let the verifier proceed until it exhausts memory, or finishes
+  (that is to recreate the earlier behavior when needed).
+- increased the size of some internal arrays a bit to better
+  accomodate the use of very long identifier or structure names.
+- much improved rule for creating and locating error trail files:
+  if possible, the trail file is created by appending .trail
+  to the filename of the source model
+  some older operating systems don't like it if the filename
+  for the source model already contains a period, so if a
+  failure is detect, a second attempt is now made by stripping
+  the existing . extesion (e.g., .pml) and replacing it with
+  .trail (some os's also truncate this to .tra, which is also
+  accepted).
+
+==== Version 4.0.3 - 3 April 2003 ====
+
+- no verbose steps printed for never claim in guided simulations
+  unless -v is given as a commandline argument
+  state changes in the never claim are still printed, but with
+  the already existing separate output ("Never claim moves to...") 
+- new spin command-line option -I, to reproduce a version of the
+  specification after preprocessing and inlining operations are
+  done.  the reproduced code is not complete: declarations and
+  process parameters are skipped, some internally generated labels
+  and jumps (e.g., replacing break statements) also become visible.
+  the version is intended only to show what the effect of inlining
+  and preprocessing is.
+- change in sched.c to suppres printing of final value of variables
+  marked 'show' -- this looks like an assignment, which is confusing.
+- small fixes in xspin, which is now xspin402.tcl
+- in guided simulation mode, when a claim from an ltl property is
+  present, the simulator's pid nrs did not always agree with the
+  verifiers numbers -- this could lead to the wrong name for a
+  process being printed in the simulation trails.
+
+==== Version 4.0.4 - 12 April 2003 ====
+
+- there was a bug in 4.0.3 that prevented successful compilation
+  of pan.c (and unbalanced endif, caused by a missing newline
+  character in pangen1.h on line 3207)
+- there was a maximum of 128 variables that could be changed per
+  atomic sequence, this is now 512.
+
+==== Version 4.0.5 - 29 May 2003 ====
+
+- correction in the reporting of process id's during guided simulation.
+  the numbers could be off by one when never claims are used.
+  (just a reporting problem, the run itself was always correct)
+- increased bounds on the length of strings passed as preprocessor
+  commands
+- explicit cast of return value ot strlen to int, to keep compilers
+  happier
+- fixed subtle bug in the fairness option (reported by Dragan
+  Bosnacki).  with fairness enabled, standard claim stutter could
+  in special cases cause a false acceptance cycle to be reported
+  (i.e., a cycle not containing an accepting state).
+  for compatibility, the old behavior can still be obtained by
+  compiling the pan.c verifiers with -DOLDFAIR. the default is
+  the fixed algorithm.
+- restricted the maximum length of a string in the lookup table
+  for c_code segments to 1024 characters.  this table is only used
+  to print out the code segment in error traces -- so the truncation
+  is cosmetic, not functional.  it avoids compiler complaints about
+  excessively long strings though (which could prevent compilation).
+- improved error reporting when a value outside the range of the
+  target data type is passed as an parameter in a run statement
+
+==== Version 4.0.6 - 29 May 2003 ====
+
+- the fix of the fairness option wasn't quite right.
+  directive -DOLDFAIR is gone again, and the real fix
+  is now in place.
+
+==== Version 4.0.7 - 1 August 2003 ====
+
+.------------------------------------------------------.
+| Version 4.0.7 is the version of Spin that is         |
+| described in the Spin book (Addison-Wesley 2003)     |
+| and that is used for all examples there              |
+| http://spinroot.com/spin/Doc/Book_extras/index.html  |
+.------------------------------------------------------.
+
+- added (really restored) code for allowing separate
+  compilation of pan.c for model and claim
+  two new (previously undisclosed) commandline
+  options -S1 and -S2 -- usage documented in the new book
+
+- if it is detected that a c_expr statement definitely has
+  side effects, this now triggers a fatal error.
+
+- complains about more than 255 active processes
+  being declared in active prefix
+
+- fix in -A option: removed bug in handling of eval()
+
+- cosmetic changes:
+  endstate and end-state are now spelled 'end state' as
+  preferred by Websters dictionary (...)
+  hash-array, hash-table, and never-claim similarly
+  are now spelled without hyphens
+
+- improved error replay for models with embedded c code
+
+- the -m option is no longer automatically set in guided
+  simulation runs.
+
+- change spin.h to allow it to be included twice without
+  ill effects (happens in y.tab.c, generated from spin.y)
+
+- updated the make_gcc file for newer versions if cygwin
+
+==== Version 4.1.0 - 4 December 2003 ====
+
+- new spin option -h, when used it will print out the
+  seed number that was used for the random number
+  generator at the end of a simulation run -- useful
+  when you have to reproduce a run precisely, but forgot
+  to set an explicit seed value with option -n
+
+- c_track now has an optional extra argument, to be
+  documented - the extra qualifier cannot be used with BFS
+  (spin.h, spin.y, spinlex.c, pangen4.c, ...)
+
+- the documentation (book p. 41) says that unsigned data
+  can use a width specifier up to 32 bits -- it actually
+  only worked up to 31 bits. it now works as advertised.
+  fix courtesy of Doug McIlroy. (vars.c)
+
+- when trying to compile a model without initialized
+  channels, a confusing compiler error would result.
+  now avoided (spin.y, pangen1.c)
+
+- there is no longer a default maximum memory arena
+  on verifications, that would apply in the absence of
+  an explicit -DMEMCNT or -DMEMLIM setting (the default
+  was 256 Mb).
+
+- some more fixes to account for 64bit machines, courtesy
+  of C. Scott Ananian.
+
+- from Dominik Brettnacher, some instructions on compiling Spin
+  on a Mac under OS X, added to the installation README.html
+  file.
+
+- so far you could not use a -w parameter larger than
+  31 during bitstate search -- this effectively limited
+  the max bitarray to about 512Mb.  the max is now -w32
+  which extends this to 1Gb (i.e., 4 10^9 bits).
+  (really should be allowed to go higher, but wordsize
+  gets in the way for now.)
+
+- suppressed a redundant 'transition failed' message
+  that could occur during guided simulations (guided.c)
+
+- fixed a long standing bug that could show up if the last
+  element of an atomic sequence was itself a sub-sequence
+  (e.g., defined as an inline or as an unless stmnt).
+  in those cases, atomicity could be lost before the
+  last statement (sequence) completed. (flow.c)
+
+- fixed two long standing bugs in parsing of
+  nested unless structures. the bug showed up in
+  a double nested unless that is itself embedded in a
+  non-atomic block. symptom was that some code became
+  unreachable (thanks to Judi Romijn for the example).
+  goto statements that survived state machine optimization
+  also did not properly get tagged with escape options.
+
+- also fixed a bug in handling excessively long assertion
+  strings (larger than 999 characters) during verification
+
+- revised the way that c_track is implemented (the points
+  where c_update and c_revert are called) to make it a
+  little easier to maintain
+
+- removed some no longer used code from pangen1.h
+
+- fixed bug in treatment of rendezvous statements in BFS mode
+
+- xspin408.tcl update: compiler errors are now printed in the
+  log window, as they should have been all along...
+  (courtesy Doug McIlroy)
+
+==== Version 4.1.1 - 2 January 2004 ====
+
+- extended bitstate hashing on 32-bit machines to work correctly
+  with -w arguments up to and including -w34 (courtesy Peter Dillinger)
+- reduced amount of memory allocated to dfs stack in bitstate
+  mode to something more reasonable (it's accessed through a
+  hash function -- now related to the maxdepth, not the -w
+  parameter
+- fixed bug that could cause problem with very long assertions
+  (more than 256 characters long)
+
+- in xspin411, verbose mode during verifications is now default
+  (it adds line numbers reached in the never claim to the output)
+- small fixes to the search capability in most text windows
+
+==== Version 4.1.2 - 21 February 2004 ====
+
+- fixed bug in support for notrace assertions (the pan.c would
+  not compile if a notrace assertion was defined)
+- fixed unintended feature interaction between bitstate search
+  and the -i or -I runtime flags for finding the shortest
+  counter-example
+- some cosmetic changes to ease the life of static analyzers
+- fixed implementation of Jenkins function to optionally
+  skip a semi-compression of the statevector -- to increase speed
+  (pointed out by Peter Dillinger)
+- fixed bug in resetting memory stack arena that could show up
+  in iterative verification runs with pan -R argument
+  (also found by Peter Dillinger)
+- new version of xspin 4.1.2, with a better layout of some
+  of the panels
+
+==== Version 4.1.3 - 24 April 2004 ====
+
+- changed from using "cpp" by default to using "gcc -E -x c"
+  given that most users/systems have gcc anyway to compile c programs
+  and not all systems have cpp in a fixed place.
+  there should be no visible effect of this change.
+
+- a rendezvous send operation inside an atomic sequence was
+  incorrectly accepted as a candidate for merging with subsequent
+  statements in the atomic sequence. it is the only type of statement
+  that can cause loss of atomicity (and a switch to another process)
+  when *executable* (rather than when blocking, as is the case for
+  all other types of statements, including asynchronous sends).
+  this is now fixed, such that if there is at least one rv channel
+  in the system, send operations inside atomic sequences cannot
+  be merged with any other statement
+  (in general, we cannot determine statically if a send operation
+  targets an rv channel or an asynchronous channel, so we can only
+  safely allow the merging if there are no rv channels at all).
+  this can cause a small increase in the number of stored states
+  for models with rendezvous cannels
+
+- counter-examples produced for liveness properties (non-progress or
+  acceptance cycles) often contained one step too many -- now fixed
+
+- added check for reuse of varnames in multiple message fields
+  i.e., q?x,x is not allowed (would cause trouble in the verifier)
+
+- added a warning against using a remote reference to a label
+  that is declared inside an atomic or d_step sequence -- such
+  labels are always invisible to the never claim (since the
+  executing of the sequence containing the label is meant to be
+  indivisible), which can cause confusion.
+
+- "StackOnly" can be used as an alternative to "UnMatched" when used
+  as the optional 3rd argument a c_track primitive (see Spin2004 paper)
+
+==== Version 4.2.0 - 27 June 2004 ====
+
+- main.c now recognizes __OpenBSD__ and treats it the same as __FreeBSD__
+
+- general cleanup of code (removing some ifdefs etc)
+
+- allow reuse of varnames in multiple message fields (see 4.1.3) if
+  var is an array variable (e.g., using different elements)
+
+- deleted support for directive -DCOVEST -- replaced with -DNOCOVEST
+
+- deleted support for directive -DHYBRID_HASH
+
+- deleted support for directive -DOHASH, -DJHASH, -DEXTENDED
+  added -DMM for an experimental/debugging mode (non-documented)
+
+- replaced Jenkins' original hashfunction with an extended version
+  contributed by Peter Dillinger.
+  it uses more of the information to generate multiple pseudo hash values
+  (multi-hashing with anywhere from 1,2,... hash-functions)
+
+- added runtime verifier flag -k to support multi-hashing in Bitstate mode.
+  pan -k2 reproduces the default behavior, with 2 bits set per state.
+  pan -k1 is the same as the old pan -s (which also still works).
+  (as also first suggested by Dillinger and Manolios from Georgia Tech.)
+
+- some more useful hints are generated at the end of each bitstate
+  run about possible improvements in coverage, based on the results
+  obtained in the last run.
+
+- updated xspin420.tcl to match the above changes in verification options.
+
+==== Version 4.2.1 - 8 October 2004 ====
+
+- improvement of BFS mode for partial order reduction, thanks to
+  Dragan Bosnacki
+- fewer redundant declarations and fewer complaints from static analyzers
+- a d_step could under some circumstances interfere with a rendezvous
+  in progress (e.g., when the d_step started with an if statement, or
+  when it started with a send or receive rather then a straight guard
+  condition (i.e., an expression).  this now works as it should.
+- 4.2.0 attempted to make support for coverage estimates the default.
+  this, however, means that on some systems the pan.c source has to be
+  compiled with an additional -lm flag (for the math library)
+  coverage estimates had to be turned off explicitly by compiling with
+  -DNOCOVEST
+  in 4.2.1 the earlier default is restored, meaning that you have to
+  specify -DCOVEST to get the coverage estimates (and presumably you
+  will then know to compile also with -lm)
+- fixed bug that caused an internal name conflict on the verification
+  of the mobile1 model from the Test distribution
+- fixed a problem that prevented having more than 127 distinct proctypes
+  the max is now 255, the same as the max number of running processes.
+- fix to restore bitstate hashing to work on 64-bit machines
+  we still only compute a 32-bit hash; the largest usable bitstate
+  hash-array remains 2^35 bits (i.e., 2^32 bytes or 4 Gigabytes).
+  (the maximum on 32-bit machines remains -w34 or 2 Gigabytes)
+  for 64-bit mode, we will extend this soon to take advantage of
+  larger memory sizes available on those machines. [see 4.2.5]
+- the default number of hash-functions used in bitstate hashing
+  is now 3 (equivalent to a runtime option -k3), which gives slightly
+  better coverage in most cases
+
+==== Version 4.2.2 - 12 December 2004 ====
+
+- verifiers now can be compiled with -DRANDOMIZE (for dfs mode only)
+  to achieve that transitions within each process are explored in
+  random, rather than fixed, order. the other in which processes are
+  explored remains fixed, with most recently created process explored
+  first (if we can think of a good way of supporting random mode
+  for this, we may add this later).  if there is an 'else' transition
+  among the option, no randomization is done (since 'else' currently
+  must be explored as the last option in a set, to work correctly).
+  this option can be useful to get more meaningful coverage of very
+  large states that cannot be explored exhaustively.
+  the idea for this option is Doron Peled's.
+- fixed a limitation in the pan.c verifiers that prevented the use
+  of channels with more than 256 slots.  this should rarely be an
+  issue, since very large asynchronous channels are seldomly useful
+  in verifications, but it might as well work.
+- fix to avoid a compiler complaint about a missing prototype when
+  compiling pan.c with -DBFS
+- renamed error message about us of hidden arrays in parameter list
+  to the more accurate description 'array of structures'
+
+==== Version 4.2.3 - 5 February 2005 ====
+
+- _pid and _ are no longer considered global for partial order reduction
+- fixed bug that could lead to the error "confusing control structure"
+  during guided simulations (replay of error trails)
+- fixed problem where an error trail could be 1 step too long for
+  invalid endstate errors
+- added experimental 64-bit hash mode for 64-bit machines,
+  compile pan.c in bitstate mode with the additional directive -DHASH64
+  the code is by Bob Jenkins: http://burtleburtle.net/bob/c/lookup8.c
+  [placeholder for a later extension for 64 bit machines]
+
+==== Version 4.2.4 - 14 February 2005 ====
+
+- added missing newline after #ifdef HASH64 -- introduced in 4.2.3
+  this caused a compiler warning when compiling pan.c in -DBITSTATE mode
+- a terminating run ending in an accept state was not stutter extended
+  unless a never claim was defined.  this now works also without a
+  never claim, provided that a search for acceptance cycles is performed.
+  in the absence of a never claim the corresponding error type is
+  called a 'accept stutter' sequence (to distinguish it from 'claim stutter')
+  (bug report from Alice Miller)
+  the extension is disabled if the compiler directive -DNOSTUTTER is used,
+  just like for the normal claim stutter extension rule
+- added support for using -DSC on file sizes larger than 2Gb (courtesy Hendrik Tews)
+- in simulation mode, the guard statement of a d_step sequence was not
+  subject to escape clauses from a possible unless statement, contrary to the
+  language spec. in verification mode this did work correctly; simulation mode fixed.
+  (courtesy Theo Ruys and David Guaspari)
+- added warning for use of an 'unless' construct inside a d_step sequence
+
+==== Version 4.2.5 - 2 April 2005 ====
+
+- the default bitstate space size is now 1 Mb (was 512K)
+- the default hashtable size in exhaustive mode is now 512K slots (was 256K)
+- fixed memory leak that can bite in very long simulation runs
+  (courtesy Hendrik Tews)
+- now turns off dataflow optimization (setting dead variables to 0)
+  when remote variable references are used. (this is a little bit of
+  overkill, since we'd only need to turn it off for the variables
+  that are being monitored from the never claim, but it is simple and safe)
+- you can now compile pan.c with -DHASH64 to invoke a 64bit Jenkins hash,
+  (enabled by default on 64bit machines) or disable it by compiling with -DHASH32
+  (which is the default on 32bit machines)
+  the 64-bit version of Spin (and of the pan.c files it generates) has now been
+  fully tested; this means that we can now use more than 4 Gbyte of memory, both
+  in full state and in bitstate mode.
+- added pan runtime options -M and -G (inspired by the work of Peter Dillinger
+  and Panagiotis Manolios on 3Spin), with a simple implementation.
+  (the code for pangen1.h actually got smaller in this update).
+
+  these two new options are available in bitstate mode only and allow the user to
+  define a bitstate hash array that is not necessarily equal to a power of two.
+  if you use -M or -G, then this overrides any other setting you may have
+  used for -w.  for example:
+       pan -M5 will use a hash array of 5 Megabytes
+       pan -G7 will use a hash array of 7 Gigabytes.
+  use this instead of -w when the hash array cannot be a power of 2 bytes large.
+  pan -M4 is technically the same as pan -w25 in that it will allocate
+  a hash array of 4 Megabytes (2^(25-3) bytes), but it can be slower
+  because indices into the hash-array are now computed with a modulo operator
+  instead of with faster bit masks and bit shifts. similarly,
+  pan -G1 is technicall the same as pan -M1024 or pan -w33
+  whether the use of -M and -G is slower than -w depends on your compiler.
+  many modern compilers (e.g. gcc and microsoft visual studio) will automatically
+  optimize the hash array access anyway when it effectively is a power
+  of two large (i.e., independent of whether you use -w25 or -M4).
+  in a small set of tests on  a 2.5 GHz machine, using both gcc and the MS
+  compilers, no meaningful difference in speed when using -M or -G could be
+  measured, compared with -w (not even for non powers of two hash array sizes).
+  (the difference in runtime was in the order of 3 to 4%).
+
+==== Version 4.2.6 - 27 October 2005 ====
+
+- mostly small fixes -- one bug fix for reading error trails on 64bit machines
+  (courtesy Ignacy Gawedzki)
+- the full tar file now creates all files into a single common directory named
+  Spin, which will simplify keep track of versions and updates
+- small update of xspin as well (now xspin4.2.6)
+  the main change in xspin is that on startup it will now look for a file with
+  the same name as the filename argument given (which is typically the name of
+  the file with the Promela model in it) with extension .xsp
+  so when executing "xspin model"  the command will look for a file "model.xsp".
+  xspin will read this file (if present) for commands to execute upon startup.
+  (very useful for demos!)
+  commands must start with either "X:" or "L:"
+  an L: command must be followed by a number, which is used to set the number of
+  lines that should be visible in the command log window
+  an X: command can be followed by any shell command, that xspin will now execute
+  automatically, with the output appearing in the command log window
+  an example .xsp file:
+
+X: spin -a model
+L: 25
+X: nice gcc -DMEMLIM=1000 -DCOLLAPSE -DSAFETY -DREACH -o pan pan.c
+X: nice time -p ./pan -i -m150
+X: spin -t -c -q3 model
+X: cp model.trail pan_in.trail
+
+==== Version 4.2.7 - 23 June 2006 ====
+
+- change in pc_zpp.c, courtesy of Sasha Ivanov, to fix an incorrect order of
+  preprocessing directives -- scanning "if" before "ifdef" and "ifndef"
+
+- all 3 very dubious types of statements in the following model were erroneously
+  accepted by Spin version 4.2.6 and predecessors.
+  they no longer are -- courtesy of the class of 2006 @ Caltech CS
+       active proctype X() {
+               chan q = [2] of { int, int };
+
+               _nr_pr++;       /* change the number of processes... */
+               _p = 3;         /* change the state of process X.... */
+               q!2(run X());   /* something really devious with run */
+       }
+
+- added the compiler directive __NetBSD__
+
+- the vectorsize is now always stored in an unsigned long, to avoid
+  some obscure bugs when the size is chosen too small
+
+- fix in the parsing of LTL formulae with spin -f to make sure that
+  unbalanced braces are always detected
+
+- added warning against use of rendezvous in BFS mode -- which cannot
+  guarantee that all invalid endstates will be preserved
+
+- minor things: make_pc now defaults to gcc instead of cl (the microsoft
+  visual studio compiler)
+
+- xspin4.2.7 disables some bindings that seem to be failing
+  consistently now on all platforms, although the reason is unclear
+  (this occurs in the automata view and the msc views, which are supposed
+  to track states or execution steps to source lines in the main text
+  window -- instead these bindings, if enabled, now seem to hang the gui)
+
+==== Version 4.2.8 - 6 January 2007 ====
+
+- added optimizations in cycle search described by Schwoon & Esparza 2005,
+  in  'a note on on-the-fly verification algorithms' and in
+  Gastin, Moro, and Zeitoun 2004, 'Minimization of counter-examples in Spin'
+  to allow for early detection of acceptance cycles, if a state is found
+  on the stack that is accepting, while still in the 1st dfs. the version
+  also mentioned in Schwoon & Esparza -- for the case where the source state
+  of such a transition is accepting -- is also included.
+
+- eleminated many of the #ifdef PC directives that distinguished between
+  use of y.tab.h and y_tab.h which is no longer needed with the newer
+  versions if yacc on cygwin (e.g., bison yacc)
+
+- the use of a non-local x[rs] assertion is now fatal
+
+- fixed small problem where scheduler could lose track of a process during
+  simulations
+
+- small rewrites for problems spotted by static analyzers
+
+- restored correct working of separate compilation option (-S[12])
+
+- fixed initialization problem with local variables (making sure that
+  a local can be initialized with a parameter or with the value of a
+  previously declared and initialized local
+
+- emalloc now returns NULL when 0 bytes are requested (robert shelton 10/20/06)
+
+- using _stat instead of stat on WIN32 platforms for compatibility with cl.exe
+
+- avoided a problem with non-writable strings, in pan.c
+
+- renamed QPROVISO to Q_PROVISO in preparation for related updates in 4.3.0
+
+- fixed problem with the final transition of an error trail sometimes
+  not appearing in the trail file (alex groce)
+
+==== Version 4.2.9 - 8 February 2007 ====
+
+- the optimization for cycle search from 4.2.8 wasn't complete -- it could cause
+  annoying messages to show up, and the start of a cycle not being identified
+  in all cases (Moti Ben-Ari) -- it now works they way it was intended
+
+- made it possible to compile pan.c with visual studio, provided that -DWIN32 or
+  -DWIN64 are included in the compiler directives; see make_pc for an example.
+  without this, file creat calls would crash the application -- because the windows
+  implementation of this call uses its own set of flags...
+
+- the spin parser now flags all cases where the wrong number of parameters
+  is specified in a run statement (as suggested by Klaus Havelund)
+
+- it is now possible to use a c_expr inside an expression, e.g. as in
+       x[ c_expr { 4 } ] = 3 or x[ c_expr { f() } ]  (Rajeev Joshi)
+
+- a new option for ./pan when embedded C code is used: -S to replay the
+  error trace without printing anything other than the user-defined printfs
+  from the model itself or from inside c_code fragments - (Rajeev Joshi)
+
+==== Version 4.3.0 - 22 June 2007 ====
+
+- bug fix (thank you Claus Traulsen) for goto jumps from one atomic
+  sequence into another. if the first was globally safe, but the second
+  was not, then an erroneous partial-order reduction was possible
+- small changes based on static analyzer output, to increase robustness
+- smaller pan.c files generated if huge arrays are part of the model
+- more accurate reporting of statecounts in bitstate liveness mode
+- better portability for compilation with visual studio
+- likely to be the last spin version 4 release -- the next should be 5.0
+  which supports safety and liveness verification on multi-core systems
+
+==== Version 5.0 - 26 October 2007 ====
+
+- lots of small changes to make the sources friendlier to static analyzers,
+  like coverity, klocwork, codesonar, and uno, so that they find fewer things
+  to warn about
+- improved check for a match of the number of operands specified to a run
+  operator with the number of formal parameters specified for the proctype
+  (courtesy an example by Klaus Havelund)
+- memory counts are now printed properly as MB quantities (divided by
+  1024*1024 instead of 1,000,000)
+- more accurate treament of atomic sections that contain goto statements,
+  when they jump into a different atomic section (especially when the two
+  atomics have different properties under partial order reduction)
+  (courtesy and example by Claus Traulsen)
+- improvement treatment of run statements for processes that initialize
+  local variables with global expressions. in these cases the run
+  statement itself is now recognized as global -- otherwise it can still
+  be treated as local under partial order reduction rules
+- improved treatment of variable update printing when xspin is used.
+  before, large structures were always full printed on every step, which
+  could slow down xspin significantly -- this now happens only if there
+  was a change of at least one of the values printed.
+
+  Additions:
+- support for use of multi-core systems, for both safety and liveness
+  properties. see: http://www.spinroot.com/spin/multicore/
+- added the time of a run in seconds as part of all outputs, and in many
+  cases also the number of new states reached per second
+
+- new compile-time directives for pan.c supported in Version 5.0 include:
+       NCORE, SEP_STATE, USE_DISK, MAX_DSK_FILE, FULL_TRAIL, T_ALERT
+  and for more specialized use:
+       SET_SEG_SIZE, SET_WQ_SIZE, C_INIT, SHORT_T, ONESECOND
+  the following three can be left unspecified unless prompted by pan itself
+  on a first trial run:
+       VMAX, PMAX, QMAX,
+  the use of all the above directives is explained in
+       http://www.spinroot.com/spin/multicore/V5_Readme.html
+  for typical multi-core applications only the use of -DNCORE=N is
+  typically needed
+- a small number of other new directives is not related to the use of
+  multicore verifications - their use is also explained (at the very
+  bottom of) the V5_Readme.html file mentioned above. they are:
+       FREQ, NUSCC, BUDGET, THROTTLE, LOOPSTATE, NO_V_PROVISO
diff --git a/trunk/verif/Spin/Doc/V5.Updates b/trunk/verif/Spin/Doc/V5.Updates
new file mode 100755 (executable)
index 0000000..bb90d82
--- /dev/null
@@ -0,0 +1,174 @@
+Distribution Update History of the SPIN sources
+===============================================
+
+==== Version 5.0 - 26 October 2007 ====
+
+The update history since 1989:
+
+ Version 0: Jan. 1989 - Jan. 1990  5.6K lines: original book version
+ Version 1: Jan. 1990 - Jan. 1995  7.9K lines: first version on netlib
+ Version 2: Jan. 1995 - Aug. 1997  6.1K lines: partial-order reduction
+ Version 3: Aug. 1997 - Jan. 2003 17.9K lines: bdd-like compression (MA)
+ Version 4: Jan. 2003 - Oct. 2007 28.2K lines: embedded c-code, bfs
+ Version 5: Oct. 2007 -           32.8K lines: multi-core support
+
+See the end of the V4.Updates file for the main changes
+between the last Spin version 4.3.0 and Spin version 5.0.
+
+For more details on the use of the new options in 5.0, see also:
+       http://www.spinroot.com/spin/multicore/V5_Readme.html
+and
+       http://www.spinroot.com/spin/multicore/index.html
+which has additional details on the IEEE TSE paper on Spin V5.0.
+
+==== Version 5.1 - 3 November 2007 ====
+
+- fixed an endless loop in the parser for complex atomic sequences
+  (thanks to Mirek Filipow for the example)
+- noticed poor scaling for shared memory system with more than 8 cpus
+  in large rings the downstream cpus can fail to receive sufficient work
+  for some applications, which leads to poor performance.
+  modified the algorithm by adding a global queue that allows
+  cpus to also share some states independent of the ring structure.
+  (and modified the termination algorithm slightly to accomodate this)
+  this improves overall behavior, allows for deeper handoff depths, and
+  restores the scaling on mega-multicore systems
+  linear scalling sometimes stops past roughly 8 cpu's, but some speedup
+  was measured with the new algorithm up to 36 cpu-nodes
+- disabling the global queue is possible but not recommended
+- other smaller fixes, e.g. in issueing recompilation hints etc.
+
+==== Version 5.1.1 - 11 November 2007 ====
+
+- added a new directive -DSFH for fast safety verification
+  this uses a little more memory, but can give a significant speedup
+  it uses Hsieh's fast hash function, which isn't as good as Jenkins,
+  but can be faster, especially when compiling -O2 or -O3.
+  this option does not work in 64-bit mode (yet).
+  the speedup for safety properties the speedup can be up to 2x.
+- some more code cleanup -- more uses of #error and #warning to
+  give faster feedback on unsupported combinations of directives
+- reduced verbosity of outputs in multi-core mode somewhat
+- moved queue access pointers (free and full) into shared memory
+  to give more flexibility in defining handoff strategies
+  (i.e., all cores can now access all queues in principle)
+  added experimental handoff strategies -DPSTAT (with or without -DRROBIN)
+  another experimental handoff strategy is -DFRUGAL (when not using -DPSTAT)
+  [removed in 5.1.2 -- after more experiments showing limited benefit]
+- changed handoff heuristic for bitstate mode, to no longer drop
+  states silently if the target q is full, but instead to explore
+  such states locally -- this increases maxdepth requirements, but
+  is more faithful to the way non-bitstate searches work, and gives
+  better coverage overall
+- changed the way that the global queue is used for multi-core search
+  (the global queue was introduced in 5.1.0 to support scaling to larger
+  number of cores) it is now the second choice, not the first, for a
+  handoff -- the first choice is the normal handoff strategy (normally
+  a handoff to the right neighbor in the logical ring of cores)
+- removed the obsolete directive -DCOVEST
+
+==== Version 5.1.2 - 22 November 2007 ====
+
+- added an automatic resize option for the hashtable in non-bitstate mode
+  this is generally more efficient, although it will still remain faster to
+  choose the right -w parameter up front.
+  this option increases memory use somewhat (the hash now has to be stored
+  in the hashtable together with each state -- which adds about 4 bytes to
+  each state) the automatic resizing feature can be disabled with -DNO_RESIZE
+  (e.g., to reduce memory).  not enabled in multi-core mode.
+- replaced the global heap in multicore mode with separate heaps for each
+  process (still using shared memory of course) -- this reduces the
+  amount of locking needed (suggested by Petr Rockai -- comparable to using hoard)
+- rewrote the compress function with some loop unwinding to try to speed
+  it up a bit (but no major improvement noticed)
+- increased the number of critical sections used for hashtable access in
+  multi-core mode 8x. this improves scaling for some problems
+  (e.g., for elevator2.3 from the BEEM database).
+- made it in principle possible to use more than 2 cores for liveness
+  verification, although more work would be needed to turn this into
+  a method that can speedup the verification of liveness properties further
+- reduced SFH to non-bitstate mode (it is slower than Jenkins if used for
+  double-bit hash computations)
+- changed the format of printfs a little to line up numbers better in output.
+  also improved the accuracy of the resource usage numbers reported
+  in multi-core mode
+- removed the experimentsl directives PSTAT, RROBIN, and FRUGAL from 5.1.1
+- also removed another stale directive R_H
+- updated the 64-bit version of Jenkins hash with the latest version
+  posted on his website (already a few years ago it seems).
+  no big difference in performance or accuracy could be noted though.
+- made liveness verification work with a global queue
+- changed the details of the state handoff mechanism, to rely more on
+  the global queue, to improve scaling behavior on larger numbers of cores
+- reduced the sizes of the handoff queues to the handoff-depth leaving
+  only the global queue at a fixed 128 MB -- in measurements this was a win
+- improved code for setting default values for MEMLIM
+- increased the value of VMAX to match that of the full VECTORSZ, so that
+  redefining it will be less frequently necessary -- leaving VMAX too high
+  reduces only the number of available slots in the queues
+- increased the value of PMAX and QMAX from 16 to 64, so that they
+  also should need adjusting much more rarely
+
+==== Version 5.1.3 - 8 December 2007 ====
+
+- fixed important bug that was introduced in 5.1.2 -- the automatic resize option
+  did not work correctly when -DCOLLAPSE was used. the result of a verification was
+  still correct, but the hashtable would become very slow after a single resizing,
+  and possibly duplicate work being done.  corrected. (found by Alex Groce)
+- if the directive -DSPACE is defined, a more memory frugal (and slightly slower)
+  algorithm is used. no automatic resize of the hashtable and no suppression of
+  the default statevector compression mode (used by default in combination with SFH)
+- COLLAPSE compression didn't work with the new hash functions
+- if NGQ is defined (no global queue) in multi-core mode, the local workqueues
+  of the cpus is now a fixed size, rather than derived from the -z argument
+- preventing crash of the parser on the structure if :: false fi, reported
+  by Peter Schauss
+- on CYGWIN the max segment size for shared memory is now restricted to 512MB,
+  matching the max imposed by cywin itself
+- increased the max length of an input line to 1024 (from 512), to avoid preprocessing
+  problems for very long LTL formulae (reported by Peter Schauss)
+
+==== Version 5.1.4 - 27 January 2008 ====
+
+- fixed bug in enforcement of weak fairness -- introduced in 4.2.8 with the shortcut
+  based on Schwoon & Esparza 2005. the early stop after a match on the stack did
+  not take the fairness algorithm into account -- which means that it could generate
+  a counter-example that did not meet the fairness requirement.
+  reported by david farago.
+- added option to explore dfs in reverse with -DREVERSE (useful for very large searches
+  that run out of memory or time before completing the search)
+- added option to allow bfs to use disk, by compiling with -DBFS_DISK
+- can set limit to incore bfs queue with -DBFS_LIMIT=N (default N=100000 states)
+- can set limit to size of each file created with -DBFS_DISK_LIMIT=N (default N=1000000 states)
+- removed obsolete directive -DQLIST
+- made disk-use option for multi-core search work in more cases
+- new runtime option for pan.c to set a time limit to a verification run to a fixed
+  number of N minutes by saying ./pan -QN (single-core runs only)
+
+==== Version 5.1.5 - 26 April 2008 ====
+
+- added directives -DT_REVERSE to reverse order in which transitions are explored
+  (complementary to -DREVERSE from 5.1.4 and an alternative to -DRANDOMIZE)
+- added directive -DSCHED to enforce a context switch restriction (see pan -L)
+- added directive -DZAPH in bitstate mode, resets the hash array to empty each time it becomes half full
+- see online references for usage of all new directives
+  http://spinroot.com/spin/Man/Pan.html
+- directive -DRANDOMIZE can now take an optional random-seed value, as in -DRANDOMIZE=4347
+- added pan runtime option -x to prevent overwriting existing trail files
+- added pan runtime option -L to set a max for context switches (in combination with -DSCHED)
+- pan runtime option -r can take an argument, specifying the trailfile to use
+- pan runtime option -S replays a trail while printing only user-defined printfs
+- omitted references to obsolete directives OHASH, JHASH, HYBRIDHASH, COVEST, NOCOVEST, BCOMP
+- added directive -DPUTPID to include the process pid into each trailfile name
+- better check for inline parameter replacement, to prevent infinite recursion
+  when the formal parameter contains the replacement text
+- increased maximum size of a line for internal macro replacement to 2K
+- other small fixes, e.g., in verbose output, cleaned up multi-core usage detail
+
+==== Version 5.1.6 - 9 May 2008 ====
+
+- the bug fix from 5.1.4 for Schwoon & Esparza's shortcut in combination with fairness
+  did not go far enough. an example by Hirofumi Watanabe showed that the shortcut is
+  not compatible with the fairness algorithm at all. the result was the possible
+  generation of invalid accept cycles. the short-cut is no longer used when fairness
+  is enabled. no other changes in this version.
diff --git a/trunk/verif/Spin/Man/spin.1 b/trunk/verif/Spin/Man/spin.1
new file mode 100755 (executable)
index 0000000..3dbc493
--- /dev/null
@@ -0,0 +1,274 @@
+.ds Z S\s-2PIN\s0
+.ds P P\s-2ROMELA\s0
+.\"
+.\" On CYGWIN move this page to c:/cygwin/usr/man/man1/spin.1
+.\"
+.TH SPIN 1
+.CT 1 comm_mach protocol
+.SH NAME
+spin \(mi verification tool for models of concurrent systems
+.SH SYNOPSIS
+.B spin
+.BI "-a [-m]"
+[
+.BI -P cpp
+]
+.I file
+.br
+.B spin
+.BI "[-bglmprsv] [-n\f2N\f(BI]"
+[
+.BI -P cpp
+]
+.I file
+.br
+.B spin
+.BI "-c [-t]"
+[
+.BI -P cpp
+]
+.I file
+.br
+.B spin
+.BI -d
+[
+.BI -P cpp
+]
+.I file
+.br
+.B spin
+.BI -f
+.I LTL
+.br
+.B spin
+.BI -F
+.I file
+.br
+.B spin
+.BI "-i [-bglmprsv] [-n\f2N\f(BI]"
+[
+.BI -P cpp
+]
+.I file
+.br
+.B spin
+.BI "-M [-t]"
+[
+.BI -P cpp
+]
+.I file
+.br
+.B spin
+.BI "-t[N] [-bglmprsv] [-j\f2N\f(BI]"
+[
+.BI -P cpp
+]
+.I file
+.br
+.B spin
+.BI -V
+.I file
+.SH DESCRIPTION
+\*Z
+is a tool for analyzing the logical consistency of
+asynchronous systems, specifically distributed software
+amd communication protocols.
+A verification model of the system is first specified
+in a guarded command language called Promela.
+This specification language, described in the reference,
+allows for the modeling of dynamic creation of
+asynchronous processes,
+nondeterministic case selection, loops, gotos, local and
+global variables.
+It also allows for a concise specification of logical
+correctness requirements, including, but not restricted
+to requirements expressed in linear temporal logic.
+.PP
+Given a Promela model
+stored in
+.I file ,
+\*Z can perform interactive, guided, or random simulations
+of the system's execution.
+It can also generate a C program that performs an exhaustive
+or approximate verification of the correctness requirements
+for the system.
+.\"----------------------a----------------
+.TP
+.B -a
+Generate a verifier (model checker) for the specification.
+The output is written into a set of C files, named
+.BR pan. [ cbhmt ],
+that can be compiled
+.RB ( "cc pan.c" )
+to produce an executable verifier.
+The online \*Z manuals (see below) contain
+the details on compilation and use of the verifiers.
+.\"--------------------------c------------
+.TP
+.B -c
+Produce an ASCII approximation of a message sequence
+chart for a random or guided \19(when combined with \f3-t\f1)
+simulation run. See also option \f3-M\f1.
+.\"--------------------------d------------
+.TP
+.BI -d
+Produce symbol table information for the model specified in
+.I file .
+For each Promela object this information includes the type, name and
+number of elements (if declared as an array), the initial
+value (if a data object) or size (if a message channel), the
+scope (global or local), and whether the object is declared as
+a variable or as a parameter.  For message channels, the data types
+of the message fields are listed.
+For structure variables, the 3rd field defines the
+name of the structure declaration that contains the variable.
+.\"--------------------------f------------
+.TP
+.BI "-f \f2LTL\f1"
+Translate the LTL formula \f2LTL\f1 into a never claim.
+.br
+This option reads a formula in LTL syntax from the second argument
+and translates it into Promela syntax (a never claim, qhich is Promela's
+equivalent of a B\(u"chi Automaton).
+The LTL operators are written: [] (always), <> (eventually),
+and U (strong until).  There is no X (next) operator, to secure
+compatibility with the partial order reduction rules that are
+applied during the verification process.
+If the formula contains spaces, it should be quoted to form a
+single argument to the \*Z command.
+.\"--------------------------F------------
+.TP
+.BI "-F \f2file\f1"
+Translate the LTL formula stored in
+.I file
+into a never claim.
+.br
+This behaves identical to option
+.B -f
+but will read the formula from the
+.I file
+instead of from the command line.
+The file should contain the formula as the first line.  Any text
+that follows this first line is ignored, so it can be used to
+store comments or annotation on the formula.
+(On some systems the quoting conventions of the shell complicate
+the use of option
+.B -f .
+Option
+.B -F
+is meant to solve those problems.)
+.\"--------------------------i------------
+.TP
+.BI -i
+Perform an interactive simulation, prompting the user at
+every execution step that requires a nondeterministic choice
+to be made.  The simulation proceeds without user intervention
+when execution is deterministic.
+.\"--------------------------M------------
+.TP
+.BI -M
+Produce a message sequence chart in Postscript form for a
+random simulation or a guided simulation
+(when combined with \f(BI-t\f1), for the model in
+.I file ,
+and write the result into
+.I file.ps .
+See also option \f3-c\f1.
+.\"--------------------------m------------
+.TP
+.BI -m
+Changes the semantics of send events.
+Ordinarily, a send action will be (blocked) if the
+target message buffer is full.
+With this option a message sent to a full buffer is lost.
+.\"--------------------------n------------
+.TP
+.BI "-n\f2N"
+Set the seed for a random simulation to the integer value
+.I N .
+There is no space between the \f(BI-n\f1 and the integer \f2N\f1.
+.\"--------------------------t------------
+.TP
+.BI -t
+Perform a guided simulation, following the error trail that
+was produces by an earlier verification run, see the online manuals
+for the details on verification.
+.\"--------------------------V------------
+.TP
+.BI -V
+Prints the \*Z version number and exits.
+.\"--------------------------.------------
+.PP
+With only a filename as an argument and no option flags,
+\*Z performs a random simulation of the model specified in
+the file (standard input is the default if the filename is omitted).
+This normally does not generate output, except what is generated
+explicitly by the user within the model with \f(CWprintf\f1
+statements, and some details about the final state that is
+reached after the simulation completes.
+The group of options
+.B -bglmprsv
+is used to set the desired level of information that the user wants
+about a random, guided, or interactive simulation run.
+Every line of output normally contains a reference to the source
+line in the specification that generated it.
+If option
+.B -i
+is added, the simulation is \f2interactive\f1, or if option
+.B -t
+is added, the simulation is \f2guided\f1.
+.\"--------------------------bglprsv------------
+.TP
+.BI -b
+Suppress the execution of \f(CWprintf\f1 statements within the model.
+.TP
+.BI -g
+Show at each time step the current value of global variables.
+.TP
+.BI -l
+In combination with option
+.BR -p ,
+show the current value of local variables of the process.
+.TP
+.BI -p
+Show at each simulation step which process changed state,
+and what source statement was executed.
+.TP
+.BI -r
+Show all message-receive events, giving
+the name and number of the receiving process
+and the corresponding the source line number.
+For each message parameter, show
+the message type and the message channel number and name.
+.TP
+.BI -s
+Show all message-send events.
+.TP
+.BI -v
+Verbose mode, add some more detail, and generat more
+hints and warnings about the model.
+.SH SEE ALSO
+Online manuals at spinroot.com:
+.br
+.in +4
+GettingStarted.pdf,
+Roadmap.pdf,
+Manual.pdf,
+WhatsNew.pdf,
+Exercises.pdf
+.in -4
+More background information on the system and the verification process,
+can be found in, for instance:
+.br
+.in +4
+G.J. Holzmann, \f2Design and Validation of Computer Protocols\f1,
+Prentice Hall, 1991.
+.br
+--, `Design and validation of protocols: a tutorial,'
+\f2Computer Networks and ISDN Systems\f1,
+Vol. 25, No. 9, 1993, pp. 981-1017.
+.br
+--, `The model checker \*Z,'
+\f2IEEE Trans. on SE\f1, Vol, 23, No. 5, May 1997.
+.in -4
+.br 
\ No newline at end of file
diff --git a/trunk/verif/Spin/README.html b/trunk/verif/Spin/README.html
new file mode 100755 (executable)
index 0000000..4df3ed9
--- /dev/null
@@ -0,0 +1,374 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<!-- saved from url=(0040)http://spinroot.com/spin/Man/README.html -->
+<HTML><HEAD><TITLE>Spin - Version 5.1 - December 2007</TITLE>
+<META http-equiv=Content-Type content="text/html; charset=windows-1252">
+<META content="MSHTML 6.00.2800.1276" name=GENERATOR></HEAD>
+<BODY bgColor=#ffffff>
+<p>
+<H1><TT><FONT color=#ff0000>SPIN README</FONT></TT></H1>
+<ul></ul>
+<H2><TT>Overview of this File</TT></H2>
+<OL>
+  <LI><A href="http://spinroot.com/spin/Man/README.html#S2">Downloading Spin</A>
+  <LI><A href="http://spinroot.com/spin/Man/README.html#S1">Installing Spin</A>
+  <LI><A href="http://spinroot.com/spin/Man/README.html#S3">Related software
+  (gcc, cpp, tcl/tk wish, yacc, dot, jspin, ltl2ba)</A> </LI></OL>
+<HR>
+
+<H2><TT>0. Overview</TT></H2>This readme file contains the guidelines for
+downloading and installing Spin and related software on Unix/Linux and Windows
+platforms. Refer to <A href="http://spinroot.com/spin/whatispin.html">Spin's
+homepage</A> for a general description of Spin, with pointers to <A
+href="http://spinroot.com/spin/Man/index.html">manual pages</A>, <A
+href="http://spinroot.com/spin/News/index.html">newsletters</A>.
+<p>Spin is distributed in source form to encourage research in formal
+verification, and to help a support friendly and open exchange of algorithms,
+ideas, and tools. The software itself has a copyright from Lucent Technologies
+and Bell Laboratories, and is distributed for research and educational purposes
+only (i.e., no guarantee of any kind is implied by the distribution of the code,
+and all rights are reserved by the copyright holder). For this general use of
+Spin, no license is required.
+<p>Commercial application of the Spin software is also allowed, but requires the
+acceptance of a basic license. Refer to the <A
+href="http://www.spinroot.com/spin/spin_license.html">Spin Public license</A> for details.
+<p>
+<HR>
+
+<H2><TT><A name=S2>1. Downloading Spin</A></TT></H2>Spin runs on Unix,
+Solaris, and Linux machines, on most flavors of Windows PCs, and on Macs.
+Precompiled binary executables for some popular types of machines are available
+in the
+<A href="http://spinroot.com/spin/Bin/index.html">Spin Binaries</A>.
+<p>
+All binaries have an extension that matches the Spin version number,
+such as <tt>spin427.exe</tt>. To install the binary, rename it to
+<tt>spin.exe</tt> and copy it into your bin directory.
+<p>
+If you have machine type that is not available there, or if you are
+installing Spin for the first time, then follow the more detailed instructions
+below.
+<ul>
+  <LI><B>Unix</B> systems: <BR>download the most recent .tar-file with sources,
+  the graphical interface Xspin, documentation and examples from the <A
+  href="http://spinroot.com/spin/Src/index.html">Spin Distribution</A>, and
+  continue at <A href="http://spinroot.com/spin/Man/README.html#S1a"><FONT
+  color=red><B><TT>Step 2a</TT></B></FONT></A>.</LI>
+  <p></p>
+  <LI><B>PCs</B> (Windows95/98/2000/NT/XP): <BR>download the most recent
+  pc_spin*.zip file, with a precompiled Spin executable, the graphical interface
+  Xspin, and some examples from the <A
+  href="http://spinroot.com/spin/Src/index.html">Spin Distribution</A>, and
+  continue at <A href="http://spinroot.com/spin/Man/README.html#S1b"><FONT
+  color=red><B><TT>Step 2b</TT></B></FONT></A>. </LI>
+  <p></p>
+  <LI><B>Macs</B> (Mac OS X): <BR>download the most recent .tar-file with sources,
+  from the <A href="http://spinroot.com/spin/Src/index.html">Spin Distribution</A>,
+  and continue at <A href="http://spinroot.com/spin/Man/README.html#S1c"><FONT
+  color=red><B><TT>Step 2c</TT></B></FONT></A>.
+  </LI></ul>
+<p>
+<HR>
+
+<H2><TT><A name=S1>2. Installing Spin</A></TT></H2>
+<ul>
+  <LI><A href="http://spinroot.com/spin/Man/README.html#S1a"><TT>Unix/Linux
+  systems</TT> (compiled from the sources)</A>
+  <LI><A href="http://spinroot.com/spin/Man/README.html#S1b"><TT>Windows
+  PC's</TT> (using the executable)</A> </LI>
+  <LI><A href="http://spinroot.com/spin/Man/README.html#S1c"><TT>Macs
+  </TT> (compiled from the sources, with some patches)</A> </LI></ul><p>
+<HR>
+
+<H2><TT><A name=S1a><FONT color=red>2a. Installing Spin on a Unix/Linux
+System</A></FONT></TT></H2>
+<ul>Place the *.tar.gz file from the <A
+  href="http://spinroot.com/spin/Src/index.html">Spin Source Distribution</A> in
+  clean directory, and cd to that directory. If you have a standard Unix/Linux system,
+  unpack the archive, and compile an executable, for instance as follows: <pre>        gunzip *.tar.gz
+       tar -xf *.tar
+       cd Src*
+       make    # or, on older distributions: make -f make_unix
+</pre>
+  <p>If you are on a SOLARIS system, edit the makefile and add
+  <TT>-DSOLARIS</TT> to the compiler directives in the makefile before you type
+  'make'. Similarly, if you use a different C compiler than defined in the
+  makefile, edit the makefile first. You need to have at least a C compiler and
+  a copy of yacc.
+  <p>If all else fails, you can also compile everything with the following line:
+<pre>  yacc -v -d spin.y; cc -o spin *.c
+</pre>
+  <p>Spin should compile without warnings. Install the executable version of
+  spin in a directory that is within your default search path (such as your home
+  bin directory, or /usr/local/bin etc.)
+  <p>
+  On Unix/Linux systems Spin assumes that the standard C preprocessor cpp is
+  stored in file "/lib/cpp". On some systems this is different: check the
+  comments in the makefile for details if you run into this problem.
+
+  <H3><TT>Testing</TT></H3>To test the basic sanity of the Spin executable, cd
+  to the Test directory that was created when you unpacked the source archive,
+  and follow the instructions in README.tests file that is included there.
+  <H3><TT>Adding Xspin (Unix/Linux)</TT></H3>Xspin is an optional, but highly
+  recommended, graphical user interface to Spin, written in Tcl/Tk. To obtain
+  Tcl/Tk, see <A href="http://spinroot.com/spin/Man/README.html#S3">Related
+  software</A>. The Xspin source can be found the Xspin4.? directory that will
+  also have been created when you unpacked the source tarfile.
+  <p>The current version of Xspin is compatible with 
+<pre>  Tk version 4.2 - Tcl version 7.6
+       Tk version 8.4 - Tcl version 8.4
+</pre>
+  <p>Xspin prints the version numbers of Spin, Xspin, and Tcl/Tk when it starts
+  up. You can also check separately which version of Tcl/Tk you have installed
+  by executing the following commands in `wish' (a Tcl/Tk command): <pre>      info tclversion
+       puts $tk_version
+</pre>You can find out which version of Spin you have by typing, at the
+  command prompt: <pre>        $ spin -V
+</pre>
+  <p>Xspin can also make use the graph layout program 'dot' if it is available
+  on your system (not required, but very nice if available -- xspin will
+  automatically recognize if it is installed.) For information on 'dot,' see <A
+  href="http://spinroot.com/spin/Man/README.html#S3">Related software</A>.
+  <p>To install Xspin on Unix/Linux:
+  <ul>
+    <LI>cd to directory Xspin... from the distribution,
+    <LI>Rename xspin*.tcl into a more convenient form (like xspin or xspin.tcl)
+    and follow the instructions at the top of this xspin.tcl file. Minimally:
+    you must change the first few lines of this file to point to the executable
+    `wish' command on your system that you want to use. If you use another
+    C-compiler than the default (gcc), you should update the global variable CC
+    inside xspin as well. Follow the instructions inside the xspin.tcl file to
+    do so.
+    <LI>copy the file into a directory within your search path, renamed to plain <tt>xspin</tt>
+and make it
+    executable, for instance:
+<pre>  cp xspin510.tcl /usr/local/bin/xspin
+       chmod +x /usr/local/bin/xspin
+</pre>
+    <LI>On Unix/Linux, invoke the program by typing
+<pre>  xspin   # or xspin.tcl if you keep the extension...
+or
+       xspin promela_spec
+
+For example:
+       cd Test
+       xspin leader
+</pre></LI></ul>Check the online Help menus in xspin for more details on
+  routine use. </ul>
+<p>
+<HR>
+
+<H2><TT><A name=S1b><FONT color=red>2b. Installing Spin on a Windows
+PC</FONT></A></TT></H2>
+<ul>If you just need to update the Spin executable itself, download a new
+  version from <A
+  href="http://spinroot.com/spin/Bin/index.html">http://spinroot.com/spin/Bin/index.html</A>
+  If you need more files, e.g. a new copy of Xspin, download the latest
+  pc_spin*.zip file from <A
+  href="http://spinroot.com/spin/Src/index.html">http://spinroot.com/spin/Src/index.html</A>
+  Extract the files from pc_spin*.zip, and copy spin*.exe, renamed spin.exe, into the directory
+  where all your commands reside and that is within your default search path
+  (e.g., c:/cygwin/bin/, or c:\apps\spin\) You can find out what your search
+  path is set to by typing 'set' at an MS-DOS prompt -- this prints a list of
+  all defined variables in your environment, including the search path that is
+  used to find executable commands.
+  (Note that you may need to set the search path in the environment variables)
+  <p>If you use Spin from the command line (i.e., without Xspin), be warned that
+  some command shells, e.g., the MKS Korn-shell, have none-standard rules for
+  argument parsing (i.e., you can not reliably quote an argument that contains
+  spaces, such as an LTL formula). In most cases this will not be much of a
+  problem, except with the conversion of LTL formula with the Spin -f option.
+  You can circumvent this by using -F instead of -f, to read the formula from a
+  file instead of the command line.
+  <p>To run Spin, also with the precompiled version, you need a working
+  C-compiler and a C-preprocessor, because Spin generates its model checking
+  software as C-source files that require compilation before a verification can
+  be performed. This guarantees fast model checking, because each model checker
+  can be optimized to the specific model being checked. Check, for instance, if
+  you can compile and run a minimal C program succesfully, e.g.:
+<pre>
+       #include &#60;stdio.h&#62;
+       int main(void) { printf("hello\n"); }
+</pre>
+  <p>To find a public version of a C compiler and some instructions on how to
+  install it see <A href="http://spinroot.com/spin/Man/README.html#S3">Related
+  software</A>.
+  <H3><TT>Adding Xspin (PC)</TT></H3>To run Xspin on a PC, you need the PC
+  version of Tcl/Tk, which you can find under <A
+  href="http://spinroot.com/spin/Man/README.html#S3">Related software</A>.
+  <p>The xspin*.tcl source is contained in the .zip file of the <A
+  href="http://spinroot.com/spin/Src/index.html">distribution</A>. Copy the .tcl
+  file as is into a directory where you plan to work, or put a shortcut to this
+  file on the Desktop or in the Start Menu. If you keep the extension .tcl, make
+  sure it is recognized as a 'wish' file by the system, so that xspin starts
+  when you double click the xspin*.tcl script.
+  <p>Under cygwin, copy the xspin*.tcl file to /bin/xspin and make it executable
+  -- check the first few lines of xspin*.tcl to make sure the location of xspin
+  matches what you have on your system (it is currently setup for
+  c:/cygwin/bin/xspin). You can now use xspin as a normal Unix-style command,
+  and you can pass the name of a filename to it, for instance as: <pre>        xspin leader
+</pre>
+  <p>An indirect way to force xspin to startup is to first start `wish' from the
+  Start Menu, under Programs, then select the larger window that comes up (the
+  command window), and cd to the directory where you've stored the xspin.tcl
+  file. Then you can then start it up by typing: <pre> source xspin.tcl  # or whatever else you've named this
+</pre>and you should be up and running.
+  <p>The PC installation assumes that you have a command called "cpp.exe"
+  available (which comes with the gnu-c installation), which is the traditional
+  name of the C preprocessor. Alternatively, it can also use the Visual C++
+  compiler, which is named cl.exe for preprocessing. To complicate your life
+  somewhat, if you have a copy of the Borland C++ compiler installed, you'll
+  notice that this cplusplus compiler was also named cpp.exe -- that's not the
+  cpp you want. To avoid the name clash, you either have to edit the Spin source
+  code to give it the full path name of the 'real' cpp.exe and recompile, or use
+  Spin with the command-line option -Pxxxx where xxxx is the path for cpp.exe.
+  Nothing much in Spin will work without access to cpp.exe. You can do a
+  reasonable number of things without gcc.exe though (like simulations). The
+  C-compiler is required for all verifications and for the automata views in
+  Xspin. </p></ul>
+<p>
+<H2><TT><A name=S1c><FONT color=red>2c. Installing Spin on a Mac</FONT></A></TT></H2>
+  <ul>
+  Compile Spin from its sources, as described under 2a for Unix systems in general,
+  while following the suggestions below, which were provided by
+  Dominik Brettnacher, email: <tt>domi@saargate.de</tt>.
+<p>
+The C preprocessor on Mac OS X cannot be found in <tt>/lib</tt>.
+Change the path in the makefile for the
+proper location (<tt>/usr/bin/cpp</tt>), and in addition
+also tell the Mac preprocessor to handle its input as
+"assembler-with-cpp."
+This can be done by adding a flag to cpp, for instance in
+the makefile by adding the directive
+<ul>
+<pre>
+-DCPP="\"/usr/bin/cpp -xassembler-with-cpp\""
+</pre>
+</ul>
+to the definition of <tt>CFLAGS</tt>.
+</pre>
+<p>
+<H3><TT>Adding Xspin (Unix)</TT></H3>
+On the Mac, Xspin is known to work correctly with Tcl/Tk Aqua,
+which offers a self-contained binary distribution for the Mac.
+Use, for instance, "TclTkAquaStandalone", version 8.4.4 from
+<ul>
+<pre><a href="http://www.maths.mq.edu.au/~steffen/tcltk/TclTkAqua/">http://www.maths.mq.edu.au/~steffen/tcltk/TclTkAqua/</a>
+</pre>
+</ul>
+<p>
+Xspin by default places its temporary files into the root directory.
+This is nasty if you have admin privileges and probably leads to error
+messages if you don't.
+To prevent this, add a "cd" statement to xspin (no arguments, just cd by
+itself on a line), as the first command executed.
+Place it, for instance, directly after the opening comments in the file.
+This makes Xspin use the home directory for these files.
+<p>
+TclTk Aqua also provides the possibility to start a script when being run.
+For instance, to make Xspin start if you launch the TCL interpreter:
+move the xspin file into the "Wish Shell.app", as follows:
+<ul><pre>
+chmod -R u+w Wish\ Shell.app
+mkdir Wish\ Shell.app/Contents/Resources/Scripts
+mv xspin*.tcl Wish\ Shell.app/Contents/Resources/Scripts/AppMain.tcl
+</pre>
+</ul>
+</ul>
+
+<HR>
+
+<H2><TT><A name=S3>3. Related Software</A></TT></H2>
+<ul>Pointers to public domain versions of some related software packages are
+  discussed below:
+  <ul>
+    <LI>Gcc,</LI>
+    <LI>Cpp,</LI>
+    <LI>Yacc,</LI>
+    <LI>Tcl/Tk wish,</LI>
+    <LI>Dot,</LI>
+    <LI>JSpin, and</LI>
+    <LI>Ltl2Ba. </LI></ul>
+  <H3><TT>GCC</TT></H3>On Unix/Linux you probably have gcc, or an equivalent,
+  installed. On the PC you need either a copy of Visual Studio Express (for the cl
+  command), or an installation of gcc with minimally the executables: gcc.exe,
+  and cpp.exe in your search path, together with all the standard C library
+  routines and header files. You can get good free version of all these files
+  with the <TT>cygwin</TT> toolkit, which is mostly self-installing and
+  available from: <A href="http://www.cygwin.com/">http://www.cygwin.com/</A>
+  <BR>See also what's available in <A
+  href="http://spinroot.com/spin/Bin/index.html">http://spinroot.com/spin/Bin/index.html</A>.
+
+  <H3><TT>Tcl/Tk Wish</TT></H3>To run Xspin you'll need Tcl/Tk. Tcl/Tk was
+  written by John Ousterhout (john.ousterhout@eng.sun.com) and is public domain.
+  It can be obtained (for PCs or Unix) from cygwin, or from: <A
+  href="http://www.tcl.tk/">http://www.tcl.tk/</A> or also (a more recent extension):
+  <a href="http://www.activestate.com/Products/ActiveTcl/">
+  http://www.activestate.com/Products/ActiveTcl/</a><BR>More details can be found
+  in netnews-group: comp.lang.tcl
+
+  <H3><TT>Yacc (optional)</TT></H3>To compile Spin itself from its sources on a
+  PC, you'll need to have a copy of yacc installed. A public domain version for
+  a PC can most easily be obtained from <b>cygwin</b>, or also from: 
+<pre>  <A href="ftp://ftp.cs.berkeley.edu/ucb/4bsd/byacc.tar.Z">ftp://ftp.cs.berkeley.edu/ucb/4bsd/byacc.tar.Z</A>
+</pre>A copy of this file is also available in: <A
+  href="http://spinroot.com/spin/Bin/index.html">http://spinroot.com/spin/Bin/index.html</A>
+  (You don't need yacc on the PC's if you use the pre-compiled version of Spin
+  for the pc in the pc*.zip file from the distribution) Look at the file
+  make_it.bat for an example on how to perform the compilation.
+  <H3><TT>Dot (optional)</TT></H3>Dot is a graph layout tool developed by
+  Stephen North and colleagues at AT&amp;T (email: north@research.att.com).
+  Xspin can make use of dot to beautify the layout of the state-machines in the
+  automata-view option (recommended!).
+To obtain Dot, see
+<pre>
+       <A href="http://www.graphviz.org/">http://www.graphviz.org/</A>
+</pre>
+The are both PC and Unix versions of dot available. For documentation of
+dot see, for instance:
+<pre><I>       A technique for drawing directed graphs</I>,
+       by Gansner, Koutsofios, North and Vo,
+       IEEE-TSE, March, 1993.
+</pre>
+If you accept the default installation on a PC, you will need to define the
+location of dot.exe in the xspin source as follows:
+<pre>
+       set DOT "C:/Program\\ Files\ATT\Graphviz/bin/dot.exe"
+</pre>
+(the line that sets the location of DOT appears near the top of the xspin.tcl file).
+<H3><TT>JSpin (optional)</TT></H3>
+An alternative to the Xspin GUI, written in Java instead of Tcl/Tk.
+Written by Moti Ben-Ari (moti.ben-ari@weizmann.ac.il), see
+<pre>
+       <a href="http://stwww.weizmann.ac.il/g-cs/benari/jspin/">http://stwww.weizmann.ac.il/g-cs/benari/jspin/</a>
+</pre>
+The jSpin tool currently expects spin to be installed on Windows in c:/spin/spin.exe, and it assumes that you are using the
+mingw version of gcc.
+  <H3><TT>Ltl2Ba (optional)</TT></H3>A faster method to generate very small
+  never claims from LTL formulae, developed by Denis Oddoux and Paul Gastin is
+  available online in source form:
+<pre>
+       <A href="http://spinroot.com/spin/Src/ltl2ba.tar.gz">http://spinroot.com/spin/Src/ltl2ba.tar.gz</A>
+</pre>
+The latest version can be obtained from the authors website via:
+<pre>
+       <A href="http://www.lsv.ens-cachan.fr/~gastin/ltl2ba/download.php">http://www.lsv.ens-cachan.fr/~gastin/ltl2ba/download.php</A>
+See also
+       <A href="http://www.lsv.ens-cachan.fr/~gastin/ltl2ba/index.php">http://www.lsv.ens-cachan.fr/~gastin/ltl2ba/index.php</A>
+</pre>
+The C source code can be linked with Spin, or run as a standalone tool.
+<p>
+</ul>
+<HR>
+<TT>
+<TABLE cols=3 width="100%">
+<TBODY><TR>
+<TD align=left><A href="http://spinroot.com/spin/whatispin.html"><TT>Spin HomePage</TT></A></TD>
+<TD></TD>
+<TD align=right><FONT size=3><B><TT>
+(Page Last Updated: 26 April 2008)
+</TT></B></FONT></TD>
+</TR></TBODY>
+</TABLE>
+</TT>
+</BODY>
+</HTML>
diff --git a/trunk/verif/Spin/Src5.1.6/dstep.c b/trunk/verif/Spin/Src5.1.6/dstep.c
new file mode 100755 (executable)
index 0000000..5f6f3b3
--- /dev/null
@@ -0,0 +1,411 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+#define MAXDSTEP       1024    /* was 512 */
+
+char   *NextLab[64];
+int    Level=0, GenCode=0, IsGuard=0, TestOnly=0;
+
+static int     Tj=0, Jt=0, LastGoto=0;
+static int     Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
+static void    putCode(FILE *, Element *, Element *, Element *, int);
+
+extern int     Pid, claimnr, separate, OkBreak;
+
+static void
+Sourced(int n, int special)
+{      int i;
+       for (i = 0; i < Tj; i++)
+               if (Tojump[i] == n)
+                       return;
+       if (Tj >= MAXDSTEP)
+               fatal("d_step sequence too long", (char *)0);
+       Special[Tj] = special;
+       Tojump[Tj++] = n;
+}
+
+static void
+Dested(int n)
+{      int i;
+       for (i = 0; i < Tj; i++)
+               if (Tojump[i] == n)
+                       return;
+       for (i = 0; i < Jt; i++)
+               if (Jumpto[i] == n)
+                       return;
+       if (Jt >= MAXDSTEP)
+               fatal("d_step sequence too long", (char *)0);
+       Jumpto[Jt++] = n;
+       LastGoto = 1;
+}
+
+static void
+Mopup(FILE *fd)
+{      int i, j;
+
+       for (i = 0; i < Jt; i++)
+       {       for (j = 0; j < Tj; j++)
+                       if (Tojump[j] == Jumpto[i])
+                               break;
+               if (j == Tj)
+               {       char buf[16];
+                       if (Jumpto[i] == OkBreak)
+                       {       if (!LastGoto)
+                               fprintf(fd, "S_%.3d_0:  /* break-dest */\n",
+                                       OkBreak);
+                       } else {
+                               sprintf(buf, "S_%.3d_0", Jumpto[i]);
+                               non_fatal("goto %s breaks from d_step seq", buf);
+       }       }       }
+       for (j = 0; j < Tj; j++)
+       {       for (i = 0; i < Jt; i++)
+                       if (Tojump[j] == Jumpto[i])
+                               break;
+#ifdef DEBUG
+               if (i == Jt && !Special[i])
+                       fprintf(fd, "\t\t/* no goto's to S_%.3d_0 */\n",
+                       Tojump[j]);
+#endif
+       }
+       for (j = i = 0; j < Tj; j++)
+               if (Special[j])
+               {       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 */
+       Jt = 0;
+}
+
+static int
+FirstTime(int n)
+{      int i;
+       for (i = 0; i < Tj; i++)
+               if (Tojump[i] == n)
+                       return (Special[i] <= 1);
+       return 1;
+}
+
+static void
+illegal(Element *e, char *str)
+{
+       printf("illegal operator in 'd_step:' '");
+       comment(stdout, e->n, 0);
+       printf("'\n");
+       fatal("'%s'", str);
+}
+
+static void
+filterbad(Element *e)
+{
+       switch (e->n->ntyp) {
+       case ASSERT:
+       case PRINT:
+       case 'c':
+               /* run cannot be completely undone
+                * with sv_save-sv_restor
+                */
+               if (any_oper(e->n->lft, RUN))
+                       illegal(e, "run operator in d_step");
+
+               /* remote refs inside d_step sequences
+                * would be okay, but they cannot always
+                * be interpreted by the simulator the
+                * same as by the verifier (e.g., for an
+                * error trail)
+                */
+               if (any_oper(e->n->lft, 'p'))
+                       illegal(e, "remote reference in d_step");
+               break;
+       case '@':
+               illegal(e, "process termination");
+               break;
+       case D_STEP:
+               illegal(e, "nested d_step sequence");
+               break;
+       case ATOMIC:
+               illegal(e, "nested atomic sequence");
+               break;
+       default:
+               break;
+       }
+}
+
+static int
+CollectGuards(FILE *fd, Element *e, int inh)
+{      SeqList *h; Element *ee;
+
+       for (h = e->sub; h; h = h->nxt)
+       {       ee = huntstart(h->this->frst);
+               filterbad(ee);
+               switch (ee->n->ntyp) {
+               case NON_ATOMIC:
+                       inh += CollectGuards(fd, ee->n->sl->this->frst, inh);
+                       break;
+               case  IF:
+                       inh += CollectGuards(fd, ee, inh);
+                       break;
+               case '.':
+                       if (ee->nxt->n->ntyp == DO)
+                               inh += CollectGuards(fd, ee->nxt, inh);
+                       break;
+               case ELSE:
+                       if (inh++ > 0) fprintf(fd, " || ");
+/* 4.2.5 */            if (Pid != claimnr)
+                               fprintf(fd, "(boq == -1 /* else */)");
+                       else
+                               fprintf(fd, "(1 /* else */)");
+                       break;
+               case 'R':
+                       if (inh++ > 0) fprintf(fd, " || ");
+                       fprintf(fd, "("); TestOnly=1;
+                       putstmnt(fd, ee->n, ee->seqno);
+                       fprintf(fd, ")"); TestOnly=0;
+                       break;
+               case 'r':
+                       if (inh++ > 0) fprintf(fd, " || ");
+                       fprintf(fd, "("); TestOnly=1;
+                       putstmnt(fd, ee->n, ee->seqno);
+                       fprintf(fd, ")"); TestOnly=0;
+                       break;
+               case 's':
+                       if (inh++ > 0) fprintf(fd, " || ");
+                       fprintf(fd, "("); TestOnly=1;
+/* 4.2.1 */            if (Pid != claimnr) fprintf(fd, "(boq == -1) && ");
+                       putstmnt(fd, ee->n, ee->seqno);
+                       fprintf(fd, ")"); TestOnly=0;
+                       break;
+               case 'c':
+                       if (inh++ > 0) fprintf(fd, " || ");
+                       fprintf(fd, "("); TestOnly=1;
+                       if (Pid != claimnr)
+                               fprintf(fd, "(boq == -1 && ");
+                       putstmnt(fd, ee->n->lft, e->seqno);
+                       if (Pid != claimnr)
+                               fprintf(fd, ")");
+                       fprintf(fd, ")"); TestOnly=0;
+                       break;
+       }       }
+       return inh;
+}
+
+int
+putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln, int seqno)
+{      int isg=0; char buf[64];
+
+       NextLab[0] = "continue";
+       filterbad(s->frst);
+
+       switch (s->frst->n->ntyp) {
+       case UNLESS:
+               non_fatal("'unless' inside d_step - ignored", (char *) 0);
+               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);
+               break;
+       case IF:
+               fprintf(fd, "if (!(");
+               if (!CollectGuards(fd, s->frst, 0))     /* what about boq? */
+                       fprintf(fd, "1");
+               fprintf(fd, "))\n\t\t\tcontinue;");
+               isg = 1;
+               break;
+       case '.':
+               if (s->frst->nxt->n->ntyp == DO)
+               {       fprintf(fd, "if (!(");
+                       if (!CollectGuards(fd, s->frst->nxt, 0))
+                               fprintf(fd, "1");
+                       fprintf(fd, "))\n\t\t\tcontinue;");
+                       isg = 1;
+               }
+               break;
+       case 'R': /* <- can't really happen (it's part of a 'c') */
+               fprintf(fd, "if (!("); TestOnly=1;
+               putstmnt(fd, s->frst->n, s->frst->seqno);
+               fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
+               break;
+       case 'r':
+               fprintf(fd, "if (!("); TestOnly=1;
+               putstmnt(fd, s->frst->n, s->frst->seqno);
+               fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
+               break;
+       case 's':
+               fprintf(fd, "if (");
+#if 1
+/* 4.2.1 */    if (Pid != claimnr) fprintf(fd, "(boq != -1) || ");
+#endif
+               fprintf(fd, "!("); TestOnly=1;
+               putstmnt(fd, s->frst->n, s->frst->seqno);
+               fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
+               break;
+       case 'c':
+               fprintf(fd, "if (!(");
+               if (Pid != claimnr) fprintf(fd, "boq == -1 && ");
+               TestOnly=1;
+               putstmnt(fd, s->frst->n->lft, s->frst->seqno);
+               fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
+               break;
+       case ELSE:
+               fprintf(fd, "if (boq != -1 || (");
+               if (separate != 2) fprintf(fd, "trpt->");
+               fprintf(fd, "o_pm&1))\n\t\t\tcontinue;");
+               break;
+       case ASGN:      /* new 3.0.8 */
+               fprintf(fd, "IfNotBlocked");
+               break;
+       }
+       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);
+
+       if (nxt)
+       {       extern Symbol *Fname;
+               extern int lineno;
+
+               if (FirstTime(nxt->Seqno)
+               && (!(nxt->status & DONE2) || !(nxt->status & D_ATOM)))
+               {       fprintf(fd, "S_%.3d_0: /* 1 */\n", nxt->Seqno);
+                       nxt->status |= DONE2;
+                       LastGoto = 0;
+               }
+               Sourced(nxt->Seqno, 1);
+               lineno = ln;
+               Fname = nxt->n->fn;     
+               Mopup(fd);
+       }
+       unskip(s->frst->seqno);
+       return LastGoto;
+}
+
+static void
+putCode(FILE *fd, Element *f, Element *last, Element *next, int isguard)
+{      Element *e, *N;
+       SeqList *h; int i;
+       char NextOpt[64];
+       static int bno = 0;
+
+       for (e = f; e; e = e->nxt)
+       {       if (e->status & DONE2)
+                       continue;
+               e->status |= DONE2;
+
+               if (!(e->status & D_ATOM))
+               {       if (!LastGoto)
+                       {       fprintf(fd, "\t\tgoto S_%.3d_0;\n",
+                                       e->Seqno);
+                               Dested(e->Seqno);
+                       }
+                       break;
+               }
+               fprintf(fd, "S_%.3d_0: /* 2 */\n", e->Seqno);
+               LastGoto = 0;
+               Sourced(e->Seqno, 0);
+
+               if (!e->sub)
+               {       filterbad(e);
+                       switch (e->n->ntyp) {
+                       case NON_ATOMIC:
+                               h = e->n->sl;
+                               putCode(fd, h->this->frst,
+                                       h->this->extent, e->nxt, 0);
+                               break;
+                       case BREAK:
+                               if (LastGoto) break;
+                               if (e->nxt)
+                               {       i = target( huntele(e->nxt,
+                                               e->status, -1))->Seqno;
+                                       fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
+                                       fprintf(fd, "/* 'break' */\n");
+                                       Dested(i);
+                               } else
+                               {       if (next)
+                                       {       fprintf(fd, "\t\tgoto S_%.3d_0;",
+                                                       next->Seqno);
+                                               fprintf(fd, " /* NEXT */\n");
+                                               Dested(next->Seqno);
+                                       } else
+                                       fatal("cannot interpret d_step", 0);
+                               }
+                               break;
+                       case GOTO:
+                               if (LastGoto) break;
+                               i = huntele( get_lab(e->n,1),
+                                       e->status, -1)->Seqno;
+                               fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
+                               fprintf(fd, "/* 'goto' */\n");
+                               Dested(i);
+                               break;
+                       case '.':
+                               if (LastGoto) break;
+                               if (e->nxt && (e->nxt->status & DONE2))
+                               {       i = e->nxt?e->nxt->Seqno:0;
+                                       fprintf(fd, "\t\tgoto S_%.3d_0;", i);
+                                       fprintf(fd, " /* '.' */\n");
+                                       Dested(i);
+                               }
+                               break;
+                       default:
+                               putskip(e->seqno);
+                               GenCode = 1; IsGuard = isguard;
+                               fprintf(fd, "\t\t");
+                               putstmnt(fd, e->n, e->seqno);
+                               fprintf(fd, ";\n");
+                               GenCode = IsGuard = isguard = LastGoto = 0;
+                               break;
+                       }
+                       i = e->nxt?e->nxt->Seqno:0;
+                       if (e->nxt && e->nxt->status & DONE2 && !LastGoto)
+                       {       fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
+                               fprintf(fd, "/* ';' */\n");
+                               Dested(i);
+                               break;
+                       }
+               } else
+               {       for (h = e->sub, i=1; h; h = h->nxt, i++)
+                       {       sprintf(NextOpt, "goto S_%.3d_%d",
+                                       e->Seqno, i);
+                               NextLab[++Level] = NextOpt;
+                               N = (e->n && e->n->ntyp == DO) ? e : e->nxt;
+                               putCode(fd, h->this->frst,
+                                       h->this->extent, N, 1);
+                               Level--;
+                               fprintf(fd, "%s: /* 3 */\n", &NextOpt[5]);
+                               LastGoto = 0;
+                       }
+                       if (!LastGoto)
+                       {       fprintf(fd, "\t\tUerror(\"blocking sel ");
+                               fprintf(fd, "in d_step (nr.%d, near line %d)\");\n",
+                               bno++, (e->n)?e->n->ln:0);
+                               LastGoto = 0;
+                       }
+               }
+               if (e == last)
+               {       if (!LastGoto && next)
+                       {       fprintf(fd, "\t\tgoto S_%.3d_0;\n",
+                                       next->Seqno);
+                               Dested(next->Seqno);
+                       }
+                       break;
+       }       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/flow.c b/trunk/verif/Spin/Src5.1.6/flow.c
new file mode 100755 (executable)
index 0000000..ac3e4e4
--- /dev/null
@@ -0,0 +1,794 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+extern Symbol  *Fname;
+extern int     nr_errs, lineno, verbose;
+extern short   has_unless, has_badelse;
+
+Element *Al_El = ZE;
+Label  *labtab = (Label *) 0;
+int    Unique=0, Elcnt=0, DstepStart = -1;
+
+static Lbreak  *breakstack = (Lbreak *) 0;
+static Lextok  *innermost;
+static SeqList *cur_s = (SeqList *) 0;
+static int     break_id=0;
+
+static Element *if_seq(Lextok *);
+static Element *new_el(Lextok *);
+static Element *unless_seq(Lextok *);
+static void    add_el(Element *, Sequence *);
+static void    attach_escape(Sequence *, Sequence *);
+static void    mov_lab(Symbol *, Element *, Element *);
+static void    walk_atomic(Element *, Element *, int);
+
+void
+open_seq(int top)
+{      SeqList *t;
+       Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
+
+       t = seqlist(s, cur_s);
+       cur_s = t;
+       if (top) Elcnt = 1;
+}
+
+void
+rem_Seq(void)
+{
+       DstepStart = Unique;
+}
+
+void
+unrem_Seq(void)
+{
+       DstepStart = -1;
+}
+
+static int
+Rjumpslocal(Element *q, Element *stop)
+{      Element *lb, *f;
+       SeqList *h;
+
+       /* allow no jumps out of a d_step sequence */
+       for (f = q; f && f != stop; f = f->nxt)
+       {       if (f && f->n && f->n->ntyp == GOTO)
+               {       lb = get_lab(f->n, 0);
+                       if (!lb || lb->Seqno < DstepStart)
+                       {       lineno = f->n->ln;
+                               Fname = f->n->fn;
+                               return 0;
+               }       }
+               for (h = f->sub; h; h = h->nxt)
+               {       if (!Rjumpslocal(h->this->frst, h->this->last))
+                               return 0;
+       
+       }       }
+       return 1;
+}
+
+void
+cross_dsteps(Lextok *a, Lextok *b)
+{
+       if (a && b
+       &&  a->indstep != b->indstep)
+       {       lineno = a->ln;
+               Fname  = a->fn;
+               fatal("jump into d_step sequence", (char *) 0);
+       }
+}
+
+int
+is_skip(Lextok *n)
+{
+       return (n->ntyp == PRINT
+       ||      n->ntyp == PRINTM
+       ||      (n->ntyp == 'c'
+               && n->lft
+               && n->lft->ntyp == CONST
+               && n->lft->val  == 1));
+}
+
+void
+check_sequence(Sequence *s)
+{      Element *e, *le = ZE;
+       Lextok *n;
+       int cnt = 0;
+
+       for (e = s->frst; e; le = e, e = e->nxt)
+       {       n = e->n;
+               if (is_skip(n) && !has_lab(e, 0))
+               {       cnt++;
+                       if (cnt > 1
+                       &&  n->ntyp != PRINT
+                       &&  n->ntyp != PRINTM)
+                       {       if (verbose&32)
+                                       printf("spin: line %d %s, redundant skip\n",
+                                               n->ln, n->fn->name);
+                               if (e != s->frst
+                               &&  e != s->last
+                               &&  e != s->extent)
+                               {       e->status |= DONE;      /* not unreachable */
+                                       le->nxt = e->nxt;       /* remove it */
+                                       e = le;
+                               }
+                       }
+               } else
+                       cnt = 0;
+       }
+}
+
+void
+prune_opts(Lextok *n)
+{      SeqList *l;
+       extern Symbol *context;
+       extern char *claimproc;
+
+       if (!n
+       || (context && claimproc && strcmp(context->name, claimproc) == 0))
+               return;
+
+       for (l = n->sl; l; l = l->nxt)  /* find sequences of unlabeled skips */
+               check_sequence(l->this);
+}
+
+Sequence *
+close_seq(int nottop)
+{      Sequence *s = cur_s->this;
+       Symbol *z;
+
+       if (nottop > 0 && (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,
+                       z->name);
+               switch (nottop) {
+               case 1:
+                       printf("=====> stmnt unless Label: stmnt\n");
+                       printf("sorry, cannot jump to the guard of an\n");
+                       printf("escape (it is not a unique state)\n");
+                       break;
+               case 2:
+                       printf("=====> instead of  ");
+                       printf("\"Label: stmnt unless stmnt\"\n");
+                       printf("=====> always use  ");
+                       printf("\"Label: { stmnt unless stmnt }\"\n");
+                       break;
+               case 3:
+                       printf("=====> instead of  ");
+                       printf("\"atomic { Label: statement ... }\"\n");
+                       printf("=====> always use  ");
+                       printf("\"Label: atomic { statement ... }\"\n");
+                       break;
+               case 4:
+                       printf("=====> instead of  ");
+                       printf("\"d_step { Label: statement ... }\"\n");
+                       printf("=====> always use  ");
+                       printf("\"Label: d_step { statement ... }\"\n");
+                       break;
+               case 5:
+                       printf("=====> instead of  ");
+                       printf("\"{ Label: statement ... }\"\n");
+                       printf("=====> always use  ");
+                       printf("\"Label: { statement ... }\"\n");
+                       break;
+               case 6:
+                       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("Label:  do (or if)\n");
+                       printf("        :: ...\n");
+                       printf("        :: statement\n");
+                       printf("        od (or fi)\n");
+                       break;
+               case 7:
+                       printf("cannot happen - labels\n");
+                       break;
+               }
+               alldone(1);
+       }
+
+       if (nottop == 4
+       && !Rjumpslocal(s->frst, s->last))
+               fatal("non_local jump in d_step sequence", (char *) 0);
+
+       cur_s = cur_s->nxt;
+       s->maxel = Elcnt;
+       s->extent = s->last;
+       if (!s->last)
+               fatal("sequence must have at least one statement", (char *) 0);
+       return s;
+}
+
+Lextok *
+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
+       {       open_seq(0); add_seq(Es);
+               Sl = seqlist(close_seq(1), 0);
+       }
+
+       if (No->ntyp == NON_ATOMIC)
+       {       No->sl->nxt = Sl;
+               Sl = No->sl;
+       } else  if (No->ntyp == ':'
+               && (No->lft->ntyp == NON_ATOMIC
+               ||  No->lft->ntyp == ATOMIC
+               ||  No->lft->ntyp == D_STEP))
+       {
+               int tok = No->lft->ntyp;
+
+               No->lft->sl->nxt = Sl;
+               Re->sl = No->lft->sl;
+
+               open_seq(0); add_seq(Re);
+               Re = nn(ZN, tok, ZN, ZN);
+               Re->sl = seqlist(close_seq(7), 0);
+               Re->ln = No->ln;
+               Re->fn = No->fn;
+
+               Re = nn(No, ':', Re, ZN);       /* lift label */
+               Re->ln = No->ln;
+               Re->fn = No->fn;
+               return Re;
+       } else
+       {       open_seq(0); add_seq(No);
+               Sl = seqlist(close_seq(2), Sl);
+       }
+
+       Re->sl = Sl;
+       return Re;
+}
+
+SeqList *
+seqlist(Sequence *s, SeqList *r)
+{      SeqList *t = (SeqList *) emalloc(sizeof(SeqList));
+
+       t->this = s;
+       t->nxt = r;
+       return t;
+}
+
+static Element *
+new_el(Lextok *n)
+{      Element *m;
+
+       if (n)
+       {       if (n->ntyp == IF || n->ntyp == DO)
+                       return if_seq(n);
+               if (n->ntyp == UNLESS)
+                       return unless_seq(n);
+       }
+       m = (Element *) emalloc(sizeof(Element));
+       m->n = n;
+       m->seqno = Elcnt++;
+       m->Seqno = Unique++;
+       m->Nxt = Al_El; Al_El = m;
+       return m;
+}
+
+static int
+has_chanref(Lextok *n)
+{
+       if (!n) return 0;
+
+       switch (n->ntyp) {
+       case 's':       case 'r':
+#if 0
+       case 'R':       case LEN:
+#endif
+       case FULL:      case NFULL:
+       case EMPTY:     case NEMPTY:
+               return 1;
+       default:
+               break;
+       }
+       if (has_chanref(n->lft))
+               return 1;
+
+       return has_chanref(n->rgt);
+}
+
+void
+loose_ends(void)       /* properly tie-up ends of sub-sequences */
+{      Element *e, *f;
+
+       for (e = Al_El; e; e = e->Nxt)
+       {       if (!e->n
+               ||  !e->nxt)
+                       continue;
+               switch (e->n->ntyp) {
+               case ATOMIC:
+               case NON_ATOMIC:
+               case D_STEP:
+                       f = e->nxt;
+                       while (f && f->n->ntyp == '.')
+                               f = f->nxt;
+                       if (0) printf("link %d, {%d .. %d} -> %d (ntyp=%d) was %d\n",
+                               e->seqno,
+                               e->n->sl->this->frst->seqno,
+                               e->n->sl->this->last->seqno,
+                               f?f->seqno:-1, f?f->n->ntyp:-1,
+                               e->n->sl->this->last->nxt?e->n->sl->this->last->nxt->seqno:-1);
+                       if (!e->n->sl->this->last->nxt)
+                               e->n->sl->this->last->nxt = f;
+                       else
+                       {       if (e->n->sl->this->last->nxt->n->ntyp != GOTO)
+                               {       if (!f || e->n->sl->this->last->nxt->seqno != f->seqno)
+                                       non_fatal("unexpected: loose ends", (char *)0);
+                               } else
+                                       e->n->sl->this->last = e->n->sl->this->last->nxt;
+                               /*
+                                * fix_dest can push a goto into the nxt position
+                                * in that case the goto wins and f is not needed
+                                * but the last fields needs adjusting
+                                */
+                       }
+                       break;
+       }       }
+}
+
+static Element *
+if_seq(Lextok *n)
+{      int     tok = n->ntyp;
+       SeqList *s  = n->sl;
+       Element *e  = new_el(ZN);
+       Element *t  = new_el(nn(ZN,'.',ZN,ZN)); /* target */
+       SeqList *z, *prev_z = (SeqList *) 0;
+       SeqList *move_else  = (SeqList *) 0;    /* to end of optionlist */
+       int     ref_chans = 0;
+
+       for (z = s; z; z = z->nxt)
+       {       if (!z->this->frst)
+                       continue;
+               if (z->this->frst->n->ntyp == ELSE)
+               {       if (move_else)
+                               fatal("duplicate `else'", (char *) 0);
+                       if (z->nxt)     /* is not already at the end */
+                       {       move_else = z;
+                               if (prev_z)
+                                       prev_z->nxt = z->nxt;
+                               else
+                                       s = n->sl = z->nxt;
+                               continue;
+                       }
+               } else
+                       ref_chans |= has_chanref(z->this->frst->n);
+               prev_z = z;
+       }
+       if (move_else)
+       {       move_else->nxt = (SeqList *) 0;
+               /* if there is no prev, then else was at the end */
+               if (!prev_z) fatal("cannot happen - if_seq", (char *) 0);
+               prev_z->nxt = move_else;
+               prev_z = move_else;
+       }
+       if (prev_z
+       &&  ref_chans
+       &&  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);
+               nr_errs--;
+       }
+
+       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)
+               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 */
+       }
+       add_el(e, cur_s->this);
+       add_el(t, cur_s->this);
+       return e;                       /* destination node for label */
+}
+
+static void
+escape_el(Element *f, Sequence *e)
+{      SeqList *z;
+
+       for (z = f->esc; z; z = z->nxt)
+               if (z->this == e)
+                       return; /* already there */
+
+       /* cover the lower-level escapes of this state */
+       for (z = f->esc; z; z = z->nxt)
+               attach_escape(z->this, e);
+
+       /* now attach escape to the state itself */
+
+       f->esc = seqlist(e, f->esc);    /* in lifo order... */
+#ifdef DEBUG
+       printf("attach %d (", e->frst->Seqno);
+       comment(stdout, e->frst->n, 0);
+       printf(")       to %d (", f->Seqno);
+       comment(stdout, f->n, 0);
+       printf(")\n");
+#endif
+       switch (f->n->ntyp) {
+       case UNLESS:
+               attach_escape(f->sub->this, e);
+               break;
+       case IF:
+       case DO:
+               for (z = f->sub; z; z = z->nxt)
+                       attach_escape(z->this, e);
+               break;
+       case D_STEP:
+               /* attach only to the guard stmnt */
+               escape_el(f->n->sl->this->frst, e);
+               break;
+       case ATOMIC:
+       case NON_ATOMIC:
+               /* attach to all stmnts */
+               attach_escape(f->n->sl->this, e);
+               break;
+       }
+}
+
+static void
+attach_escape(Sequence *n, Sequence *e)
+{      Element *f;
+
+       for (f = n->frst; f; f = f->nxt)
+       {       escape_el(f, e);
+               if (f == n->extent)
+                       break;
+       }
+}
+
+static Element *
+unless_seq(Lextok *n)
+{      SeqList *s  = n->sl;
+       Element *e  = new_el(ZN);
+       Element *t  = new_el(nn(ZN,'.',ZN,ZN)); /* target */
+       SeqList *z;
+
+       e->n = nn(n, UNLESS, ZN, ZN);
+       e->n->sl = s;                   /* info only */
+       e->sub = s;
+
+       /* need 2 sequences: normal execution and escape */
+       if (!s || !s->nxt || s->nxt->nxt)
+               fatal("unexpected unless structure", (char *)0);
+
+       /* append the target state to both */
+       for (z = s; z; z = z->nxt)
+               add_el(t, z->this);
+
+       /* attach escapes to all states in normal sequence */
+       attach_escape(s->this, s->nxt->this);
+
+       add_el(e, cur_s->this);
+       add_el(t, cur_s->this);
+#ifdef DEBUG
+       printf("unless element (%d,%d):\n", e->Seqno, t->Seqno);
+       for (z = s; z; z = z->nxt)
+       {       Element *x; printf("\t%d,%d,%d :: ",
+               z->this->frst->Seqno,
+               z->this->extent->Seqno,
+               z->this->last->Seqno);
+               for (x = z->this->frst; x; x = x->nxt)
+                       printf("(%d)", x->Seqno);
+               printf("\n");
+       }
+#endif
+       return e;
+}
+
+Element *
+mk_skip(void)
+{      Lextok  *t = nn(ZN, CONST, ZN, ZN);
+       t->val = 1;
+       return new_el(nn(ZN, 'c', t, ZN));
+}
+
+static void
+add_el(Element *e, Sequence *s)
+{
+       if (e->n->ntyp == GOTO)
+       {       Symbol *z = has_lab(e, (1|2|4));
+               if (z)
+               {       Element *y; /* insert a skip */
+                       y = mk_skip();
+                       mov_lab(z, e, y); /* inherit label */
+                       add_el(y, s);
+       }       }
+#ifdef DEBUG
+       printf("add_el %d after %d -- ",
+       e->Seqno, (s->last)?s->last->Seqno:-1);
+       comment(stdout, e->n, 0);
+       printf("\n");
+#endif
+       if (!s->frst)
+               s->frst = e;
+       else
+               s->last->nxt = e;
+       s->last = e;
+}
+
+static Element *
+colons(Lextok *n)
+{
+       if (!n)
+               return ZE;
+       if (n->ntyp == ':')
+       {       Element *e = colons(n->lft);
+               set_lab(n->sym, e);
+               return e;
+       }
+       innermost = n;
+       return new_el(n);
+}
+
+void
+add_seq(Lextok *n)
+{      Element *e;
+
+       if (!n) return;
+       innermost = n;
+       e = colons(n);
+       if (innermost->ntyp != IF
+       &&  innermost->ntyp != DO
+       &&  innermost->ntyp != UNLESS)
+               add_el(e, cur_s->this);
+}
+
+void
+set_lab(Symbol *s, Element *e)
+{      Label *l; extern Symbol *context;
+
+       if (!s) return;
+       for (l = labtab; l; l = l->nxt)
+               if (l->s == s && l->c == context)
+               {       non_fatal("label %s redeclared", s->name);
+                       break;
+               }
+       l = (Label *) emalloc(sizeof(Label));
+       l->s = s;
+       l->c = context;
+       l->e = e;
+       l->nxt = labtab;
+       labtab = l;
+}
+
+Element *
+get_lab(Lextok *n, int md)
+{      Label *l;
+       Symbol *s = n->sym;
+
+       for (l = labtab; l; l = l->nxt)
+               if (s == l->s)
+                       return (l->e);
+
+       lineno = n->ln;
+       Fname = n->fn;
+       if (md) fatal("undefined label %s", s->name);
+       return ZE;
+}
+
+Symbol *
+has_lab(Element *e, int special)
+{      Label *l;
+
+       for (l = labtab; l; l = l->nxt)
+       {       if (e != l->e)
+                       continue;
+               if (special == 0
+               ||  ((special&1) && !strncmp(l->s->name, "accept", 6))
+               ||  ((special&2) && !strncmp(l->s->name, "end", 3))
+               ||  ((special&4) && !strncmp(l->s->name, "progress", 8)))
+                       return (l->s);
+       }
+       return ZS;
+}
+
+static void
+mov_lab(Symbol *z, Element *e, Element *y)
+{      Label *l;
+
+       for (l = labtab; l; l = l->nxt)
+               if (e == l->e)
+               {       l->e = y;
+                       return;
+               }
+       if (e->n)
+       {       lineno = e->n->ln;
+               Fname  = e->n->fn;
+       }
+       fatal("cannot happen - mov_lab %s", z->name);
+}
+
+void
+fix_dest(Symbol *c, Symbol *a)         /* c:label name, a:proctype name */
+{      Label *l; extern Symbol *context;
+
+#if 0
+       printf("ref to label '%s' in proctype '%s', search:\n",
+               c->name, a->name);
+       for (l = labtab; l; l = l->nxt)
+               printf("        %s in   %s\n", l->s->name, l->c->name);
+#endif
+
+       for (l = labtab; l; l = l->nxt)
+       {       if (strcmp(c->name, l->s->name) == 0
+               &&  strcmp(a->name, l->c->name) == 0)   /* ? */
+                       break;
+       }
+       if (!l)
+       {       printf("spin: label '%s' (proctype %s)\n", c->name, a->name);
+               non_fatal("unknown label '%s'", c->name);
+               if (context == a)
+               printf("spin: cannot remote ref a label inside the same proctype\n");
+               return;
+       }
+       if (!l->e || !l->e->n)
+               fatal("fix_dest error (%s)", c->name);
+       if (l->e->n->ntyp == GOTO)
+       {       Element *y = (Element *) emalloc(sizeof(Element));
+               int     keep_ln = l->e->n->ln;
+               Symbol  *keep_fn = l->e->n->fn;
+
+               /* insert skip - or target is optimized away */
+               y->n = l->e->n;           /* copy of the goto   */
+               y->seqno = find_maxel(a); /* unique seqno within proc */
+               y->nxt = l->e->nxt;
+               y->Seqno = Unique++; y->Nxt = Al_El; Al_El = y;
+
+               /* turn the original element+seqno into a skip */
+               l->e->n = nn(ZN, 'c', nn(ZN, CONST, ZN, ZN), ZN);
+               l->e->n->ln = l->e->n->lft->ln = keep_ln;
+               l->e->n->fn = l->e->n->lft->fn = keep_fn;
+               l->e->n->lft->val = 1;
+               l->e->nxt = y;          /* append the goto  */
+       }
+       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);
+       }
+}
+
+int
+find_lab(Symbol *s, Symbol *c, int markit)
+{      Label *l;
+
+       for (l = labtab; l; l = l->nxt)
+       {       if (strcmp(s->name, l->s->name) == 0
+               &&  strcmp(c->name, l->c->name) == 0)
+               {       l->visible |= markit;
+                       return (l->e->seqno);
+       }       }
+       return 0;
+}
+
+void
+pushbreak(void)
+{      Lbreak *r = (Lbreak *) emalloc(sizeof(Lbreak));
+       Symbol *l;
+       char buf[64];
+
+       sprintf(buf, ":b%d", break_id++);
+       l = lookup(buf);
+       r->l = l;
+       r->nxt = breakstack;
+       breakstack = r;
+}
+
+Symbol *
+break_dest(void)
+{
+       if (!breakstack)
+               fatal("misplaced break statement", (char *)0);
+       return breakstack->l;
+}
+
+void
+make_atomic(Sequence *s, int added)
+{      Element *f;
+
+       walk_atomic(s->frst, s->last, added);
+
+       f = s->last;
+       switch (f->n->ntyp) {   /* is last step basic stmnt or sequence ? */
+       case NON_ATOMIC:
+       case ATOMIC:
+               /* redo and search for the last step of that sequence */
+               make_atomic(f->n->sl->this, added);
+               break;
+
+       case UNLESS:
+               /* escapes are folded into main sequence */
+               make_atomic(f->sub->this, added);
+               break;
+
+       default:
+               f->status &= ~ATOM;
+               f->status |= L_ATOM;
+               break;
+       }
+}
+
+static void
+walk_atomic(Element *a, Element *b, int added)
+{      Element *f; Symbol *ofn; int oln;
+       SeqList *h;
+
+       ofn = Fname;
+       oln = lineno;
+       for (f = a; ; f = f->nxt)
+       {       f->status |= (ATOM|added);
+               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");
+                       goto mknonat;
+               case D_STEP:
+                       if (!(verbose&32))
+                       {       if (added) goto mknonat;
+                               break;
+                       }
+                       printf("spin: warning, line %3d %s, d_step inside ",
+                        f->n->ln, f->n->fn->name);
+                       if (added)
+                       {       printf("d_step (ignored)\n");
+                               goto mknonat;
+                       }
+                       printf("atomic\n");
+                       break;
+               case NON_ATOMIC:
+mknonat:               f->n->ntyp = NON_ATOMIC; /* can jump here */
+                       h = f->n->sl;
+                       walk_atomic(h->this->frst, h->this->last, added);
+                       break;
+               case UNLESS:
+                       if (added)
+                       { printf("spin: error, line %3d %s, unless in d_step (ignored)\n",
+                                f->n->ln, f->n->fn->name);
+                       }
+               }
+               for (h = f->sub; h; h = h->nxt)
+                       walk_atomic(h->this->frst, h->this->last, added);
+               if (f == b)
+                       break;
+       }
+       Fname = ofn;
+       lineno = oln;
+}
+
+void
+dumplabels(void)
+{      Label *l;
+
+       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);
+}
diff --git a/trunk/verif/Spin/Src5.1.6/guided.c b/trunk/verif/Spin/Src5.1.6/guided.c
new file mode 100755 (executable)
index 0000000..5f72f69
--- /dev/null
@@ -0,0 +1,333 @@
+/***** 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            */
+
+#include "spin.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "y.tab.h"
+
+extern RunList *run, *X;
+extern Element *Al_El;
+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 void ana_src(int, int);
+
+int    TstOnly = 0, pno;
+
+static int     lastclaim = -1;
+static FILE    *fd;
+static void    lost_trail(void);
+
+static void
+whichproc(int p)
+{      RunList *oX;
+
+       for (oX = run; oX; oX = oX->nxt)
+               if (oX->pid == p)
+               {       printf("(%s) ", oX->n->name);
+                       break;
+               }
+}
+
+static int
+newer(char *f1, char *f2)
+{
+#if defined(WIN32) || defined(WIN64)
+       struct _stat x, y;
+#else
+       struct stat x, y;
+#endif
+
+       if (stat(f1, (struct stat *)&x) < 0) return 0;
+       if (stat(f2, (struct stat *)&y) < 0) return 1;
+       if (x.st_mtime < y.st_mtime) return 0;
+       
+       return 1;
+}
+
+void
+hookup(void)
+{      Element *e;
+
+       for (e = Al_El; e; e = e->Nxt)
+               if (e->n
+               && (e->n->ntyp == ATOMIC
+               ||  e->n->ntyp == NON_ATOMIC
+               ||  e->n->ntyp == D_STEP))
+                       (void) huntstart(e);
+}
+
+int
+not_claim(void)
+{
+       return (!Have_claim || !X || X->pid != 0);
+}
+
+void
+match_trail(void)
+{      int i, a, nst;
+       Element *dothis;
+       char snap[512], *q;
+
+       /*
+        * if source model name is leader.pml
+        * look for the trail file under these names:
+        *      leader.pml.trail
+        *      leader.pml.tra
+        *      leader.trail
+        *      leader.tra
+        */
+
+       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 */
+               if ((fd = fopen(snap, "r")) == NULL)
+               {       if ((q = strchr(oFname->name, '.')) != NULL)
+                       {       *q = '\0';
+                               if (ntrail)
+                                       sprintf(snap, "%s%d.trail",
+                                               oFname->name, ntrail);
+                               else
+                                       sprintf(snap, "%s.trail",
+                                               oFname->name);
+                               *q = '.';
+
+                               if ((fd = fopen(snap, "r")) != NULL)
+                                       goto okay;
+
+                               snap[strlen(snap)-2] = '\0';    /* last try */
+                               if ((fd = fopen(snap, "r")) != NULL)
+                                       goto okay;
+                       }
+                       printf("spin: cannot find trail file\n");
+                       alldone(1);
+       }       }
+okay:          
+       if (xspin == 0 && newer(oFname->name, snap))
+       printf("spin: warning, \"%s\" is newer than %s\n",
+               oFname->name, snap);
+
+       Tval = 1;
+
+       /*
+        * sets Tval because timeouts may be part of trail
+        * this used to also set m_loss to 1, but that is
+        * better handled with the runtime -m flag
+        */
+
+       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 (verbose)
+                       {       if (columns == 2)
+                               dotag(stdout, " CYCLE>\n");
+                               else
+                               dotag(stdout, "<<<<<START OF CYCLE>>>>>\n");
+                       }
+                       continue;
+               }
+
+               if (cutoff > 0 && depth >= cutoff)
+               {       printf("-------------\n");
+                       printf("depth-limit (-u%d steps) reached\n", cutoff);
+                       break;
+               }
+
+               if (Skip_claim && pno == 0) continue;
+
+               for (dothis = Al_El; dothis; dothis = dothis->Nxt)
+               {       if (dothis->Seqno == nst)
+                               break;
+               }
+               if (!dothis)
+               {       printf("%3d: proc %d, no matching stmnt %d\n",
+                               depth, pno - Have_claim, nst);
+                       lost_trail();
+               }
+
+               i = nproc - nstop + Skip_claim;
+
+               if (dothis->n->ntyp == '@')
+               {       if (pno == i-1)
+                       {       run = run->nxt;
+                               nstop++;
+                               if (verbose&4)
+                               {       if (columns == 2)
+                                       {       dotag(stdout, "<end>\n");
+                                               continue;
+                                       }
+                                       if (Have_claim && pno == 0)
+                                       printf("%3d: claim terminates\n",
+                                               depth);
+                                       else
+                                       printf("%3d: proc %d terminates\n",
+                                               depth, pno - Have_claim);
+                               }
+                               continue;
+                       }
+                       if (pno <= 1) continue; /* init dies before never */
+                       printf("%3d: stop error, ", depth);
+                       printf("proc %d (i=%d) trans %d, %c\n",
+                               pno - Have_claim, i, nst, dothis->n->ntyp);
+                       lost_trail();
+               }
+
+               if (!xspin && (verbose&32))
+               {       printf("i=%d pno %d\n", i, pno);
+               }
+
+               for (X = run; X; X = X->nxt)
+               {       if (--i == pno)
+                               break;
+               }
+
+               if (!X)
+               {       if (verbose&32)
+                       {       printf("%3d: no process %d (step %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
+               {       X->pc  = dothis;
+               }
+
+               lineno = dothis->n->ln;
+               Fname  = dothis->n->fn;
+
+               if (dothis->n->ntyp == D_STEP)
+               {       Element *g, *og = dothis;
+                       do {
+                               g = eval_sub(og);
+                               if (g && depth >= jumpsteps
+                               && ((verbose&32) || ((verbose&4) && not_claim())))
+                               {       if (columns != 2)
+                                       {       p_talk(og, 1);
+               
+                                               if (og->n->ntyp == D_STEP)
+                                               og = og->n->sl->this->frst;
+               
+                                               printf("\t[");
+                                               comment(stdout, og->n, 0);
+                                               printf("]\n");
+                                       }
+                                       if (verbose&1) dumpglobals();
+                                       if (verbose&2) dumplocal(X);
+                                       if (xspin) printf("\n");
+                               }
+                               og = g;
+                       } while (g && g != dothis->nxt);
+                       if (X != NULL)
+                       {       X->pc = g?huntele(g, 0, -1):g;
+                       }
+               } else
+               {
+keepgoing:             if (dothis->merge_start)
+                               a = dothis->merge_start;
+                       else
+                               a = dothis->merge;
+
+                       if (X != NULL)
+                       {       X->pc = eval_sub(dothis);
+                               if (X->pc) X->pc = huntele(X->pc, 0, a);
+                       }
+
+                       if (depth >= jumpsteps
+                       && ((verbose&32) || ((verbose&4) && not_claim())))      /* -v or -p */
+                       {       if (columns != 2)
+                               {       p_talk(dothis, 1);
+       
+                                       if (dothis->n->ntyp == D_STEP)
+                                       dothis = dothis->n->sl->this->frst;
+               
+                                       printf("\t[");
+                                       comment(stdout, dothis->n, 0);
+                                       printf("]");
+                                       if (a && (verbose&32))
+                                       printf("\t<merge %d now @%d>",
+                                               dothis->merge,
+                                               (X && X->pc)?X->pc->seqno:-1);
+                                       printf("\n");
+                               }
+                               if (verbose&1) dumpglobals();
+                               if (verbose&2) dumplocal(X);
+                               if (xspin) printf("\n");
+
+                               if (X && !X->pc)
+                               {       X->pc = dothis;
+                                       printf("\ttransition failed\n");
+                                       a = 0;  /* avoid inf loop */
+                               }
+                       }
+                       if (a && X && X->pc && X->pc->seqno != a)
+                       {       dothis = X->pc;
+                               goto keepgoing;
+               }       }
+
+               if (Have_claim && X && X->pid == 0
+               &&  dothis->n
+               &&  lastclaim != dothis->n->ln)
+               {       lastclaim = dothis->n->ln;
+                       if (columns == 2)
+                       {       char t[128];
+                               sprintf(t, "#%d", lastclaim);
+                               pstext(0, t);
+                       } else
+                       {
+                               printf("Never claim moves to line %d\t[", lastclaim);
+                               comment(stdout, dothis->n, 0);
+                               printf("]\n");
+       }       }       }
+       printf("spin: trail ends after %d steps\n", depth);
+       wrapup(0);
+}
+
+static void
+lost_trail(void)
+{      int d, p, n, l;
+
+       while (fscanf(fd, "%d:%d:%d:%d\n", &d, &p, &n, &l) == 4)
+       {       printf("step %d: proc  %d ", d, p); whichproc(p);
+               printf("(state %d) - d %d\n", n, l);
+       }
+       wrapup(1);      /* no return */
+}
+
+int
+pc_value(Lextok *n)
+{      int i = nproc - nstop;
+       int pid = eval(n);
+       RunList *Y;
+
+       for (Y = run; Y; Y = Y->nxt)
+       {       if (--i == pid)
+                       return Y->pc->seqno;
+       }
+       return 0;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/main.c b/trunk/verif/Spin/Src5.1.6/main.c
new file mode 100755 (executable)
index 0000000..528b729
--- /dev/null
@@ -0,0 +1,788 @@
+/***** 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            */
+
+#include <stdlib.h>
+#include "spin.h"
+#include "version.h"
+#include <signal.h>
+/* #include <malloc.h> */
+#include <time.h>
+#ifdef PC
+#include <io.h>
+extern int unlink(const char *);
+#else
+#include <unistd.h>
+#endif
+#include "y.tab.h"
+
+extern int     DstepStart, lineno, tl_terse;
+extern FILE    *yyin, *yyout, *tl_out;
+extern Symbol  *context;
+extern char    *claimproc;
+extern void    repro_src(void);
+extern void    qhide(int);
+
+Symbol *Fname, *oFname;
+
+int    Etimeouts;      /* nr timeouts in program */
+int    Ntimeouts;      /* nr timeouts in never claim */
+int    analyze, columns, dumptab, has_remote, has_remvar;
+int    interactive, jumpsteps, m_loss, nr_errs, cutoff;
+int    s_trail, ntrail, verbose, xspin, notabs, rvopt;
+int    no_print, no_wrapup, Caccess, limited_vis, like_java;
+int    separate;       /* separate compilation */
+int    export_ast;     /* pangen5.c */
+
+int    merger = 1, deadvar = 1, ccache = 1;
+
+static int preprocessonly, SeedUsed;
+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:
+       1       -g global variable values
+       2       -l local variable values
+       4       -p all process actions
+       8       -r receives
+       16      -s sends
+       32      -v verbose
+       64      -w very verbose
+#endif
+
+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    *PreArg[64];
+static int     PreCnt = 0;
+static char    out1[64];
+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    "/lib/cpp"      /* classic Unix systems */
+#endif
+#endif
+#endif
+
+#endif
+static char    *PreProc = CPP;
+extern int     depth; /* at least some steps were made */
+
+void
+alldone(int estatus)
+{
+       if (preprocessonly == 0
+       &&  strlen(out1) > 0)
+               (void) unlink((const char *)out1);
+
+       if (seedy && !analyze && !export_ast
+       && !s_trail && !preprocessonly && depth > 0)
+               printf("seed used: %d\n", SeedUsed);
+
+       if (xspin && (analyze || s_trail))
+       {       if (estatus)
+                       printf("spin: %d error(s) - aborting\n",
+                       estatus);
+               else
+                       printf("Exit-Status 0\n");
+       }
+       exit(estatus);
+}
+
+void
+preprocess(char *a, char *b, int a_tmp)
+{      char precmd[1024], cmd[2048]; int i;
+#ifdef PC
+       extern int try_zpp(char *, char *);
+       if (PreCnt == 0 && try_zpp(a, b)) goto out;
+#endif
+       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))
+       {       (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)
+{
+       printf("use: spin [-option] ... [-option] file\n");
+       printf("\tNote: file must always be the last argument\n");
+       printf("\t-A apply slicing algorithm\n");
+       printf("\t-a generate a verifier in pan.c\n");
+       printf("\t-B no final state details in simulations\n");
+       printf("\t-b don't execute printfs in simulation\n");
+       printf("\t-C print channel access info (combine with -g etc.)\n");
+       printf("\t-c columnated -s -r simulation output\n");
+       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-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-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-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-l print all local variables\n");
+       printf("\t-M print msc-flow in Postscript\n");
+       printf("\t-m lose msgs sent to full queues\n");
+       printf("\t-N file use never claim stored in file\n");
+       printf("\t-nN seed for random nr generator\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-Pxxx use xxx for preprocessing\n");
+       printf("\t-p print all statements\n");
+       printf("\t-qN suppress io for queue N in printouts\n");
+       printf("\t-r print receive events\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-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");
+       printf("\t-w very verbose (when combined with -l or -g)\n");
+       printf("\t-[XYZ] reserved for use by xspin interface\n");
+       printf("\t-V print version number and exit\n");
+       alldone(1);
+}
+
+void
+optimizations(int nr)
+{
+       switch (nr) {
+       case '1':
+               dataflow = 1 - dataflow; /* dataflow */
+               if (verbose&32)
+               printf("spin: dataflow optimizations turned %s\n",
+                       dataflow?"on":"off");
+               break;
+       case '2':
+               /* dead variable elimination */
+               deadvar = 1 - deadvar;
+               if (verbose&32)
+               printf("spin: dead variable elimination turned %s\n",
+                       deadvar?"on":"off");
+               break;
+       case '3':
+               /* statement merging */
+               merger = 1 - merger;
+               if (verbose&32)
+               printf("spin: statement merging turned %s\n",
+                       merger?"on":"off");
+               break;
+
+       case '4':
+               /* rv optimization */
+               rvopt = 1 - rvopt;
+               if (verbose&32)
+               printf("spin: rendezvous optimization turned %s\n",
+                       rvopt?"on":"off");
+               break;
+       case '5':
+               /* case caching */
+               ccache = 1 - ccache;
+               if (verbose&32)
+               printf("spin: case caching turned %s\n",
+                       ccache?"on":"off");
+               break;
+       default:
+               printf("spin: bad or missing parameter on -o\n");
+               usage();
+               break;
+       }
+}
+
+#if 0
+static int
+Rename(const char *old, char *new)
+{      FILE *fo, *fn;
+       char buf[1024];
+
+       if ((fo = fopen(old, "r")) == NULL)
+       {       printf("spin: cannot open %s\n", old);
+               return 1;
+       }
+       if ((fn = fopen(new, "w")) == NULL)
+       {       printf("spin: cannot create %s\n", new);
+               fclose(fo);
+               return 2;
+       }
+       while (fgets(buf, 1024, fo))
+               fputs(buf, fn);
+
+       fclose(fo);
+       fclose(fn);
+
+       return 0;       /* success */
+}
+#endif
+
+int
+main(int argc, char *argv[])
+{      Symbol *s;
+       int T = (int) time((time_t *)0);
+       int usedopts = 0;
+       extern void ana_src(int, int);
+
+       yyin  = stdin;
+       yyout = stdout;
+       tl_out = stdout;
+
+       /* unused flags: e, w, x, y, z, A, G, I, L, O, Q, R, S, T, 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 'B': no_wrapup = 1; break;
+               case 'b': no_print = 1; break;
+               case 'C': Caccess = 1; break;
+               case 'c': columns = 1; break;
+               case 'D': PreArg[++PreCnt] = (char *) &argv[1][0];
+                         break;        /* define */
+               case 'd': dumptab =  1; break;
+               case 'E': PreArg[++PreCnt] = (char *) &argv[1][2];
+                         break;
+               case 'F': ltl_file = (char **) (argv+2);
+                         argc--; argv++; break;
+               case 'f': add_ltl = (char **) argv;
+                         argc--; argv++; break;
+               case 'g': verbose +=  1; break;
+               case 'h': seedy = 1; break;
+               case 'i': interactive = 1; break;
+               case 'I': inlineonly = 1; break;
+               case 'J': like_java = 1; break;
+               case 'j': jumpsteps = atoi(&argv[1][2]); break;
+               case 'l': verbose +=  2; break;
+               case 'M': columns = 2; break;
+               case 'm': m_loss   =  1; break;
+               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]))
+                               qhide(atoi(&argv[1][2]));
+                         break;
+               case 'r': verbose +=  8; break;
+               case 's': verbose += 16; break;
+               case 'T': notabs = 1; break;
+               case 't': s_trail  =  1;
+                         if (isdigit(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 'v': verbose += 32; break;
+               case 'V': printf("%s\n", SpinVersion);
+                         alldone(0);
+                         break;
+               case 'w': verbose += 64; break;
+               case 'X': xspin = notabs = 1;
+#ifndef PC
+                         signal(SIGPIPE, alldone); /* not posix... */
+#endif
+                         break;
+               case 'Y': limited_vis = 1; break;       /* used by xspin */
+               case 'Z': preprocessonly = 1; break;    /* used by xspin */
+
+               default : usage(); break;
+               }
+               argc--; argv++;
+       }
+       if (usedopts && !analyze)
+               printf("spin: warning -o[123] option ignored in simulations\n");
+       
+       if (ltl_file)
+       {       char formula[4096];
+               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);
+               fclose(tl_out);
+               tl_out = stdout;
+               *ltl_file = (char *) formula;
+       }
+       if (argc > 1)
+       {       char cmd[128], out2[64];
+
+               /* must remain in current dir */
+               strcpy(out1, "pan.pre");
+
+               if (add_ltl || nvr_file)
+                       strcpy(out2, "pan.___");
+
+               if (add_ltl)
+               {       tl_out = cpyfile(argv[1], out2);
+                       nr_errs = tl_main(2, add_ltl);  /* in tl_main.c */
+                       fclose(tl_out);
+                       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);
+                       fclose(fd);
+                       preprocess(out2, out1, 1);
+               } else
+                       preprocess(argv[1], out1, 0);
+
+               if (preprocessonly)
+                       alldone(0);
+
+               if (!(yyin = fopen(out1, "r")))
+               {       printf("spin: cannot open %s\n", out1);
+                       alldone(1);
+               }
+
+               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);
+                       oFname->name[i-1] = '\0';
+                       oFname = lookup(&oFname->name[1]);
+               }
+       } else
+       {       oFname = Fname = lookup("<stdin>");
+               if (add_ltl)
+               {       if (argc > 0)
+                               exit(tl_main(2, add_ltl));
+                       printf("spin: missing argument to -f\n");
+                       alldone(1);
+               }
+               printf("%s\n", SpinVersion);
+               printf("reading input from stdin:\n");
+               fflush(stdout);
+       }
+       if (columns == 2)
+       {       extern void putprelude(void);
+               if (xspin || verbose&(1|4|8|16|32))
+               {       printf("spin: -c precludes all flags except -t\n");
+                       alldone(1);
+               }
+               putprelude();
+       }
+       if (columns && !(verbose&8) && !(verbose&16))
+               verbose += (8+16);
+       if (columns == 2 && limited_vis)
+               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;
+       s = lookup("_pid");     s->type = PREDEF;
+       s = lookup("_last");    s->type = PREDEF;
+       s = lookup("_nr_pr");   s->type = PREDEF; /* new 3.3.10 */
+
+       yyparse();
+       fclose(yyin);
+       loose_ends();
+
+       if (inlineonly)
+       {       repro_src();
+               return 0;
+       }
+
+       chanaccess();
+       if (!Caccess)
+       {       if (!s_trail && (dataflow || merger))
+                       ana_src(dataflow, merger);
+               sched();
+               alldone(nr_errs);
+       }
+       return 0;
+}
+
+int
+yywrap(void)   /* dummy routine */
+{
+       return 1;
+}
+
+void
+non_fatal(char *s1, char *s2)
+{      extern int yychar; extern char yytext[];
+
+       printf("spin: line %3d %s, Error: ",
+               lineno, Fname?Fname->name:"nofilename");
+       if (s2)
+               printf(s1, s2);
+       else
+               printf(s1);
+       if (yychar != -1 && yychar != 0)
+       {       printf("        saw '");
+               explain(yychar);
+               printf("'");
+       }
+       if (strlen(yytext)>1)
+               printf(" near '%s'", yytext);
+       printf("\n");
+       nr_errs++;
+}
+
+void
+fatal(char *s1, char *s2)
+{
+       non_fatal(s1, s2);
+       alldone(1);
+}
+
+char *
+emalloc(size_t n)
+{      char *tmp;
+
+       if (n == 0)
+               return NULL;    /* robert shelton 10/20/06 */
+
+       if (!(tmp = (char *) malloc(n)))
+               fatal("not enough memory", (char *)0);
+       memset(tmp, 0, n);
+       return tmp;
+}
+
+void
+trapwonly(Lextok *n /* , char *unused */)
+{      extern int realread;
+       short i = (n->sym)?n->sym->type:0;
+
+       if (i != MTYPE
+       &&  i != BIT
+       &&  i != BYTE
+       &&  i != SHORT
+       &&  i != INT
+       &&  i != UNSIGNED)
+               return;
+
+       if (realread)
+       n->sym->hidden |= 128;  /* var is read at least once */
+}
+
+void
+setaccess(Symbol *sp, Symbol *what, int cnt, int t)
+{      Access *a;
+
+       for (a = sp->access; a; a = a->lnk)
+               if (a->who == context
+               &&  a->what == what
+               &&  a->cnt == cnt
+               &&  a->typ == t)
+                       return;
+
+       a = (Access *) emalloc(sizeof(Access));
+       a->who = context;
+       a->what = what;
+       a->cnt = cnt;
+       a->typ = t;
+       a->lnk = sp->access;
+       sp->access = a;
+}
+
+Lextok *
+nn(Lextok *s, int t, Lextok *ll, Lextok *rl)
+{      Lextok *n = (Lextok *) emalloc(sizeof(Lextok));
+       static int warn_nn = 0;
+
+       n->ntyp = (short) t;
+       if (s && s->fn)
+       {       n->ln = s->ln;
+               n->fn = s->fn;
+       } else if (rl && rl->fn)
+       {       n->ln = rl->ln;
+               n->fn = rl->fn;
+       } else if (ll && ll->fn)
+       {       n->ln = ll->ln;
+               n->fn = ll->fn;
+       } else
+       {       n->ln = lineno;
+               n->fn = Fname;
+       }
+       if (s) n->sym  = s->sym;
+       n->lft  = ll;
+       n->rgt  = rl;
+       n->indstep = DstepStart;
+
+       if (t == TIMEOUT) Etimeouts++;
+
+       if (!context) return n;
+
+       if (t == 'r' || t == 's')
+               setaccess(n->sym, ZS, 0, t);
+       if (t == 'R')
+               setaccess(n->sym, ZS, 0, 'P');
+
+       if (context->name == claimproc)
+       {       int forbidden = separate;
+               switch (t) {
+               case ASGN:
+                       printf("spin: Warning, never claim has side-effect\n");
+                       break;
+               case 'r': case 's':
+                       non_fatal("never claim contains i/o stmnts",(char *)0);
+                       break;
+               case TIMEOUT:
+                       /* never claim polls timeout */
+                       if (Ntimeouts && Etimeouts)
+                               forbidden = 0;
+                       Ntimeouts++; Etimeouts--;
+                       break;
+               case LEN: case EMPTY: case FULL:
+               case 'R': case NFULL: case NEMPTY:
+                       /* status becomes non-exclusive */
+                       if (n->sym && !(n->sym->xu&XX))
+                       {       n->sym->xu |= XX;
+                               if (separate == 2) {
+                               printf("spin: warning, make sure that the S1 model\n");
+                               printf("      also polls channel '%s' in its claim\n",
+                               n->sym->name); 
+                       }       }
+                       forbidden = 0;
+                       break;
+               case 'c':
+                       AST_track(n, 0);        /* register as a slice criterion */
+                       /* fall thru */
+               default:
+                       forbidden = 0;
+                       break;
+               }
+               if (forbidden)
+               {       printf("spin: never, saw "); explain(t); printf("\n");
+                       fatal("incompatible with separate compilation",(char *)0);
+               }
+       } else if ((t == ENABLED || t == PC_VAL) && !(warn_nn&t))
+       {       printf("spin: Warning, using %s outside never claim\n",
+                       (t == ENABLED)?"enabled()":"pc_value()");
+               warn_nn |= t;
+       } else if (t == NONPROGRESS)
+       {       fatal("spin: Error, using np_ outside never claim\n", (char *)0);
+       }
+       return n;
+}
+
+Lextok *
+rem_lab(Symbol *a, Lextok *b, Symbol *c)       /* proctype name, pid, label name */
+{      Lextok *tmp1, *tmp2, *tmp3;
+
+       has_remote++;
+       c->type = LABEL;        /* refered to in global context here */
+       fix_dest(c, a);         /* in case target of rem_lab is jump */
+       tmp1 = nn(ZN, '?',   b, ZN); tmp1->sym = a;
+       tmp1 = nn(ZN, 'p', tmp1, ZN);
+       tmp1->sym = lookup("_p");
+       tmp2 = nn(ZN, NAME,  ZN, ZN); tmp2->sym = a;
+       tmp3 = nn(ZN, 'q', tmp2, ZN); tmp3->sym = c;
+       return nn(ZN, EQ, tmp1, tmp3);
+#if 0
+             .---------------EQ-------.
+            /                          \
+          'p' -sym-> _p               'q' -sym-> c (label name)
+          /                           /
+        '?' -sym-> a (proctype)     NAME -sym-> a (proctype name)
+        / 
+       b (pid expr)
+#endif
+}
+
+Lextok *
+rem_var(Symbol *a, Lextok *b, Symbol *c, Lextok *ndx)
+{      Lextok *tmp1;
+
+       has_remote++;
+       has_remvar++;
+       dataflow = 0;   /* turn off dead variable resets 4.2.5 */
+       tmp1 = nn(ZN, '?', b, ZN); tmp1->sym = a;
+       tmp1 = nn(ZN, 'p', tmp1, ndx);
+       tmp1->sym = c;
+       return tmp1;
+#if 0
+       cannot refer to struct elements
+       only to scalars and arrays
+
+           'p' -sym-> c (variable name)
+           / \______  possible arrayindex on c
+          /
+        '?' -sym-> a (proctype)
+        / 
+       b (pid expr)
+#endif
+}
+
+void
+explain(int n)
+{      FILE *fd = stdout;
+       switch (n) {
+       default:        if (n > 0 && n < 256)
+                               fprintf(fd, "'%c' = '", n);
+                       fprintf(fd, "%d'", n);
+                       break;
+       case '\b':      fprintf(fd, "\\b"); break;
+       case '\t':      fprintf(fd, "\\t"); break;
+       case '\f':      fprintf(fd, "\\f"); break;
+       case '\n':      fprintf(fd, "\\n"); break;
+       case '\r':      fprintf(fd, "\\r"); break;
+       case 'c':       fprintf(fd, "condition"); break;
+       case 's':       fprintf(fd, "send"); break;
+       case 'r':       fprintf(fd, "recv"); break;
+       case 'R':       fprintf(fd, "recv poll %s", Operator); break;
+       case '@':       fprintf(fd, "@"); break;
+       case '?':       fprintf(fd, "(x->y:z)"); break;
+       case ACTIVE:    fprintf(fd, "%sactive", Keyword); break;
+       case AND:       fprintf(fd, "%s&&",     Operator); break;
+       case ASGN:      fprintf(fd, "%s=",      Operator); break;
+       case ASSERT:    fprintf(fd, "%sassert", Function); break;
+       case ATOMIC:    fprintf(fd, "%satomic", Keyword); break;
+       case BREAK:     fprintf(fd, "%sbreak",  Keyword); break;
+       case C_CODE:    fprintf(fd, "%sc_code", Keyword); break;
+       case C_DECL:    fprintf(fd, "%sc_decl", Keyword); break;
+       case C_EXPR:    fprintf(fd, "%sc_expr", Keyword); break;
+       case C_STATE:   fprintf(fd, "%sc_state",Keyword); break;
+       case C_TRACK:   fprintf(fd, "%sc_track",Keyword); break;
+       case CLAIM:     fprintf(fd, "%snever",  Keyword); break;
+       case CONST:     fprintf(fd, "a constant"); break;
+       case DECR:      fprintf(fd, "%s--",     Operator); break;
+       case D_STEP:    fprintf(fd, "%sd_step", Keyword); break;
+       case D_PROCTYPE: fprintf(fd, "%sd_proctype", Keyword); break;
+       case DO:        fprintf(fd, "%sdo",     Keyword); break;
+       case DOT:       fprintf(fd, "."); break;
+       case ELSE:      fprintf(fd, "%selse",   Keyword); break;
+       case EMPTY:     fprintf(fd, "%sempty",  Function); break;
+       case ENABLED:   fprintf(fd, "%senabled",Function); break;
+       case EQ:        fprintf(fd, "%s==",     Operator); break;
+       case EVAL:      fprintf(fd, "%seval",   Function); break;
+       case FI:        fprintf(fd, "%sfi",     Keyword); break;
+       case FULL:      fprintf(fd, "%sfull",   Function); break;
+       case GE:        fprintf(fd, "%s>=",     Operator); break;
+       case GOTO:      fprintf(fd, "%sgoto",   Keyword); break;
+       case GT:        fprintf(fd, "%s>",      Operator); break;
+       case HIDDEN:    fprintf(fd, "%shidden", Keyword); break;
+       case IF:        fprintf(fd, "%sif",     Keyword); break;
+       case INCR:      fprintf(fd, "%s++",     Operator); break;
+       case INAME:     fprintf(fd, "inline name"); break;
+       case INLINE:    fprintf(fd, "%sinline", Keyword); break;
+       case INIT:      fprintf(fd, "%sinit",   Keyword); break;
+       case ISLOCAL:   fprintf(fd, "%slocal",  Keyword); break;
+       case LABEL:     fprintf(fd, "a label-name"); break;
+       case LE:        fprintf(fd, "%s<=",     Operator); break;
+       case LEN:       fprintf(fd, "%slen",    Function); break;
+       case LSHIFT:    fprintf(fd, "%s<<",     Operator); break;
+       case LT:        fprintf(fd, "%s<",      Operator); break;
+       case MTYPE:     fprintf(fd, "%smtype",  Keyword); break;
+       case NAME:      fprintf(fd, "an identifier"); break;
+       case NE:        fprintf(fd, "%s!=",     Operator); break;
+       case NEG:       fprintf(fd, "%s! (not)",Operator); break;
+       case NEMPTY:    fprintf(fd, "%snempty", Function); break;
+       case NFULL:     fprintf(fd, "%snfull",  Function); break;
+       case NON_ATOMIC: fprintf(fd, "sub-sequence"); break;
+       case NONPROGRESS: fprintf(fd, "%snp_",  Function); break;
+       case OD:        fprintf(fd, "%sod",     Keyword); break;
+       case OF:        fprintf(fd, "%sof",     Keyword); break;
+       case OR:        fprintf(fd, "%s||",     Operator); break;
+       case O_SND:     fprintf(fd, "%s!!",     Operator); break;
+       case PC_VAL:    fprintf(fd, "%spc_value",Function); break;
+       case PNAME:     fprintf(fd, "process name"); break;
+       case PRINT:     fprintf(fd, "%sprintf", Function); break;
+       case PRINTM:    fprintf(fd, "%sprintm", Function); break;
+       case PRIORITY:  fprintf(fd, "%spriority", Keyword); break;
+       case PROCTYPE:  fprintf(fd, "%sproctype",Keyword); break;
+       case PROVIDED:  fprintf(fd, "%sprovided",Keyword); break;
+       case RCV:       fprintf(fd, "%s?",      Operator); break;
+       case R_RCV:     fprintf(fd, "%s??",     Operator); break;
+       case RSHIFT:    fprintf(fd, "%s>>",     Operator); break;
+       case RUN:       fprintf(fd, "%srun",    Operator); break;
+       case SEP:       fprintf(fd, "token: ::"); break;
+       case SEMI:      fprintf(fd, ";"); break;
+       case SHOW:      fprintf(fd, "%sshow", Keyword); break;
+       case SND:       fprintf(fd, "%s!",      Operator); break;
+       case STRING:    fprintf(fd, "a string"); break;
+       case TRACE:     fprintf(fd, "%strace", Keyword); break;
+       case TIMEOUT:   fprintf(fd, "%stimeout",Keyword); break;
+       case TYPE:      fprintf(fd, "data typename"); break;
+       case TYPEDEF:   fprintf(fd, "%stypedef",Keyword); break;
+       case XU:        fprintf(fd, "%sx[rs]",  Keyword); break;
+       case UMIN:      fprintf(fd, "%s- (unary minus)", Operator); break;
+       case UNAME:     fprintf(fd, "a typename"); break;
+       case UNLESS:    fprintf(fd, "%sunless", Keyword); break;
+       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/make_pc b/trunk/verif/Spin/Src5.1.6/make_pc
new file mode 100755 (executable)
index 0000000..d6641e8
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+# SPIN - Verification Software - Version 5.1 - November 2007
+#
+# Tool documentation: http://spinroot.com/
+# bug-reports: bugs@spinroot.com            
+
+# This script is for compiling Spin on a PC with a Unix shell
+# It requires 3 things to be installed on your system:
+#      cygwin (for sh, bison yacc, echo, mv, and rm)
+#      either gcc or the Visual C++ compiler (cl)
+# On a 2.5GHz system everything compiles in under 1 second.
+# See also makefile for compiling Spin on a standard Unix/Linux system.
+
+# CC="gcc"
+# CFLAGS="-DPC -DNXT -O1 -Wall -ansi -w -o spin.exe"
+
+CC="cl"        # Visual Studio for a standalone compilation
+CFLAGS="-DPC -DNXT -DWIN32 -D_CONSOLE -O2 -Zp4 -nologo -wd4996 -Fespin.exe"
+
+yacc -v -d spin.y
+
+# compile for 32 or 64 bits:
+  $CC -DWIN32 $CFLAGS *.c
+# $CC -DWIN64 $CFLAGS *.c bufferoverflowu.lib
+
+rm -f *.o *.obj
+rm -f y?tab.? y.output
+
+# install in the usual place on cygwin:
+echo "mv spin.exe /usr/bin"
+mv spin.exe /usr/bin
diff --git a/trunk/verif/Spin/Src5.1.6/makefile b/trunk/verif/Spin/Src5.1.6/makefile
new file mode 100755 (executable)
index 0000000..c8c93c8
--- /dev/null
@@ -0,0 +1,74 @@
+# SPIN - Verification Software - Version 5.1 - November 2007
+#
+# Copyright  (c) 1989-2006 Lucent Technologies, Bell Labs
+# Extensions (c) 2006-2007 NASA/JPL California Institute of Technology
+# All Rights Reserved. For educational purposes only.
+# No guarantee whatsoever is expressed or implied by
+# the distribution of this code.
+#
+# Written by:    Gerard J. Holzmann
+# Documentation: http://spinroot.com/
+# Bug-reports:   bugs@spinroot.com
+
+CC=cc -DNXT    # -DNXT enables the X operator in LTL
+# CC=cc -m32 -DNXT     # for 32bit compilation on a 64bit system
+CFLAGS=-ansi -D_POSIX_SOURCE   # on some systems add: -I/usr/include
+
+# for a more picky compilation:
+# CFLAGS=-std=c99 -Wstrict-prototypes -pedantic -fno-strength-reduce -fno-builtin -W -Wshadow -Wpointer-arith -Wcast-qual -Winline -Wall -g
+
+#      on PC:          add -DPC to CFLAGS above
+#      on Solaris:     add -DSOLARIS
+#      on MAC:         add -DMAC
+#      on HP-UX:       add -Aa
+#                      and add $(CFLAGS) to the spin.o line: $(CC) $(CFLAGS) -c y.tab.c
+#      on __FreeBSD__: omit -D_POSIX_SOURCE
+#      also recognized: __FreeBSD__ and __OpenBSD__ and __NetBSD__
+
+YACC=yacc              # on Solaris: /usr/ccs/bin/yacc
+YFLAGS=-v -d           # creates y.output and y.tab.h
+
+SPIN_OS= spin.o spinlex.o sym.o vars.o main.o ps_msc.o \
+       mesg.o flow.o sched.o run.o pangen1.o pangen2.o \
+       pangen3.o pangen4.o pangen5.o guided.o dstep.o \
+       structs.o pc_zpp.o pangen6.o reprosrc.o
+
+TL_OS= tl_parse.o tl_lex.o tl_main.o tl_trans.o tl_buchi.o \
+       tl_mem.o tl_rewrt.o tl_cache.o
+
+spin:  $(SPIN_OS) $(TL_OS)
+       $(CC) $(CFLAGS) -o spin $(SPIN_OS) $(TL_OS)
+
+spin.o:        spin.y
+       $(YACC) $(YFLAGS) spin.y
+       $(CC) -c y?tab.c
+       rm -f y?tab.c
+       mv y?tab.o spin.o
+
+$(SPIN_OS): spin.h
+
+$(TL_OS): tl.h
+
+main.o pangen2.o ps_msc.o: version.h
+pangen1.o: pangen1.h pangen3.h pangen6.h
+pangen2.o: pangen2.h pangen4.h pangen5.h
+
+# http://spinroot.com/uno/
+# using uno version 2.13 -- Oct 2007
+
+uno:   spin.o
+       uno_local -picky dstep.c flow.c guided.c main.c mesg.c pangen3.c pangen4.c pangen5.c pangen6.c pc_zpp.c ps_msc.c reprosrc.c run.c sched.c spinlex.c structs.c sym.c tl_buchi.c tl_cache.c tl_lex.c tl_main.c tl_mem.c tl_parse.c tl_rewrt.c tl_trans.c vars.c
+       uno_local -picky pangen1.c      # large includes, handle separately for now
+       uno_local -picky pangen2.c 
+       rm -f spin.o y?tab.? *.uno y.output y.debug
+
+clean:
+       rm -f spin *.o y?tab.[ch] y.output y.debug
+       rm -f pan.[chmotb] a.out core *stackdump
+
+coverity:
+       cov-build --dir covty make
+       cov-translate --dir covty gcc -c *.c
+       cov-analyze --dir covty
+       cov-format-errors --dir covty -x -X
+       echo ./covty/output/errors/index.html
diff --git a/trunk/verif/Spin/Src5.1.6/mesg.c b/trunk/verif/Spin/Src5.1.6/mesg.c
new file mode 100755 (executable)
index 0000000..f89338f
--- /dev/null
@@ -0,0 +1,650 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+#ifndef MAXQ
+#define MAXQ   2500            /* default max # queues  */
+#endif
+
+extern RunList *X;
+extern Symbol  *Fname;
+extern Lextok  *Mtype;
+extern int     verbose, TstOnly, s_trail, analyze, columns;
+extern int     lineno, depth, xspin, m_loss, jumpsteps;
+extern int     nproc, nstop;
+extern short   Have_claim;
+
+Queue  *qtab = (Queue *) 0;    /* linked list of queues */
+Queue  *ltab[MAXQ];            /* linear list of queues */
+int    nqs = 0, firstrow = 1;
+char   Buf[4096];
+
+static Lextok  *n_rem = (Lextok *) 0;
+static Queue   *q_rem = (Queue  *) 0;
+
+static int     a_rcv(Queue *, Lextok *, int);
+static int     a_snd(Queue *, Lextok *);
+static int     sa_snd(Queue *, Lextok *);
+static int     s_snd(Queue *, Lextok *);
+extern void    sr_buf(int, int);
+extern void    sr_mesg(FILE *, int, int);
+extern void    putarrow(int, int);
+static void    sr_talk(Lextok *, int, char *, char *, int, Queue *);
+
+int
+cnt_mpars(Lextok *n)
+{      Lextok *m;
+       int i=0;
+
+       for (m = n; m; m = m->rgt)
+               i += Cnt_flds(m);
+       return i;
+}
+
+int
+qmake(Symbol *s)
+{      Lextok *m;
+       Queue *q;
+       int i;
+
+       if (!s->ini)
+               return 0;
+
+       if (nqs >= MAXQ)
+       {       lineno = s->ini->ln;
+               Fname  = s->ini->fn;
+               fatal("too many queues (%s)", s->name);
+       }
+       if (analyze && nqs >= 255)
+       {       fatal("too many channel types", (char *)0);
+       }
+
+       if (s->ini->ntyp != CHAN)
+               return eval(s->ini);
+
+       q = (Queue *) emalloc(sizeof(Queue));
+       q->qid    = ++nqs;
+       q->nslots = s->ini->val;
+       q->nflds  = cnt_mpars(s->ini->rgt);
+       q->setat  = depth;
+
+       i = max(1, q->nslots);  /* 0-slot qs get 1 slot minimum */
+
+       q->contents  = (int *) emalloc(q->nflds*i*sizeof(int));
+       q->fld_width = (int *) emalloc(q->nflds*sizeof(int));
+       q->stepnr = (int *)   emalloc(i*sizeof(int));
+
+       for (m = s->ini->rgt, i = 0; m; m = m->rgt)
+       {       if (m->sym && m->ntyp == STRUCT)
+                       i = Width_set(q->fld_width, i, getuname(m->sym));
+               else
+                       q->fld_width[i++] = m->ntyp;
+       }
+       q->nxt = qtab;
+       qtab = q;
+       ltab[q->qid-1] = q;
+
+       return q->qid;
+}
+
+int
+qfull(Lextok *n)
+{      int whichq = eval(n->lft)-1;
+
+       if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
+               return (ltab[whichq]->qlen >= ltab[whichq]->nslots);
+       return 0;
+}
+
+int
+qlen(Lextok *n)
+{      int whichq = eval(n->lft)-1;
+
+       if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
+               return ltab[whichq]->qlen;
+       return 0;
+}
+
+int
+q_is_sync(Lextok *n)
+{      int whichq = eval(n->lft)-1;
+
+       if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
+               return (ltab[whichq]->nslots == 0);
+       return 0;
+}
+
+int
+qsend(Lextok *n)
+{      int whichq = eval(n->lft)-1;
+
+       if (whichq == -1)
+       {       printf("Error: sending to an uninitialized chan\n");
+               whichq = 0;
+               return 0;
+       }
+       if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
+       {       ltab[whichq]->setat = depth;
+               if (ltab[whichq]->nslots > 0)
+                       return a_snd(ltab[whichq], n);
+               else
+                       return s_snd(ltab[whichq], n);
+       }
+       return 0;
+}
+
+int
+qrecv(Lextok *n, int full)
+{      int whichq = eval(n->lft)-1;
+
+       if (whichq == -1)
+       {       if (n->sym && !strcmp(n->sym->name, "STDIN"))
+               {       Lextok *m;
+
+                       if (TstOnly) return 1;
+
+                       for (m = n->rgt; m; m = m->rgt)
+                       if (m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
+                       {       int c = getchar();
+                               (void) setval(m->lft, c);
+                       } else
+                               fatal("invalid use of STDIN", (char *)0);
+
+                       whichq = 0;
+                       return 1;
+               }
+               printf("Error: receiving from an uninitialized chan %s\n",
+                       n->sym?n->sym->name:"");
+               whichq = 0;
+               return 0;
+       }
+       if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
+       {       ltab[whichq]->setat = depth;
+               return a_rcv(ltab[whichq], n, full);
+       }
+       return 0;
+}
+
+static int
+sa_snd(Queue *q, Lextok *n)    /* sorted asynchronous */
+{      Lextok *m;
+       int i, j, k;
+       int New, Old;
+
+       for (i = 0; i < q->qlen; i++)
+       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 */
+               goto found;     /* New < Old */
+       }
+found:
+       for (j = q->qlen-1; j >= i; j--)
+       for (k = 0; k < q->nflds; k++)
+       {       q->contents[(j+1)*q->nflds+k] =
+                       q->contents[j*q->nflds+k];      /* shift up */
+               if (k == 0)
+                       q->stepnr[j+1] = q->stepnr[j];
+       }
+       return i*q->nflds;                              /* new q offset */
+}
+
+void
+typ_ck(int ft, int at, char *s)
+{
+       if ((verbose&32) && ft != at
+       && (ft == CHAN || at == CHAN))
+       {       char buf[128], tag1[64], tag2[64];
+               (void) sputtype(tag1, ft);
+               (void) sputtype(tag2, at);
+               sprintf(buf, "type-clash in %s, (%s<-> %s)", s, tag1, tag2);
+               non_fatal("%s", buf);
+       }
+}
+
+static int
+a_snd(Queue *q, Lextok *n)
+{      Lextok *m;
+       int i = q->qlen*q->nflds;       /* q offset */
+       int j = 0;                      /* q field# */
+
+       if (q->nslots > 0 && q->qlen >= q->nslots)
+               return m_loss;  /* q is full */
+
+       if (TstOnly) return 1;
+
+       if (n->val) i = sa_snd(q, n);   /* sorted insert */
+
+       q->stepnr[i/q->nflds] = depth;
+
+       for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
+       {       int New = eval(m->lft);
+               q->contents[i+j] = cast_val(q->fld_width[j], New, 0);
+               if ((verbose&16) && depth >= jumpsteps)
+                       sr_talk(n, New, "Send ", "->", j, q);
+               typ_ck(q->fld_width[j], Sym_typ(m->lft), "send");
+       }
+       if ((verbose&16) && depth >= jumpsteps)
+       {       for (i = j; i < q->nflds; i++)
+                       sr_talk(n, 0, "Send ", "->", i, q);
+               if (j < q->nflds)
+                       printf("%3d: warning: missing params in send\n",
+                               depth);
+               if (m)
+                       printf("%3d: warning: too many params in send\n",
+                               depth);
+       }
+       q->qlen++;
+       return 1;
+}
+
+static int
+a_rcv(Queue *q, Lextok *n, int full)
+{      Lextok *m;
+       int i=0, oi, j, k;
+       extern int Rvous;
+
+       if (q->qlen == 0)
+               return 0;       /* q is empty */
+try_slot:
+       /* test executability */
+       for (m = n->rgt, j=0; m && j < q->nflds; m = m->rgt, j++)
+               if ((m->lft->ntyp == CONST
+                  && q->contents[i*q->nflds+j] != m->lft->val)
+               ||  (m->lft->ntyp == EVAL
+                  && q->contents[i*q->nflds+j] != eval(m->lft->lft)))
+               {       if (n->val == 0         /* fifo recv */
+                       ||  n->val == 2         /* fifo poll */
+                       || ++i >= q->qlen)      /* last slot */
+                               return 0;       /* no match  */
+                       goto try_slot;
+               }
+       if (TstOnly) return 1;
+
+       if (verbose&8)
+       {       if (j < q->nflds)
+                       printf("%3d: warning: missing params in next recv\n",
+                               depth);
+               else if (m)
+                       printf("%3d: warning: too many params in next recv\n",
+                               depth);
+       }
+
+       /* set the fields */
+       if (Rvous)
+       {       n_rem = n;
+               q_rem = q;
+       }
+
+       oi = q->stepnr[i];
+       for (m = n->rgt, j = 0; m && j < q->nflds; m = m->rgt, j++)
+       {       if (columns && !full)   /* was columns == 1 */
+                       continue;
+               if ((verbose&8) && !Rvous && depth >= jumpsteps)
+               {       sr_talk(n, q->contents[i*q->nflds+j],
+                       (full && n->val < 2)?"Recv ":"[Recv] ", "<-", j, q);
+               }
+               if (!full)
+                       continue;       /* test */
+               if (m && m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
+               {       (void) setval(m->lft, q->contents[i*q->nflds+j]);
+                       typ_ck(q->fld_width[j], Sym_typ(m->lft), "recv");
+               }
+               if (n->val < 2)         /* not a poll */
+               for (k = i; k < q->qlen-1; k++)
+               {       q->contents[k*q->nflds+j] =
+                         q->contents[(k+1)*q->nflds+j];
+                       if (j == 0)
+                         q->stepnr[k] = q->stepnr[k+1];
+               }
+       }
+
+       if ((!columns || full)
+       && (verbose&8) && !Rvous && depth >= jumpsteps)
+       for (i = j; i < q->nflds; i++)
+       {       sr_talk(n, 0,
+               (full && n->val < 2)?"Recv ":"[Recv] ", "<-", i, q);
+       }
+       if (columns == 2 && full && !Rvous && depth >= jumpsteps)
+               putarrow(oi, depth);
+
+       if (full && n->val < 2)
+               q->qlen--;
+       return 1;
+}
+
+static int
+s_snd(Queue *q, Lextok *n)
+{      Lextok *m;
+       RunList *rX, *sX = X;   /* rX=recvr, sX=sendr */
+       int i, j = 0;   /* q field# */
+
+       for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
+       {       q->contents[j] = cast_val(q->fld_width[j], eval(m->lft), 0);
+               typ_ck(q->fld_width[j], Sym_typ(m->lft), "rv-send");
+       }
+       q->qlen = 1;
+       if (!complete_rendez())
+       {       q->qlen = 0;
+               return 0;
+       }
+       if (TstOnly)
+       {       q->qlen = 0;
+               return 1;
+       }
+       q->stepnr[0] = depth;
+       if ((verbose&16) && depth >= jumpsteps)
+       {       m = n->rgt;
+               rX = X; X = sX;
+               for (j = 0; m && j < q->nflds; m = m->rgt, j++)
+                       sr_talk(n, eval(m->lft), "Sent ", "->", j, q);
+               for (i = j; i < q->nflds; i++)
+                       sr_talk(n, 0, "Sent ", "->", i, q);
+               if (j < q->nflds)
+                         printf("%3d: warning: missing params in rv-send\n",
+                               depth);
+               else if (m)
+                         printf("%3d: warning: too many params in rv-send\n",
+                               depth);
+               X = rX; /* restore receiver's context */
+               if (!s_trail)
+               {       if (!n_rem || !q_rem)
+                               fatal("cannot happen, s_snd", (char *) 0);
+                       m = n_rem->rgt;
+                       for (j = 0; m && j < q->nflds; m = m->rgt, j++)
+                       {       if (m->lft->ntyp != NAME
+                               ||  strcmp(m->lft->sym->name, "_") != 0)
+                                       i = eval(m->lft);
+                               else    i = 0;
+
+                               if (verbose&8)
+                               sr_talk(n_rem,i,"Recv ","<-",j,q_rem);
+                       }
+                       if (verbose&8)
+                       for (i = j; i < q->nflds; i++)
+                               sr_talk(n_rem, 0, "Recv ", "<-", j, q_rem);
+                       if (columns == 2)
+                               putarrow(depth, depth);
+               }
+               n_rem = (Lextok *) 0;
+               q_rem = (Queue *) 0;
+       }
+       return 1;
+}
+
+static void
+channm(Lextok *n)
+{      char lbuf[512];
+
+       if (n->sym->type == CHAN)
+               strcat(Buf, n->sym->name);
+       else if (n->sym->type == NAME)
+               strcat(Buf, lookup(n->sym->name)->name);
+       else if (n->sym->type == STRUCT)
+       {       Symbol *r = n->sym;
+               if (r->context)
+               {       r = findloc(r);
+                       if (!r)
+                       {       strcat(Buf, "*?*");
+                               return;
+               }       }
+               ini_struct(r);
+               printf("%s", r->name);
+               strcpy(lbuf, "");
+               struct_name(n->lft, r, 1, lbuf);
+               strcat(Buf, lbuf);
+       } else
+               strcat(Buf, "-");
+       if (n->lft->lft)
+       {       sprintf(lbuf, "[%d]", eval(n->lft->lft));
+               strcat(Buf, lbuf);
+       }
+}
+
+static void
+difcolumns(Lextok *n, char *tr, int v, int j, Queue *q)
+{      extern int pno;
+
+       if (j == 0)
+       {       Buf[0] = '\0';
+               channm(n);
+               strcat(Buf, (strncmp(tr, "Sen", 3))?"?":"!");
+       } else
+               strcat(Buf, ",");
+       if (tr[0] == '[') strcat(Buf, "[");
+       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 (tr[0] == '[') strcat(Buf, "]");
+               pstext(cnr, Buf);
+       }
+}
+
+static void
+docolumns(Lextok *n, char *tr, int v, int j, Queue *q)
+{      int i;
+
+       if (firstrow)
+       {       printf("q\\p");
+               for (i = 0; i < nproc-nstop - Have_claim; i++)
+                       printf(" %3d", i);
+               printf("\n");
+               firstrow = 0;
+       }
+       if (j == 0)
+       {       printf("%3d", q->qid);
+               if (X)
+               for (i = 0; i < X->pid - Have_claim; i++)
+                       printf("   .");
+               printf("   ");
+               Buf[0] = '\0';
+               channm(n);
+               printf("%s%c", Buf, (strncmp(tr, "Sen", 3))?'?':'!');
+       } else
+               printf(",");
+       if (tr[0] == '[') printf("[");
+       sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
+       if (j == q->nflds - 1)
+       {       if (tr[0] == '[') printf("]");
+               printf("\n");
+       }
+}
+
+typedef struct QH {
+       int     n;
+       struct  QH *nxt;
+} QH;
+static QH *qh;
+
+void
+qhide(int q)
+{      QH *p = (QH *) emalloc(sizeof(QH));
+       p->n = q;
+       p->nxt = qh;
+       qh = p;
+}
+
+int
+qishidden(int q)
+{      QH *p;
+       for (p = qh; p; p = p->nxt)
+               if (p->n == q)
+                       return 1;
+       return 0;
+}
+
+static void
+sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q)
+{      char s[128];
+
+       if (qishidden(eval(n->lft)))
+               return;
+
+       if (columns)
+       {       if (columns == 2)
+                       difcolumns(n, tr, v, j, q);
+               else
+                       docolumns(n, tr, v, j, q);
+               return;
+       }
+       if (xspin)
+       {       if ((verbose&4) && tr[0] != '[')
+               sprintf(s, "(state -)\t[values: %d",
+                       eval(n->lft));
+               else
+               sprintf(s, "(state -)\t[%d", eval(n->lft));
+               if (strncmp(tr, "Sen", 3) == 0)
+                       strcat(s, "!");
+               else
+                       strcat(s, "?");
+       } else
+       {       strcpy(s, tr);
+       }
+
+       if (j == 0)
+       {       whoruns(1);
+               printf("line %3d %s %s",
+                       n->ln, n->fn->name, s);
+       } else
+               printf(",");
+       sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
+
+       if (j == q->nflds - 1)
+       {       if (xspin)
+               {       printf("]\n");
+                       if (!(verbose&4)) printf("\n");
+                       return;
+               }
+               printf("\t%s queue %d (", a, eval(n->lft));
+               Buf[0] = '\0';
+               channm(n);
+               printf("%s)\n", Buf);
+       }
+       fflush(stdout);
+}
+
+void
+sr_buf(int v, int j)
+{      int cnt = 1; Lextok *n;
+       char lbuf[512];
+
+       for (n = Mtype; n && j; n = n->rgt, cnt++)
+               if (cnt == v)
+               {       if(strlen(n->lft->sym->name) >= sizeof(lbuf))
+                       {       non_fatal("mtype name %s too long", n->lft->sym->name);
+                               break;
+                       }
+                       sprintf(lbuf, "%s", n->lft->sym->name);
+                       strcat(Buf, lbuf);
+                       return;
+               }
+       sprintf(lbuf, "%d", v);
+       strcat(Buf, lbuf);
+}
+
+void
+sr_mesg(FILE *fd, int v, int j)
+{      Buf[0] ='\0';
+       sr_buf(v, j);
+       fprintf(fd, Buf);
+}
+
+void
+doq(Symbol *s, int n, RunList *r)
+{      Queue *q;
+       int j, k;
+
+       if (!s->val)    /* uninitialized queue */
+               return;
+       for (q = qtab; q; q = q->nxt)
+       if (q->qid == s->val[n])
+       {       if (xspin > 0
+               && (verbose&4)
+               && q->setat < depth)
+                       continue;
+               if (q->nslots == 0)
+                       continue; /* rv q always empty */
+               printf("\t\tqueue %d (", q->qid);
+               if (r)
+               printf("%s(%d):", r->n->name, r->pid - Have_claim);
+               if (s->nel != 1)
+                 printf("%s[%d]): ", s->name, n);
+               else
+                 printf("%s): ", s->name);
+               for (k = 0; k < q->qlen; k++)
+               {       printf("[");
+                       for (j = 0; j < q->nflds; j++)
+                       {       if (j > 0) printf(",");
+                               sr_mesg(stdout, q->contents[k*q->nflds+j],
+                                       q->fld_width[j] == MTYPE);
+                       }
+                       printf("]");
+               }
+               printf("\n");
+               break;
+       }
+}
+
+void
+nochan_manip(Lextok *p, Lextok *n, int d)
+{      int e = 1;
+
+       if (d == 0 && p->sym && p->sym->type == CHAN)
+       {       setaccess(p->sym, ZS, 0, 'L');
+
+               if (n && n->ntyp == CONST)
+                       fatal("invalid asgn to chan", (char *) 0);
+
+               if (n && n->sym && n->sym->type == CHAN)
+               {       setaccess(n->sym, ZS, 0, 'V');
+                       return;
+               }       
+       }
+
+       if (!n || n->ntyp == LEN || n->ntyp == RUN)
+               return;
+
+       if (n->sym && n->sym->type == CHAN)
+       {       if (d == 1)
+                       fatal("invalid use of chan name", (char *) 0);
+               else
+                       setaccess(n->sym, ZS, 0, 'V');  
+       }
+
+       if (n->ntyp == NAME
+       ||  n->ntyp == '.')
+               e = 0;  /* array index or struct element */
+
+       nochan_manip(p, n->lft, e);
+       nochan_manip(p, n->rgt, 1);
+}
+
+void
+no_internals(Lextok *n)
+{      char *sp;
+
+       if (!n->sym
+       ||  !n->sym->name)
+               return;
+
+       sp = n->sym->name;
+
+       if ((strlen(sp) == strlen("_nr_pr") && strcmp(sp, "_nr_pr") == 0)
+       ||  (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0))
+       {       fatal("attempt to assign value to system variable %s", sp);
+       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/pangen1.c b/trunk/verif/Spin/Src5.1.6/pangen1.c
new file mode 100755 (executable)
index 0000000..36694d8
--- /dev/null
@@ -0,0 +1,1298 @@
+/***** 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            */
+/* (c) 2007: small additions for V5.0 to support multi-core verifications */
+
+#include "spin.h"
+#include "y.tab.h"
+#include "pangen1.h"
+#include "pangen3.h"
+#include "pangen6.h"
+
+extern FILE    *tc, *th, *tt;
+extern Label   *labtab;
+extern Ordered *all_names;
+extern ProcList        *rdy;
+extern Queue   *qtab;
+extern Symbol  *Fname;
+extern int     lineno, verbose, Pid, separate;
+extern int     nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
+extern short   has_sorted, has_random, has_provided;
+extern Queue   *ltab[];
+
+int    Npars=0, u_sync=0, u_async=0, hastrack = 1;
+short  has_io = 0;
+short  has_state=0;    /* code contains c_state */
+
+static Symbol  *LstSet=ZS;
+static int     acceptors=0, progressors=0, nBits=0;
+static int     Types[] = { UNSIGNED, BIT, BYTE, CHAN, MTYPE, SHORT, INT, STRUCT };
+
+static int     doglobal(char *, int);
+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    tc_predef_np(void);
+static void    put_pinit(ProcList *);
+       void    walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *);
+
+static void
+reverse_names(ProcList *p)
+{
+       if (!p) return;
+       reverse_names(p->nxt);
+       fprintf(th, "   \"%s\",\n", p->n->name);
+}
+
+void
+genheader(void)
+{      ProcList *p; int i;
+
+       if (separate == 2)
+       {       putunames(th);
+               goto here;
+       }
+
+       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");
+
+       putunames(th);
+
+       fprintf(tc, "short 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_ */
+       fprintf(tc, " };\n");
+
+       fprintf(th, "char *procname[] = {\n");
+               reverse_names(rdy);
+       fprintf(th, "   \":np_:\",\n");
+       fprintf(th, "};\n\n");
+
+here:
+       for (p = rdy; p; p = p->nxt)
+               put_ptype(p->n->name, p->tn, mst, nrRdy+1);
+               /* +1 for np_ */
+       put_ptype("np_", nrRdy, mst, nrRdy+1);
+
+       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);
+       }
+       ntimes(th, 0, 1, Head1);
+
+       LstSet = ZS;
+       (void) doglobal("", PUTV);
+
+       hastrack = c_add_sv(th);
+
+       fprintf(th, "   uchar sv[VECTORSZ];\n");
+       fprintf(th, "} State");
+#ifdef SOLARIS
+       fprintf(th,"\n#ifdef GCC\n");
+       fprintf(th, "\t__attribute__ ((aligned(8)))");
+       fprintf(th, "\n#endif\n\t");
+#endif
+       fprintf(th, ";\n\n");
+
+       fprintf(th, "#define HAS_TRACK  %d\n", hastrack);
+
+       if (separate != 2)
+               dohidden();
+}
+
+void
+genaddproc(void)
+{      ProcList *p;
+       int i = 0;
+
+       if (separate ==2) goto shortcut;
+
+       fprintf(tc, "int\naddproc(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_ */
+       ntimes(tc, 0, 1, Addp1);
+
+       if (has_provided)
+       {       fprintf(tt, "\nint\nprovided(int II, unsigned char ot, ");
+               fprintf(tt, "int tt, Trans *t)\n");
+               fprintf(tt, "{\n\tswitch(ot) {\n");
+       }
+shortcut:
+       tc_predef_np();
+       for (p = rdy; p; p = p->nxt)
+       {       Pid = p->tn;
+               put_pinit(p);
+       }
+       if (separate == 2) return;
+
+       Pid = 0;
+       if (has_provided)
+       {       fprintf(tt, "\tdefault: return 1; /* e.g., a claim */\n");
+               fprintf(tt, "\t}\n\treturn 0;\n}\n");
+       }
+
+       ntimes(tc, i, i+1, R6);
+       if (separate == 0)
+               ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
+       else
+               ntimes(tc, 1, nrRdy, R5);
+       ntimes(tc, 0, 1, R8a);
+}
+
+void
+do_locinits(FILE *fd)
+{      ProcList *p;
+
+       for (p = rdy; p; p = p->nxt)
+               c_add_locinit(fd, p->tn, p->n->name);
+}
+
+void
+genother(void)
+{      ProcList *p;
+
+       switch (separate) {
+       case 2:
+               if (claimnr >= 0)
+               ntimes(tc, claimnr, claimnr+1, R0); /* claim only */
+               break;
+       case 1:
+               ntimes(tc,     0,    1, Code0);
+               ntimes(tc, 0, claimnr, R0);     /* all except claim */
+               ntimes(tc, claimnr+1, nrRdy, R0);
+               break;
+       case 0:
+               ntimes(tc,     0,    1, Code0);
+               ntimes(tc,     0, nrRdy+1, R0); /* +1 for np_ */
+               break;
+       }
+
+       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 */
+               return;
+       case 1:
+               ntimes(tc, 0, claimnr, R0a);    /* all except claim */
+               ntimes(tc, claimnr+1, nrRdy, R0a);
+               fprintf(tc, "   if (state_tables)\n");
+               fprintf(tc, "           ini_claim(%d, 0);\n", claimnr);
+               break;
+       case 0:
+               ntimes(tc, 0, nrRdy, R0a);      /* all */
+               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, Code2d);
+       ntimes(tc, 0,     nrRdy, R4);
+       fprintf(tc, "}\n\n");
+
+       fprintf(tc, "void\n");
+       fprintf(tc, "iniglobals(void)\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");
+}
+
+void
+gensvmap(void)
+{
+       ntimes(tc, 0, 1, SvMap);
+}
+
+static struct {
+       char *s,        *t;             int n,  m,      p;
+} ln[] = {
+       {"end",         "stopstate",    3,      0,      0},
+       {"progress",    "progstate",    8,      0,      1},
+       {"accept",      "accpstate",    6,      1,      0},
+       {0,             0,              0,      0,      0},
+};
+
+static void
+end_labs(Symbol *s, int i)
+{      int oln = lineno;
+       Symbol *ofn = Fname;
+       Label *l;
+       int j; char foo[128];
+
+       if ((i == claimnr && separate == 1)
+       ||  (i != claimnr && 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
+               &&  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;
+                       progressors += ln[j].p;
+                       if (l->e->status & D_ATOM)
+                       {       sprintf(foo, "%s label inside d_step",
+                                       ln[j].s);
+                               goto complain;
+                       }
+                       if (j > 0 && (l->e->status & ATOM))
+                       {       sprintf(foo, "%s label inside atomic",
+                                       ln[j].s);
+               complain:       lineno = l->e->n->ln;
+                               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
+               &&  strcmp(l->s->context->name, s->name) == 0)
+               fprintf(tc, "\tvisstate[%d][%d] = 1;\n",
+                               i, l->e->seqno);
+
+       lineno = oln;
+       Fname  = ofn;
+}
+
+void
+ntimes(FILE *fd, int n, int m, char *c[])
+{
+       int i, j;
+       for (j = 0; c[j]; j++)
+       for (i = n; i < m; i++)
+       {       fprintf(fd, c[j], i, i, i, i, i, i);
+               fprintf(fd, "\n");
+       }
+}
+
+void
+prehint(Symbol *s)
+{      Lextok *n;
+
+       printf("spin: warning, ");
+       if (!s) return;
+
+       n = (s->context != ZS)?s->context->ini:s->ini;
+       if (n)
+       printf("line %3d %s, ", n->ln, n->fn->name);
+}
+
+void
+checktype(Symbol *sp, char *s)
+{      char buf[128]; int i;
+
+       if (!s
+       || (sp->type != BYTE
+       &&  sp->type != SHORT
+       &&  sp->type != INT))
+               return;
+
+       if (sp->hidden&16)      /* formal parameter */
+       {       ProcList *p; Lextok *f, *t;
+               int posnr = 0;
+               for (p = rdy; p; p = p->nxt)
+                       if (p->n->name
+                       &&  strcmp(s, p->n->name) == 0)
+                               break;
+               if (p)
+               for (f = p->p; f; f = f->rgt) /* list of types */
+               for (t = f->lft; t; t = t->rgt, posnr++)
+                       if (t->sym
+                       &&  strcmp(t->sym->name, sp->name) == 0)
+                       {       checkrun(sp, posnr);
+                               return;
+                       }
+
+       } else if (!(sp->hidden&4))
+       {       if (!(verbose&32)) return;
+               sputtype(buf, sp->type);
+               i = (int) strlen(buf);
+               while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
+               prehint(sp);
+               if (sp->context)
+                       printf("proctype %s:", s);
+               else
+                       printf("global");
+               printf(" '%s %s' could be declared 'bit %s'\n",
+                       buf, sp->name, sp->name);
+       } else if (sp->type != BYTE && !(sp->hidden&8))
+       {       if (!(verbose&32)) return;
+               sputtype(buf, sp->type);
+               i = (int) strlen(buf);
+               while (buf[--i] == ' ') buf[i] = '\0';
+               prehint(sp);
+               if (sp->context)
+                       printf("proctype %s:", s);
+               else
+                       printf("global");
+               printf(" '%s %s' could be declared 'byte %s'\n",
+                       buf, sp->name, sp->name);
+       }
+}
+
+int
+dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s)
+{      int h, j, k=0; extern int nr_errs;
+       Ordered *walk;
+       Symbol *sp;
+       char buf[64], buf2[128], buf3[128];
+
+       if (dowhat == INIV)
+       {       /* initialize in order of declaration */
+               for (walk = all_names; walk; walk = walk->next)
+               {       sp = walk->entry;
+                       if (sp->context
+                       && !sp->owner
+                       &&  strcmp(s, sp->context->name) == 0)
+                       {       checktype(sp, s); /* fall through */
+                               if (!(sp->hidden&16))
+                               {       sprintf(buf, "((P%d *)pptr(h))->", p);
+                                       do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
+                               }
+                               k++;
+               }       }
+       } else
+       {       for (j = 0; j < 8; j++)
+               for (h = 0; h <= 1; h++)
+               for (walk = all_names; walk; walk = walk->next)
+               {       sp = walk->entry;
+                       if (sp->context
+                       && !sp->owner
+                       &&  sp->type == Types[j]
+                       &&  ((h == 0 && sp->nel == 1) || (h == 1 && sp->nel > 1))
+                       &&  strcmp(s, sp->context->name) == 0)
+                       {       switch (dowhat) {
+                               case LOGV:
+                                       if (sp->type == CHAN
+                                       &&  verbose == 0)
+                                               break;
+                                       sprintf(buf, "%s%s:", pre, s);
+                                       { sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
+                                         sprintf(buf3, ");\n");
+                                       }
+                                       do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
+                                       break;
+                               case PUTV:
+                                       sprintf(buf, "((P%d *)pptr(h))->", p);
+                                       do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
+                                       k++;
+                                       break;
+                               }
+                               if (strcmp(s, ":never:") == 0)
+                               {       printf("error: %s defines local %s\n",
+                                               s, sp->name);
+                                       nr_errs++;
+       }       }       }       }
+
+       return k;
+}
+
+void
+c_chandump(FILE *fd)
+{      Queue *q;
+       char buf[256];
+       int i;
+
+       if (!qtab)
+       {       fprintf(fd, "void\nc_chandump(int unused) ");
+               fprintf(fd, "{ unused++; /* avoid complaints */ }\n");
+               return;
+       }
+
+       fprintf(fd, "void\nc_chandump(int from)\n");
+       fprintf(fd, "{  uchar *z; int slot;\n");
+
+       fprintf(fd, "   from--;\n");
+       fprintf(fd, "   if (from >= (int) now._nr_qs || from < 0)\n");
+       fprintf(fd, "   {       printf(\"pan: bad qid %%d\\n\", from+1);\n");
+       fprintf(fd, "           return;\n");
+       fprintf(fd, "   }\n");
+       fprintf(fd, "   z = qptr(from);\n");
+       fprintf(fd, "   switch (((Q0 *)z)->_t) {\n");
+
+       for (q = qtab; q; q = q->nxt)
+       {       fprintf(fd, "   case %d:\n\t\t", q->qid);
+               sprintf(buf, "((Q%d *)z)->", q->qid);
+
+               fprintf(fd, "for (slot = 0; slot < %sQlen; slot++)\n\t\t", buf);
+               fprintf(fd, "{  printf(\" [\");\n\t\t");
+               for (i = 0; i < q->nflds; i++)
+               {       if (q->fld_width[i] == MTYPE)
+                       {       fprintf(fd, "\tprintm(%scontents[slot].fld%d);\n\t\t",
+                               buf, i);
+                       } else
+                       fprintf(fd, "\tprintf(\"%%d,\", %scontents[slot].fld%d);\n\t\t",
+                               buf, i);
+               }
+               fprintf(fd, "   printf(\"],\");\n\t\t");
+               fprintf(fd, "}\n\t\t");
+               fprintf(fd, "break;\n");
+       }
+       fprintf(fd, "   }\n");
+       fprintf(fd, "   printf(\"\\n\");\n}\n");
+}
+
+void
+c_var(FILE *fd, char *pref, Symbol *sp)
+{      char buf[256];
+       int i;
+
+       switch (sp->type) {
+       case STRUCT:
+               /* c_struct(fd, pref, sp); */
+               fprintf(fd, "\t\tprintf(\"\t(struct %s)\\n\");\n",
+                       sp->name);
+               sprintf(buf, "%s%s.", pref, sp->name);
+               c_struct(fd, buf, sp);
+               break;
+       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);
+               } 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);
+                       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);
+                  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);
+               } else
+               for (i = 0; i < sp->nel; i++)
+               {  fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
+                       sp->name, 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",
+                       pref, sp->name, i);
+               }
+               break;
+       }
+}
+
+int
+c_splurge_any(ProcList *p)
+{      Ordered *walk;
+       Symbol *sp;
+
+       if (strcmp(p->n->name, ":never:") != 0
+       &&  strcmp(p->n->name, ":trace:") != 0
+       &&  strcmp(p->n->name, ":notrace:") != 0)
+       for (walk = all_names; walk; walk = walk->next)
+       {       sp = walk->entry;
+               if (!sp->context
+               ||  sp->type == 0
+               ||  strcmp(sp->context->name, p->n->name) != 0
+               ||  sp->owner || (sp->hidden&1)
+               || (sp->type == MTYPE && ismtype(sp->name)))
+                       continue;
+
+               return 1;
+       }
+       return 0;
+}
+
+void
+c_splurge(FILE *fd, ProcList *p)
+{      Ordered *walk;
+       Symbol *sp;
+       char pref[64];
+
+       if (strcmp(p->n->name, ":never:") != 0
+       &&  strcmp(p->n->name, ":trace:") != 0
+       &&  strcmp(p->n->name, ":notrace:") != 0)
+       for (walk = all_names; walk; walk = walk->next)
+       {       sp = walk->entry;
+               if (!sp->context
+               ||  sp->type == 0
+               ||  strcmp(sp->context->name, p->n->name) != 0
+               ||  sp->owner || (sp->hidden&1)
+               || (sp->type == MTYPE && ismtype(sp->name)))
+                       continue;
+
+               sprintf(pref, "((P%d *)pptr(pid))->", p->tn);
+               c_var(fd, pref, sp);
+       }
+}
+
+void
+c_wrapper(FILE *fd)    /* allow pan.c to print out global sv entries */
+{      Ordered *walk;
+       ProcList *p;
+       Symbol *sp;
+       Lextok *n;
+       extern Lextok *Mtype;
+       int j;
+
+       fprintf(fd, "void\nc_globals(void)\n{\t/* int i; */\n");
+       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)))
+                       continue;
+
+               c_var(fd, "now.", sp);
+       }
+       fprintf(fd, "}\n");
+
+       fprintf(fd, "void\nc_locals(int pid, int tp)\n{\t/* int i; */\n");
+       fprintf(fd, "   switch(tp) {\n");
+       for (p = rdy; p; p = p->nxt)
+       {       fprintf(fd, "   case %d:\n", p->tn);
+               if (c_splurge_any(p))
+               {       fprintf(fd, "   \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
+                               p->n->name);
+                       c_splurge(fd, p);
+               } else
+               {       fprintf(fd, "   \t/* none */\n");
+               }
+               fprintf(fd, "   \tbreak;\n");
+       }
+       fprintf(fd, "   }\n}\n");
+
+       fprintf(fd, "void\nprintm(int x)\n{\n");
+       fprintf(fd, "   switch (x) {\n");
+        for (n = Mtype, j = 1; n && j; n = n->rgt, j++)
+                fprintf(fd, "\tcase %d: Printf(\"%s\"); break;\n",
+                       j, n->lft->sym->name);
+       fprintf(fd, "   default: Printf(\"%%d\", x);\n");
+       fprintf(fd, "   }\n");
+       fprintf(fd, "}\n");
+}
+
+static int
+doglobal(char *pre, int dowhat)
+{      Ordered *walk;
+       Symbol *sp;
+       int j, cnt = 0;
+
+       for (j = 0; j < 8; j++)
+       for (walk = all_names; walk; walk = walk->next)
+       {       sp = walk->entry;
+               if (!sp->context
+               &&  !sp->owner
+               &&  sp->type == Types[j])
+               {       if (Types[j] != MTYPE || !ismtype(sp->name))
+                       switch (dowhat) {
+                       case LOGV:
+                               if (sp->type == CHAN
+                               &&  verbose == 0)
+                                       break;
+                               if (sp->hidden&1)
+                                       break;
+                               do_var(tc, dowhat, "", sp,
+                                       pre, "\", now.", ");\n");
+                               break;
+                       case INIV:
+                               checktype(sp, (char *) 0);
+                               cnt++; /* fall through */
+                       case PUTV:
+                               do_var(tc, dowhat, (sp->hidden&1)?"":"now.", sp,
+                               "", " = ", ";\n");
+                               break;
+       }       }       }
+       return cnt;
+}
+
+static void
+dohidden(void)
+{      Ordered *walk;
+       Symbol *sp;
+       int j;
+
+       for (j = 0; j < 8; j++)
+       for (walk = all_names; walk; walk = walk->next)
+       {       sp = walk->entry;
+               if ((sp->hidden&1)
+               &&  sp->type == Types[j])
+               {       if (sp->context || sp->owner)
+                       fatal("cannot hide non-globals (%s)", sp->name);
+                       if (sp->type == CHAN)
+                       fatal("cannot hide channels (%s)", sp->name);
+                       fprintf(th, "/* hidden variable: */");
+                       typ2c(sp);
+       }       }
+       fprintf(th, "int _; /* a predefined write-only variable */\n\n");
+}
+
+void
+do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
+       char *pre, char *sep, char *ter)
+{      int i;
+
+       switch(dowhat) {
+       case PUTV:
+
+               if (sp->hidden&1) break;
+
+               typ2c(sp);
+               break;
+       case LOGV:
+       case INIV:
+               if (sp->type == STRUCT)
+               {       /* struct may contain a chan */
+                       walk_struct(ofd, dowhat, s, sp, pre, sep, ter);
+                       break;
+               }
+               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)
+                               fprintf(ofd, "%s%s", s, sp->name);
+                       else
+                               do_init(ofd, sp);
+                       fprintf(ofd, "%s", ter);
+               } else
+               {       if (sp->ini && sp->ini->ntyp == CHAN)
+                       {       for (i = 0; i < sp->nel; i++)
+                               {       fprintf(ofd, "\t\t%s%s%s[%d]%s",
+                                               pre, s, sp->name, i, sep);
+                                       if (dowhat == LOGV)
+                                               fprintf(ofd, "%s%s[%d]",
+                                                       s, sp->name, i);
+                                       else
+                                               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",
+                                               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");
+               }       }
+               break;
+       }
+}
+
+static void
+do_init(FILE *ofd, Symbol *sp)
+{      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);
+       } else
+               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)
+{      int k;
+
+       if (strcmp(s, ":init:") == 0)
+               fprintf(th, "#define Pinit      ((P%d *)this)\n", 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));
+       LstSet = ZS;
+       nBits = 8 + blog(m1) + blog(m0);
+       k = dolocal(tc, "", PUTV, i, s);        /* 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 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);
+                       goto done;
+               }
+               if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
+               ||   LstSet->nel != 1)
+               {       fprintf(th, "Offsetof(P%d, %s) - %d*sizeof(",
+                               i, LstSet->name, LstSet->nel);
+               }
+               switch(LstSet->type) {
+               case UNSIGNED:
+                       fprintf(th, "%d", (nBits+7)/8);
+                       break;
+               case BIT:
+                       if (LstSet->nel == 1)
+                       {       fprintf(th, "%d", (nBits+7)/8);
+                               break;
+                       }       /* else fall through */
+               case MTYPE: case BYTE: case CHAN:
+                       fprintf(th, "uchar)"); break;
+               case SHORT:
+                       fprintf(th, "short)"); break;
+               case INT:
+                       fprintf(th, "int)"); break;
+               default:
+                       fatal("cannot happen Air %s",
+                               LstSet->name);
+               }
+done:          fprintf(th, ")\n");
+       }
+}
+
+static void
+tc_predef_np(void)
+{      int i = 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, "uchar *loopstate%d;  /* np_ */\n", i);
+
+       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);
+       if (separate == 1)
+       {       fprintf(tc, "\t\tini_claim(%d, h);\n", i);
+       } 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\tbreak;\n");
+}
+
+static void
+put_pinit(ProcList *P)
+{      Lextok  *fp, *fpt, *t;
+       Element *e = P->s->frst;
+       Symbol  *s = P->n;
+       Lextok  *p = P->p;
+       int      i = P->tn;
+       int     ini, j, k;
+
+       if (i == claimnr
+       &&  separate == 1)
+       {       fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
+               fprintf(tc, "\t\tini_claim(%d, h);\n", i);
+               fprintf(tc, "\t\tbreak;\n");
+               return;
+       }
+       if (i != claimnr
+       &&  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);
+       if (i == eventmapnr)
+       fprintf(th, "#define start_event        %d\n", ini);
+
+       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);
+
+       if (has_provided)
+       {       fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
+               if (P->prov)
+               {       fprintf(tt, "if (");
+                       putstmnt(tt, P->prov, 0);
+                       fprintf(tt, ")\n\t\t\t");
+               }
+               fprintf(tt, "return 1;\n");
+               if (P->prov)
+                       fprintf(tt, "\t\tbreak;\n");
+       }
+
+       fprintf(tc, "\t\t/* params: */\n");
+       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)
+               {       lineno = t->ln;
+                       Fname  = t->fn;
+                       fatal("array in parameter list, %s",
+                       t->sym->name);
+               }
+               fprintf(tc, "\t\t((P%d *)pptr(h))->", i);
+               if (t->sym->type == STRUCT)
+               {       if (full_name(tc, t, t->sym, 1))
+                       {       lineno = t->ln;
+                               Fname  = t->fn;
+                               fatal("hidden array in parameter %s",
+                               t->sym->name);
+                       }
+               } else
+                       fprintf(tc, "%s", t->sym->name);
+               fprintf(tc, " = par%d;\n", j);
+       }
+       fprintf(tc, "\t\t/* locals: */\n");
+       k = dolocal(tc, "", INIV, i, s->name);
+       if (k > 0)
+       {       fprintf(tc, "#ifdef VAR_RANGES\n");
+               (void) dolocal(tc, "logval(\"", LOGV, i, s->name);
+               fprintf(tc, "#endif\n");
+       }
+
+       fprintf(tc, "#ifdef HAS_CODE\n");
+       fprintf(tc, "\t\tlocinit%d(h);\n", i);
+       fprintf(tc, "#endif\n");
+
+       dumpclaims(tc, i, s->name);
+       fprintf(tc, "\t break;\n");
+}
+
+Element *
+huntstart(Element *f)
+{      Element *e = f;
+       Element *elast = (Element *) 0;
+       int cnt = 0;
+
+       while (elast != e && cnt++ < 200)       /* new 4.0.8 */
+       {       elast = e;
+               if (e->n)
+               {       if (e->n->ntyp == '.' && e->nxt)
+                               e = e->nxt;
+                       else if (e->n->ntyp == UNLESS)
+                               e = e->sub->this->frst;
+       }       }
+
+       if (cnt >= 200 || !e)
+               fatal("confusing control structure", (char *) 0);
+       return e;
+}
+
+Element *
+huntele(Element *f, int o, int stopat)
+{      Element *g, *e = f;
+       int cnt=0; /* a precaution against loops */
+
+       if (e)
+       for ( ; cnt < 200 && e->n; cnt++)
+       {
+               if (e->seqno == stopat)
+                       break;
+
+               switch (e->n->ntyp) {
+               case GOTO:
+                       g = get_lab(e->n,1);
+                       cross_dsteps(e->n, g->n);
+                       break;
+               case '.':
+               case BREAK:
+                       if (!e->nxt)
+                               return e;
+                       g = e->nxt;
+                       break;
+               case UNLESS:
+                       g = huntele(e->sub->this->frst, o, stopat);
+                       break;
+               case D_STEP:
+               case ATOMIC:
+               case NON_ATOMIC:
+               default:
+                       return e;
+               }
+               if ((o & ATOM) && !(g->status & ATOM))
+                       return e;
+               e = g;
+       }
+       if (cnt >= 200 || !e)
+               fatal("confusing control structure", (char *) 0);
+       return e;
+}
+
+void
+typ2c(Symbol *sp)
+{      int wsbits = sizeof(long)*8; /* wordsize in bits */
+       switch (sp->type) {
+       case UNSIGNED:
+               if (sp->hidden&1)
+                       fprintf(th, "\tuchar %s;", sp->name);
+               else
+                       fprintf(th, "\tunsigned %s : %d",
+                               sp->name, sp->nbits);
+               LstSet = sp;
+               if (nBits%wsbits > 0
+               &&  wsbits - nBits%wsbits < sp->nbits)
+               {       /* must padd to a word-boundary */
+                       nBits += wsbits - nBits%wsbits;
+               }
+               nBits += sp->nbits;
+               break;
+       case BIT:
+               if (sp->nel == 1 && !(sp->hidden&1))
+               {       fprintf(th, "\tunsigned %s : 1", sp->name);
+                       LstSet = sp; 
+                       nBits++;
+                       break;
+               } /* else fall through */
+               if (!(sp->hidden&1) && (verbose&32))
+               printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
+                       sp->name, sp->nel);
+               nBits += 8*sp->nel; /* mapped onto array of uchars */
+       case MTYPE:
+       case BYTE:
+       case CHAN:      /* good for up to 255 channels */
+               fprintf(th, "\tuchar %s", sp->name);
+               LstSet = sp;
+               break;
+       case SHORT:
+               fprintf(th, "\tshort %s", sp->name);
+               LstSet = sp;
+               break;
+       case INT:
+               fprintf(th, "\tint %s", sp->name);
+               LstSet = sp;
+               break;
+       case STRUCT:
+               if (!sp->Snm)
+                       fatal("undeclared structure element %s", sp->name);
+               fprintf(th, "\tstruct %s %s",
+                       sp->Snm->name,
+                       sp->name);
+               LstSet = ZS;
+               break;
+       case CODE_FRAG:
+       case PREDEF:
+               return;
+       default:
+               fatal("variable %s undeclared", sp->name);
+       }
+
+       if (sp->nel != 1)
+               fprintf(th, "[%d]", sp->nel);
+       fprintf(th, ";\n");
+}
+
+static void
+ncases(FILE *fd, int p, int n, int m, char *c[])
+{      int i, j;
+
+       for (j = 0; c[j]; j++)
+       for (i = n; i < m; i++)
+       {       fprintf(fd, c[j], i, p, i);
+               fprintf(fd, "\n");
+       }
+}
+
+void
+qlen_type(int qmax)
+{
+       fprintf(th, "\t");
+       if (qmax < 256)
+               fprintf(th, "uchar");
+       else if (qmax < 65535)
+               fprintf(th, "ushort");
+       else
+               fprintf(th, "uint");
+       fprintf(th, " Qlen;     /* q_size */\n");
+}
+
+void
+genaddqueue(void)
+{      char buf0[256];
+       int j, qmax = 0;
+       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)
+                       qmax = q->nslots;
+
+       for (q = qtab; q; q = q->nxt)
+       {       j = q->qid;
+               fprintf(tc, "\tcase %d: j = sizeof(Q%d);", j, j);
+               fprintf(tc, " q_flds[%d] = %d;", j, q->nflds);
+               fprintf(tc, " q_max[%d] = %d;", j, max(1,q->nslots));
+               fprintf(tc, " break;\n");
+
+               fprintf(th, "typedef struct Q%d {\n", j);
+               qlen_type(qmax);        /* 4.2.2 */
+               fprintf(th, "   uchar _t;       /* q_type */\n");
+               fprintf(th, "   struct {\n");
+
+               for (j = 0; j < q->nflds; j++)
+               {       switch (q->fld_width[j]) {
+                       case BIT:
+                               if (q->nflds != 1)
+                               {       fprintf(th, "\t\tunsigned");
+                                       fprintf(th, " fld%d : 1;\n", j);
+                                       break;
+                               } /* else fall through: smaller struct */
+                       case MTYPE:
+                       case CHAN:
+                       case BYTE:
+                               fprintf(th, "\t\tuchar fld%d;\n", j);
+                               break;
+                       case SHORT:
+                               fprintf(th, "\t\tshort fld%d;\n", j);
+                               break;
+                       case INT:
+                               fprintf(th, "\t\tint fld%d;\n", j);
+                               break;
+                       default:
+                               fatal("bad channel spec", "");
+                       }
+               }
+               fprintf(th, "   } contents[%d];\n", max(1, q->nslots));
+               fprintf(th, "} Q%d;\n", q->qid);
+       }
+
+       fprintf(th, "typedef struct Q0 {\t/* generic q */\n");
+       qlen_type(qmax);        /* 4.2.2 */
+       fprintf(th, "   uchar _t;\n");
+       fprintf(th, "} Q0;\n");
+
+       ntimes(tc, 0, 1, Addq1);
+
+       if (has_random)
+       {       fprintf(th, "int Q_has(int");
+               for (j = 0; j < Mpars; j++)
+                       fprintf(th, ", int, int");
+               fprintf(th, ");\n");
+
+               fprintf(tc, "int\nQ_has(int into");
+               for (j = 0; j < Mpars; j++)
+                       fprintf(tc, ", int want%d, int fld%d", j, j);
+               fprintf(tc, ")\n");
+               fprintf(tc, "{  int i;\n\n");
+               fprintf(tc, "   if (!into--)\n");
+               fprintf(tc, "   uerror(\"ref to unknown chan ");
+               fprintf(tc, "(recv-poll)\");\n\n");
+               fprintf(tc, "   if (into >= now._nr_qs || into < 0)\n");
+               fprintf(tc, "           Uerror(\"qrecv bad queue#\");\n\n");
+               fprintf(tc, "   for (i = 0; i < ((Q0 *)qptr(into))->Qlen;");
+               fprintf(tc, " i++)\n");
+               fprintf(tc, "   {\n");
+               for (j = 0; j < Mpars; j++)
+               {       fprintf(tc, "           if (want%d && ", j);
+                       fprintf(tc, "qrecv(into+1, i, %d, 0) != fld%d)\n",
+                               j, j);
+                       fprintf(tc, "                   continue;\n");
+               }
+               fprintf(tc, "           return i+1;\n");
+               fprintf(tc, "   }\n");
+               fprintf(tc, "   return 0;\n");
+               fprintf(tc, "}\n");
+       }
+
+       fprintf(tc, "#if NQS>0\n");
+       fprintf(tc, "void\nqsend(int into, int sorted");
+       for (j = 0; j < Mpars; j++)
+               fprintf(tc, ", int fld%d", j);
+       fprintf(tc, ", int args_given)\n");
+       ntimes(tc, 0, 1, Addq11);
+
+       for (q = qtab; q; q = q->nxt)
+       {       sprintf(buf0, "((Q%d *)z)->", q->qid);
+               fprintf(tc, "\tcase %d:%s\n", q->qid,
+                       (q->nslots)?"":" /* =rv= */");
+               if (q->nslots == 0)     /* reset handshake point */
+                       fprintf(tc, "\t\t(trpt+2)->o_m = 0;\n");
+
+               if (has_sorted)
+               {       fprintf(tc, "\t\tif (!sorted) goto append%d;\n", q->qid);
+                       fprintf(tc, "\t\tfor (j = 0; j < %sQlen; j++)\n", buf0);
+                       fprintf(tc, "\t\t{\t/* find insertion point */\n");
+                       sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
+                       for (j = 0; j < q->nflds; j++)
+                       {       fprintf(tc, "\t\t\tif (fld%d > %s%d) continue;\n",
+                                               j, buf0, j);
+                               fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
+                               fprintf(tc, "goto found%d;\n\n", q->qid);
+                       }
+                       fprintf(tc, "\t\t}\n");
+                       fprintf(tc, "\tfound%d:\n", q->qid);
+                       sprintf(buf0, "((Q%d *)z)->", q->qid);
+                       fprintf(tc, "\t\tfor (k = %sQlen - 1; k >= j; k--)\n", buf0);
+                       fprintf(tc, "\t\t{\t/* shift up */\n");
+                       for (j = 0; j < q->nflds; j++)
+                       {       fprintf(tc, "\t\t\t%scontents[k+1].fld%d = ",
+                                       buf0, j);
+                               fprintf(tc, "%scontents[k].fld%d;\n",
+                                       buf0, j);
+                       }
+                       fprintf(tc, "\t\t}\n");
+                       fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
+               }
+
+               fprintf(tc, "#ifdef HAS_SORTED\n");
+               fprintf(tc, "\t\t(trpt+1)->ipt = j;\n");        /* ipt was bup.oval */
+               fprintf(tc, "#endif\n");
+               fprintf(tc, "\t\t%sQlen = %sQlen + 1;\n", buf0, buf0);
+               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);
+
+       for (q = qtab; q; q = q->nxt)
+       fprintf(tc, "\tcase %d: return %d;\n", q->qid, (!q->nslots));
+
+       ntimes(tc, 0, 1, Addq3);
+
+       for (q = qtab; q; q = q->nxt)
+       fprintf(tc, "\tcase %d: return (q_sz(from) == %d);\n",
+                       q->qid, max(1, q->nslots));
+
+       ntimes(tc, 0, 1, Addq4);
+       for (q = qtab; q; q = q->nxt)
+       {       sprintf(buf0, "((Q%d *)z)->", q->qid);
+               fprintf(tc, "   case %d:%s\n\t\t",
+                       q->qid, (q->nslots)?"":" /* =rv= */");
+               if (q->nflds == 1)
+               {       fprintf(tc, "if (fld == 0) r = %s", buf0);
+                       fprintf(tc, "contents[slot].fld0;\n");
+               } else
+               {       fprintf(tc, "switch (fld) {\n");
+                       ncases(tc, q->qid, 0, q->nflds, R12);
+                       fprintf(tc, "\t\tdefault: Uerror");
+                       fprintf(tc, "(\"too many fields in recv\");\n");
+                       fprintf(tc, "\t\t}\n");
+               }
+               fprintf(tc, "\t\tif (done)\n");
+               if (q->nslots == 0)
+               {       fprintf(tc, "\t\t{      j = %sQlen - 1;\n",  buf0);
+                       fprintf(tc, "\t\t       %sQlen = 0;\n", buf0);
+                       sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
+               } else
+               {       fprintf(tc, "\t\t{      j = %sQlen;\n",  buf0);
+                       fprintf(tc, "\t\t       %sQlen = --j;\n", buf0);
+                       fprintf(tc, "\t\t       for (k=slot; k<j; k++)\n");
+                       fprintf(tc, "\t\t       {\n");
+                       sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
+                       for (j = 0; j < q->nflds; j++)
+                       {       fprintf(tc, "\t%s[k].fld%d = \n", buf0, j);
+                               fprintf(tc, "\t\t%s[k+1].fld%d;\n", buf0, j);
+                       }
+                       fprintf(tc, "\t\t       }\n");
+               }
+
+               for (j = 0; j < q->nflds; j++)
+                       fprintf(tc, "%s[j].fld%d = 0;\n", buf0, j);
+               fprintf(tc, "\t\t\tif (fld+1 != %d)\n\t\t\t", q->nflds);
+               fprintf(tc, "\tuerror(\"missing pars in receive\");\n");
+               /* incompletely received msgs cannot be unrecv'ed */
+               fprintf(tc, "\t\t}\n");
+               fprintf(tc, "\t\tbreak;\n");
+       }
+       ntimes(tc, 0, 1, Addq5);
+       for (q = qtab; q; q = q->nxt)
+       fprintf(tc, "   case %d: j = sizeof(Q%d); break;\n",
+               q->qid, q->qid);
+       ntimes(tc, 0, 1, R8b);
+
+       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, ", int);\n");
+
+       fprintf(th, "#define Addproc(x) addproc(x");
+       for (j = 0; j < Npars; j++)
+               fprintf(th, ", 0");
+       fprintf(th, ")\n");
+}
diff --git a/trunk/verif/Spin/Src5.1.6/pangen1.h b/trunk/verif/Spin/Src5.1.6/pangen1.h
new file mode 100755 (executable)
index 0000000..2a0ec12
--- /dev/null
@@ -0,0 +1,6529 @@
+/***** spin: pangen1.h *****/
+
+/* Copyright (c) 1989-2008 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            */
+/* (c) 2007: small additions for V5.0 to support multi-core verifications */
+
+static char *Code2a[] = { /* the tail of procedure run() */
+       "#if defined(VERI) && !defined(NOREDUCE) && !defined(NP)",
+       "       if (!state_tables",
+       "#ifdef HAS_CODE",
+       "       && !readtrail",
+       "#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\");",
+       "         printf(\"(never claims generated from LTL \");",
+       "         printf(\"formulae are stutter-invariant)\\n\");",
+       "       }",
+       "#endif",
+       "       UnBlock;        /* disable rendez-vous */",
+       "#ifdef BITSTATE",
+#ifndef POWOW
+       "       if (udmem)",
+       "       {       udmem *= 1024L*1024L;",
+       "       #if NCORE>1",
+       "               if (!readtrail)",
+       "               {       void init_SS(unsigned long);",
+       "                       init_SS((unsigned long) udmem);",
+       "               } else",
+       "       #endif",
+       "               SS = (uchar *) emalloc(udmem);",
+       "               bstore = bstore_mod;",
+       "       } else",
+#endif
+       "       #if NCORE>1",
+       "               { void init_SS(unsigned long);",
+       "                 init_SS(ONE_L<<(ssize-3));",
+       "               }",
+       "       #else",
+       "               SS = (uchar *) emalloc(ONE_L<<(ssize-3));",
+       "       #endif",
+       "#else",        /* if not BITSTATE */
+       "       hinit();",
+       "#endif",
+       "#if defined(FULLSTACK) && defined(BITSTATE)",
+       "       onstack_init();",
+       "#endif",
+       "#if defined(CNTRSTACK) && !defined(BFS)",
+       "       LL = (uchar *) emalloc(ONE_L<<(ssize-3));",
+       "#endif",
+       "       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",
+       "       if (vprefix > 0)",
+       "               write(svfd, (uchar *) &vprefix, sizeof(int));",
+       "#endif",
+       "#ifdef VERI",
+       "       Addproc(VERI);  /* never - pid = 0 */",
+       "#endif",
+       "       active_procs(); /* started after never */",
+       "#ifdef EVENT_TRACE",
+       "       now._event = start_event;",
+       "       reached[EVENT_TRACE][start_event] = 1;",
+       "#endif",
+
+       "#ifdef HAS_CODE",
+       "       globinit();",
+       "#endif",
+       "#ifdef BITSTATE",
+       "go_again:",
+       "#endif",
+       "       do_the_search();",
+       "#ifdef BITSTATE",
+       "       if (--Nrun > 0 && HASH_CONST[++HASH_NR])",
+       "       {       printf(\"Run %%d:\\n\", HASH_NR);",
+       "               wrap_stats();",
+       "               printf(\"\\n\");",
+       "               memset(SS, 0, ONE_L<<(ssize-3));",
+               "#ifdef CNTRSTACK",
+       "               memset(LL, 0, ONE_L<<(ssize-3));",
+               "#endif",
+               "#ifdef FULLSTACK",
+       "               memset((uchar *) S_Tab, 0, ",
+       "               maxdepth*sizeof(struct H_el *));",
+               "#endif",
+       "               nstates=nlinks=truncs=truncs2=ngrabs = 0;",
+       "               nlost=nShadow=hcmp = 0;",
+       "               Fa=Fh=Zh=Zn = 0;",
+       "               PUT=PROBE=ZAPS=Ccheck=Cholds = 0;",
+       "               goto go_again;",
+       "       }",
+       "#endif",
+       "}",
+       "#ifdef HAS_PROVIDED",
+       "int provided(int, uchar, int, Trans *);",
+       "#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 & (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 & (CS_N-1)))",
+       "#define QLOCK(n)       (3+n)",/* overlaps first n zones of hashtable */
+       "#endif",
+       "",
+       "void e_critical(int);",
+       "void x_critical(int);",
+       "",
+       "#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",
+       "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, ...)",
+       "{      /* Make sure the args to Printf",
+       "        * are always evaluated (e.g., they",
+       "        * could contain a run stmnt)",
+       "        * but do not generate the output",
+       "        * during verification runs",
+       "        * unless explicitly wanted",
+       "        * If this fails on your system",
+       "        * compile SPIN itself -DPRINTF",
+       "        * and this code is not generated",
+       "        */",
+       "#ifdef HAS_CODE",
+       "       if (readtrail)",
+       "       {       va_list args;",
+       "               va_start(args, fmt);",
+       "               vprintf(fmt, args);",
+       "               va_end(args);",
+       "               return 1;",
+       "       }",
+       "#endif",
+       "#ifdef PRINTF",
+       "       va_list args;",
+       "       va_start(args, fmt);",
+       "       vprintf(fmt, args);",
+       "       va_end(args);",
+       "#endif",
+       "       return 1;",
+       "}",
+#endif
+       "extern void printm(int);",
+
+       "#ifndef SC",
+       "#define getframe(i)    &trail[i];",
+       "#else",
+       "static long HHH, DDD, hiwater;",
+       "static long CNT1, CNT2;",
+       "static int stackwrite;",
+       "static int stackread;",
+       "static Trail frameptr;",
+       "Trail *",
+       "getframe(int d)",
+       "{",
+       "       if (CNT1 == CNT2)",
+       "               return &trail[d];",
+       "",
+       "       if (d >= (CNT1-CNT2)*DDD)",
+       "               return &trail[d - (CNT1-CNT2)*DDD];",
+       "",
+       "       if (!stackread",
+       "       &&  (stackread = open(stackfile, 0)) < 0)",
+       "       {       printf(\"getframe: cannot open %%s\\n\", stackfile);",
+       "               wrapup();",
+       "       }",
+       "       if (lseek(stackread, d* (off_t) sizeof(Trail), SEEK_SET) == -1",
+       "       || read(stackread, &frameptr, sizeof(Trail)) != sizeof(Trail))",
+       "       {       printf(\"getframe: frame read error\\n\");",
+       "               wrapup();",
+       "       }",
+       "       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;",
+       "}",
+       "#endif",
+       "#endif",
+
+       "#if NCORE>1",
+       "extern void cleanup_shm(int);",
+       "volatile unsigned int  *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",
+       "void",
+       "pan_exit(int val)",
+       "{      void stop_timer(void);",
+       "       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",
+       "       if (val == 2)",
+       "       {       val = 0;",
+       "       } else",
+       "       {       stop_timer();",
+       "       }",
+       "       exit(val);",
+       "}",
+
+       "#ifdef HAS_CODE",
+       "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 */
+       "       {       *v = '\\0'; v++;",
+       "               strcpy(buf[1-toggle], buf[toggle]);",
+       "               for (w = v; *w != '}' && *w != '\\0'; w++) /* skip */;",
+       "               if (*w != '}') return s;",
+       "               *w = '\\0'; w++;",
+       "               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])",
+       "                                +  strlen(code_lookup[i].t)",
+       "                                +  strlen(w) > 2047)",
+       "                                       return s;",
+       "                               strcat(buf[1-toggle], code_lookup[i].t);",
+       "                               break;",
+       "                       }",
+       "               strcat(buf[1-toggle], w);",
+       "               toggle = 1 - toggle;",
+       "       }",
+       "       buf[toggle][2047] = '\\0';",
+       "       return buf[toggle];",
+       "}",
+       "#else",
+       "char * transmognify(char *s) { return s; }",
+       "#endif",
+
+       "#ifdef HAS_CODE",
+       "void",
+       "add_src_txt(int ot, int tt)",
+       "{      Trans *t;",
+       "       char *q;",
+       "",
+       "       for (t = trans[ot][tt]; t; t = t->nxt)",
+       "       {       printf(\"\\t\\t\");",
+
+       "               q = transmognify(t->tp);",
+       "               for ( ; q && *q; q++)",
+       "                       if (*q == '\\n')",
+       "                               printf(\"\\\\n\");",
+       "                       else",
+       "                               putchar(*q);",
+       "               printf(\"\\n\");",
+       "       }",
+       "}",
+       "void",
+       "wrap_trail(void)",
+       "{      static int wrap_in_progress = 0;",
+       "       int i; short II;",
+       "       P0 *z;",
+       "",
+       "       if (wrap_in_progress++) return;",
+       "",
+       "       printf(\"spin: trail ends after %%ld steps\\n\", depth);",
+       "       if (onlyproc >= 0)",
+       "       {       if (onlyproc >= now._nr_pr) { pan_exit(0); }",
+       "               II = onlyproc;",
+       "               z = (P0 *)pptr(II);",
+       "               printf(\"%%3ld:\tproc %%d (%%s) \",",
+       "                       depth, II, procname[z->_t]);",
+       "               for (i = 0; src_all[i].src; i++)",
+       "                       if (src_all[i].tp == (int) z->_t)",
+       "                       {       printf(\" line %%3d\",",
+       "                                       src_all[i].src[z->_p]);",
+       "                               break;",
+       "                       }",
+       "               printf(\" (state %%2d)\", z->_p);",
+       "               if (!stopstate[z->_t][z->_p])",
+       "                       printf(\" (invalid end state)\");",
+       "               printf(\"\\n\");",
+       "               add_src_txt(z->_t, z->_p);",
+       "               pan_exit(0);",
+       "       }",
+       "       printf(\"#processes %%d:\\n\", now._nr_pr);",
+       "       if (depth < 0) depth = 0;",
+       "       for (II = 0; II < now._nr_pr; II++)",
+       "       {       z = (P0 *)pptr(II);",
+       "               printf(\"%%3ld:\tproc %%d (%%s) \",",
+       "                       depth, II, procname[z->_t]);",
+       "               for (i = 0; src_all[i].src; i++)",
+       "                       if (src_all[i].tp == (int) z->_t)",
+       "                       {       printf(\" line %%3d\",",
+       "                                       src_all[i].src[z->_p]);",
+       "                               break;",
+       "                       }",
+       "               printf(\" (state %%2d)\", z->_p);",
+       "               if (!stopstate[z->_t][z->_p])",
+       "                       printf(\" (invalid end state)\");",
+       "               printf(\"\\n\");",
+       "               add_src_txt(z->_t, z->_p);",
+       "       }",
+       "       c_globals();",
+       "       for (II = 0; II < now._nr_pr; II++)",
+       "       {       z = (P0 *)pptr(II);",
+       "               c_locals(II, z->_t);",
+       "       }",
+       "#ifdef ON_EXIT",
+       "       ON_EXIT;",
+       "#endif",
+       "       pan_exit(0);",
+       "}",
+       "FILE *",
+       "findtrail(void)",
+       "{      FILE *fd;",
+       "       char fnm[512], *q;",
+       "       char MyFile[512];",     /* avoid using a non-writable string */
+       "       char MySuffix[16];",
+       "       int  try_core;",
+       "       int  candidate_files;",
+       "",
+       "       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);",
+       "                       *q = \'.\';",
+       "                       fd = fopen(fnm, \"r\");",
+       "               }",
+       "       } else",
+       "       {       sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
+       "               fd = fopen(fnm, \"r\");",
+       "               if (fd == NULL && (q = strchr(MyFile, \'.\')))",
+       "               {       *q = \'\\0\';", /* e.g., strip .pml on original file */
+       "                       sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
+       "                       *q = \'.\';",
+       "                       fd = fopen(fnm, \"r\");",
+       "       }       }",
+       "       if (fd == NULL)",
+       "       {       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);",
+       "",
+       "void",
+       "getrail(void)",
+       "{      FILE *fd;",
+       "       char *q;",
+       "       int i, t_id, lastnever=-1; short II;",
+       "       Trans *t;",
+       "       P0 *z;",
+       "",
+       "       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\");",
+       "               if (depth < 0)",
+       "                       continue;",
+       "               if (i > now._nr_pr)",
+       "               {       printf(\"pan: Error, proc %%d invalid pid \", i);",
+       "                       printf(\"transition %%d\\n\", t_id);",
+       "                       break;",
+       "               }",
+       "               II = i;",
+       "               z = (P0 *)pptr(II);",
+       "               for (t = trans[z->_t][z->_p]; t; t = t->nxt)",
+       "                       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) t_id)",
+       "                               {       printf(\"\\tRecovered at state %%d\\n\", i);",
+       "                                       z->_p = i;",
+       "                                       goto recovered;",
+       "                       }       }",
+       "                       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);",
+       "                       break; /* pan_exit(1); */",
+       "               }",
+       "recovered:",
+       "               q = transmognify(t->tp);",
+       "               if (gui) simvals[0] = \'\\0\';",
+
+       "               this = pptr(II);",
+       "               trpt->tau |= 1;",       /* timeout always possible */
+       "               if (!do_transit(t, II))",
+       "               {       if (onlyproc >= 0 && II != onlyproc)",
+       "                               goto moveon;",
+       "                       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\");",
+       "               }",
+
+       "               if (onlyproc >= 0 && II != onlyproc)",
+       "                       goto moveon;",
+
+       "               if (verbose)",
+       "               {       printf(\"%%3ld: proc %%2d (%%s) \", depth, II, procname[z->_t]);",
+
+       "                       for (i = 0; src_all[i].src; i++)",
+       "                               if (src_all[i].tp == (int) z->_t)",
+       "                               {       printf(\" line %%3d \\\"%%s\\\" \",",
+       "                                               src_all[i].src[z->_p], PanSource);",
+       "                                       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)",
+       "               {       if (lastnever != (int) z->_p)",
+       "                       {       for (i = 0; src_all[i].src; i++)",
+       "                                       if (src_all[i].tp == (int) z->_t)",
+       "                                       {       printf(\"MSC: ~G %%d\\n\",",
+       "                                                       src_all[i].src[z->_p]);",
+       "                                               break;",
+       "                                       }",
+       "                               if (!src_all[i].src)",
+       "                                       printf(\"MSC: ~R %%d\\n\", z->_p);",
+       "                       }",
+       "                       lastnever = z->_p;",
+       "                       goto sameas;",
+       "               } else",
+       "               if (strcmp(procname[z->_t], \":np_:\") != 0)",
+       "               {",
+       "sameas:                if (no_rck) goto moveon;",
+       "                       if (coltrace)",
+       "                       {       printf(\"%%ld: \", depth);",
+       "                               for (i = 0; i < II; i++)",
+       "                                       printf(\"\\t\\t\");",
+       "                               printf(\"%%s(%%d):\", procname[z->_t], II);",
+       "                               printf(\"[%%s]\\n\", q?q:\"\");",
+       "                       } else if (!silent)",
+       "                       {       if (strlen(simvals) > 0) {",
+       "                               printf(\"%%3ld: proc %%2d (%%s)\", ",
+       "                                       depth, II, procname[z->_t]);",
+       "                               for (i = 0; src_all[i].src; i++)",
+       "                                       if (src_all[i].tp == (int) z->_t)",
+       "                                       {       printf(\" line %%3d \\\"%%s\\\" \",",
+       "                                                       src_all[i].src[z->_p], PanSource);",
+       "                                               break;",
+       "                                       }",
+       "                               printf(\"(state %%d)\t[values: %%s]\\n\", z->_p, simvals);",
+       "                               }",
+       "                               printf(\"%%3ld: proc %%2d (%%s)\", ",
+       "                                       depth, II, procname[z->_t]);",
+       "                               for (i = 0; src_all[i].src; i++)",
+       "                                       if (src_all[i].tp == (int) z->_t)",
+       "                                       {       printf(\" line %%3d \\\"%%s\\\" \",",
+       "                                                       src_all[i].src[z->_p], PanSource);",
+       "                                               break;",
+       "                                       }",
+       "                               printf(\"(state %%d)\t[%%s]\\n\", z->_p, q?q:\"\");",
+       "                       /*      printf(\"\\n\");        */",
+       "               }       }",
+       "moveon:        z->_p = t->st;",
+       "       }",
+       "       wrap_trail();",
+       "}",
+       "#endif",
+       "int",
+       "f_pid(int pt)",
+       "{      int i;",
+       "       P0 *z;",
+       "       for (i = 0; i < now._nr_pr; i++)",
+       "       {       z = (P0 *)pptr(i);",
+       "               if (z->_t == (unsigned) pt)",
+       "                       return BASE+z->_pid;",
+       "       }",
+       "       return -1;",
+       "}",
+       "#ifdef VERI",
+       "void check_claim(int);",
+       "#endif",
+       "",
+       "#if !defined(HASH64) && !defined(HASH32)",
+       "       #define HASH32",
+       "#endif",
+       "#if defined(HASH32) && defined(SAFETY) && !defined(SFH) && !defined(SPACE)",
+       "       #define SFH",
+       "#endif",
+       "#if defined(SFH) && (defined(BITSTATE) || defined(COLLAPSE) || defined(HC) || defined(HASH64))",
+       "       #undef SFH",    /* need 2 hash fcts, for which Jenkins is best */
+       "#endif",               /* or a 64 bit hash, which we dont have for SFH */
+       "#if defined(SFH) && !defined(NOCOMP)",
+       "       #define NOCOMP  /* go for speed */",
+       "#endif",
+       "#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 = K1; y = j3;",       /* was K2 before 5.1.1 */
+       "       for (;;)",
+       "       {       if (!(SS[x%%udmem]&(1<<y))) break;",    /* take the hit in speed */
+       "               if (i == hfns) {",
+                               "#ifdef DEBUG",
+       "                       printf(\"Old bitstate\\n\");",
+                               "#endif",
+       "                       return 1;",
+       "               }",
+       "               x = (x + K2 + i);",     /* no mask, using mod - was K1 before 5.1.1 */
+       "               y = (y + j4) & 7;",
+       "               i++;",
+       "       }",
+               "#ifdef RANDSTOR",
+       "       if (rand()%%100 > RANDSTOR) return 0;",
+               "#endif",
+       "       for (;;)",
+       "       {       SS[x%%udmem] |= (1<<y);",
+       "               if (i == hfns) break;", /* done */
+       "               x = (x + K2 + i);",     /* no mask - was K1 before 5.1.1 */
+       "               y = (y + j4) & 7;",
+       "               i++;",
+       "       }",
+               "#ifdef DEBUG",
+       "       printf(\"New bitstate\\n\");",
+               "#endif",
+       "       if (now._a_t&1)",
+       "       {       nShadow++;",
+       "       }",
+       "       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;",
+       "       for (;;)",
+       "       {       if (!(SS[x]&(1<<y))) break;",   /* at least one bit not set */
+       "               if (i == hfns) {",
+                               "#ifdef DEBUG",
+       "                       printf(\"Old bitstate\\n\");",
+                               "#endif",
+       "                       return 1;",
+       "               }",
+       "               x = (x + j1 + i) & nmask;",
+       "               y = (y + j4) & 7;",
+       "               i++;",
+       "       }",
+               "#ifdef RANDSTOR",
+       "       if (rand()%%100 > RANDSTOR) return 0;",
+               "#endif",
+       "       for (;;)",
+       "       {       SS[x] |= (1<<y);",
+       "               if (i == hfns) break;",         /* done */
+       "               x = (x + j1 + i) & nmask;",
+       "               y = (y + j4) & 7;",
+       "               i++;",
+       "       }",
+               "#ifdef DEBUG",
+       "       printf(\"New bitstate\\n\");",
+               "#endif",
+       "       if (now._a_t&1)",
+       "       {       nShadow++;",
+       "       }",
+       "       return 0;",
+       "}",
+       "#endif", /* BITSTATE */
+       "unsigned long TMODE = 0666; /* file permission bits for trail files */",
+       "",
+       "int trcnt=1;",
+       "char snap[64], fnm[512];",
+       "",
+       "int",
+       "make_trail(void)",
+       "{      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)",
+       "       {       sprintf(fnm, \"%%s%%d.%%s\",",
+       "                       MyFile, Nr_Trails-1, tprefix);",
+       "       } else",
+       "       {",
+       "#ifdef PUTPID",
+       "               sprintf(fnm, \"%%s%%d.%%s\", MyFile, getpid(), tprefix);",
+       "#else",
+       "               sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
+       "#endif",
+       "       }",
+#if 1
+       "       if ((fd = open(fnm, w_flags, TMODE)) < 0)",
+#else
+       "       if ((fd = creat(fnm, TMODE)) < 0)",
+#endif
+       "       {       if ((q = strchr(MyFile, \'.\')))",
+       "               {       *q = \'\\0\';",         /* strip .pml */
+       "                       if (iterative == 0 && Nr_Trails-1 > 0)",
+       "                               sprintf(fnm, \"%%s%%d.%%s\",",
+       "                                       MyFile, Nr_Trails-1, tprefix);",
+       "                       else",
+       "                               sprintf(fnm, \"%%s.%%s\", MyFile, tprefix);",
+       "                       *q = \'.\';",
+#if 1
+       "                       fd = open(fnm, w_flags, TMODE);",
+#else
+       "                       fd = creat(fnm, TMODE);",
+#endif
+       "       }       }",
+       "       if (fd < 0)",
+       "       {       printf(\"pan: cannot create %%s\\n\", fnm);",
+       "               perror(\"cause\");",
+       "       } else",
+       "       {",
+       "#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;",
+       "}",
+       "",
+       "#ifndef FREQ",
+       "#define FREQ   (1000000)",
+       "#endif",
+       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;",
+       "       char *po;",
+       "       char *qo;",
+       "       char *ps, *qs;",
+       "       struct EV_Hold *nxt;",
+       "} EV_Hold;",
+       "",
+       "typedef struct BFS_Trail {",
+       "       Trail   *frame;",
+       "       SV_Hold *onow;",
+       "       EV_Hold *omask;",
+       "#ifdef Q_PROVISO",
+       "       struct H_el *lstate;",
+       "#endif",
+       "       short boq;",
+       "       struct BFS_Trail *nxt;",
+       "} BFS_Trail;",
+       "",
+       "BFS_Trail *bfs_trail, *bfs_bot, *bfs_free;",
+       "",
+       "SV_Hold *svhold, *svfree;",
+       "",
+"#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)",
+       "#else",
+       "       #define RFLAGS  (O_RDONLY)",
+       "       #define WFLAGS  (O_CREAT|O_WRONLY|O_TRUNC)",
+       "#endif",
+
+       "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",
+       "",
+       "uchar do_reverse(Trans *, short, uchar);",
+       "void snapshot(void);",
+       "",
+       "SV_Hold *",
+       "getsv(int n)",
+       "{      SV_Hold *h = (SV_Hold *) 0, *oh;",
+       "",
+       "       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)",
+       "       {       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;",
+       "}",
+       "",
+       "EV_Hold *",
+       "getsv_mask(int n)",
+       "{      EV_Hold *h;",
+       "       static EV_Hold *kept = (EV_Hold *) 0;",
+       "",
+       "       for (h = kept; h; h = h->nxt)",
+       "               if (n == h->sz",
+       "               &&  (memcmp((char *) Mask, (char *) h->sv, n) == 0)",
+       "               &&  (now._nr_pr == h->nrpr)",
+       "               &&  (now._nr_qs == h->nrqs)",
+       "#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))",
+       "                       break;",
+       "       if (!h)",
+       "       {       h = (EV_Hold *) emalloc(sizeof(EV_Hold));",
+       "               h->sz = n;",
+       "               h->nrpr = now._nr_pr;",
+       "               h->nrqs = now._nr_qs;",
+       "",
+       "               h->sv = (char *) emalloc(n * sizeof(char));",
+       "               memcpy((char *) h->sv, (char *) Mask, n);",
+       "",
+       "               if (now._nr_pr > 0)",
+       "               {       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",
+       "                       h->po = (char *) emalloc(now._nr_pr * sizeof(short));",
+       "                       memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(short));",
+       "#endif",
+       "               }",
+       "               if (now._nr_qs > 0)",
+       "               {       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",
+       "                       h->qo = (char *) emalloc(now._nr_qs * sizeof(short));",
+       "                       memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(short));",
+       "#endif",
+       "               }",
+       "",
+       "               h->nxt = kept;",
+       "               kept = h;",
+       "       }",
+       "       return h;",
+       "}",
+       "",
+       "void",
+       "freesv(SV_Hold *p)",
+       "{      SV_Hold *h, *oh;",
+       "",
+       "       oh = (SV_Hold *) 0;",
+       "       for (h = svfree; h; oh = h, h = h->nxt)",
+       "               if (h->sz >= p->sz)",
+       "                       break;",
+       "",
+       "       if (!oh)",
+       "       {       p->nxt = svfree;",
+       "               svfree = p;",
+       "       } else",
+       "       {       p->nxt = h;",
+       "               oh->nxt = p;",
+       "       }",
+       "}",
+       "",
+       "BFS_Trail *",
+       "get_bfs_frame(void)",
+       "{      BFS_Trail *t;",
+       "",
+       "       if (bfs_free)",
+       "       {       t = bfs_free;",
+       "               bfs_free = bfs_free->nxt;",
+       "               t->nxt = (BFS_Trail *) 0;",
+       "       } else",
+       "       {       t = (BFS_Trail *) emalloc(sizeof(BFS_Trail));",
+       "       }",
+       "       t->frame = (Trail *) emalloc(sizeof(Trail));", /* always new */
+       "       return t;",
+       "}",
+       "",
+       "void",
+       "push_bfs(Trail *f, int d)",
+       "{      BFS_Trail *t;",
+       "",
+       "       t = get_bfs_frame();",
+       "       memcpy((char *)t->frame, (char *)f, sizeof(Trail));",
+       "       t->frame->o_tt = d;     /* depth */",
+       "",
+       "       t->boq = boq;",
+       "       t->onow = getsv(vsize);",
+       "       t->omask = getsv_mask(vsize);",
+       "#if defined(FULLSTACK) && defined(Q_PROVISO)",
+       "       t->lstate = Lstate;",
+       "#endif",
+       "       if (!bfs_bot)",
+       "       {       bfs_bot = bfs_trail = t;",
+       "       } else",
+       "       {       bfs_bot->nxt = t;",
+       "               bfs_bot = t;",
+       "       }",
+       "#ifdef CHECK",
+       "       printf(\"PUSH %%u (%%d)\\n\", t->frame, d);",
+       "#endif",
+       "}",
+       "",
+       "Trail *",
+       "pop_bfs(void)",
+       "{      BFS_Trail *t;",
+       "",
+       "       if (!bfs_trail)",
+       "               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",
+       "",
+       "       t->nxt = bfs_free;",
+       "       bfs_free = t;",
+       "",
+       "       vsize = t->onow->sz;",
+       "       boq = t->boq;",
+"#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);",
+       "       memcpy((uchar *) Mask, (uchar *) t->omask->sv, vsize);",
+
+       "       if (now._nr_pr > 0)",
+       "#if VECTORSZ>32000",
+       "       {       memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(int));",
+       "#else",
+       "       {       memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(short));",
+       "#endif",
+       "               memcpy((char *)proc_skip,   (char *)t->omask->ps, now._nr_pr * sizeof(uchar));",
+       "       }",
+       "       if (now._nr_qs > 0)",
+       "#if VECTORSZ>32000",
+       "       {       memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(int));",
+       "#else",
+       "       {       memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(short));",
+       "#endif",
+       "               memcpy((uchar *)q_skip,   (uchar *)t->omask->qs, now._nr_qs * sizeof(uchar));",
+       "       }",
+
+"#ifdef BFS_DISK",
+       "       if (t->onow->sv != (State *) 0)",
+"#endif",
+       "               freesv(t->onow);        /* omask not freed */",
+       "#ifdef CHECK",
+       "       printf(\"POP %%u (%%d)\\n\", t->frame, t->frame->o_tt);",
+       "#endif",
+       "       return t->frame;",
+       "}",
+       "",
+       "void",
+       "store_state(Trail *ntrpt, int shortcut, short oboq)",
+       "{",
+       "#ifdef VERI",
+       "       Trans *t2 = (Trans *) 0;",
+       "       uchar ot; int tt, E_state;",
+       "       uchar o_opm = trpt->o_pm, *othis = this;",
+       "",
+       "       if (shortcut)",
+       "       {",
+       "#ifdef VERBOSE",
+       "               printf(\"claim: shortcut\\n\");",
+       "#endif",
+       "               goto store_it;  /* no claim move */",
+       "       }",
+       "",
+       "       this  = (((uchar *)&now)+proc_offset[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",
+       "       E_state = 0;",
+               "#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",
+       "               if (do_transit(t2, 0))",
+       "               {",
+               "#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",
+       "                       E_state = t2->e_trans;",
+               "#endif",
+       "                       if (t2->st > 0)",
+       "                       {       ((P0 *)this)->_p = t2->st;",
+       "                               reached[ot][t2->st] = 1;",
+               "#ifndef NOCLAIM",
+       "                               check_claim(t2->st);",
+               "#endif",
+       "                       }",
+       "                       if (now._nr_pr == 0)    /* claim terminated */",
+       "                               uerror(\"end state in claim reached\");",
+       "",
+               "#ifdef PEG",
+       "                       peg[t2->forw]++;",
+               "#endif",
+       "                       trpt->o_pm |= 1;",
+       "                       if (t2->atom&2)",       /* atomic in claim */
+       "                       Uerror(\"atomic in claim not supported in BFS mode\");",
+       "store_it:",
+       "",
+       "#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",
+       "                       {       static long sdone = (long) 0; long ndone;",
+       "                               nstates++;",
+       "#ifndef NOREDUCE",
+       "                               trpt->tau |= 64;", /* succ definitely outside stack */
+       "#endif",
+       "                               ndone = (unsigned long) (nstates/((double) 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)",
+       "                               {       Trail *x;",
+       "                                       x = (Trail *) trpt->ostate; /* pre-rv state */",
+       "                                       if (x) x->o_pm |= 4; /* mark success */",
+       "                               }",
+       "#endif",
+       "                               push_bfs(ntrpt, trpt->o_tt+1);",
+       "                       } else",
+       "                       {       truncs++;",
+
+       "#if !defined(NOREDUCE) && defined(FULLSTACK) && defined(Q_PROVISO)",
+               "#if !defined(BITSTATE)",
+       "                               if (Lstate && Lstate->tagged) trpt->tau |= 64;",
+               "#else",
+       "                               if (trpt->tau&32)",
+       "                               {  BFS_Trail *tprov;",
+       "                                  for (tprov = bfs_trail; tprov; tprov = tprov->nxt)",
+       "                                       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",
+       "                       }",
+       "#ifdef VERI",
+       "                       ((P0 *)this)->_p = tt;  /* reset claim */",
+       "                       if (t2)",
+       "                               do_reverse(t2, 0, 0);",
+       "                       else",
+       "                               break;",
+       "       }       }",
+       "       this = othis;",
+       "       trpt->o_pm = o_opm;",
+       "#endif",
+       "}",
+       "",
+       "Trail *ntrpt;",        /* 4.2.8 */
+       "",
+       "void",
+       "bfs(void)",
+       "{      Trans *t; Trail *otrpt, *x;",
+       "       uchar _n, _m, ot, nps = 0;",
+       "       int tt, E_state;",
+       "       short II, From = (short) (now._nr_pr-1), To = BASE;",
+       "       short oboq = boq;",
+       "",
+       "       ntrpt = (Trail *) emalloc(sizeof(Trail));",
+       "       trpt->ostate = (struct H_el *) 0;",
+       "       trpt->tau = 0;",
+       "",
+       "       trpt->o_tt = -1;",
+       "       store_state(ntrpt, 0, oboq);    /* initial state */",
+       "",
+       "       while ((otrpt = pop_bfs()))     /* also restores now */",
+       "       {       memcpy((char *) trpt, (char *) otrpt, sizeof(Trail));",
+       "#if defined(C_States) && (HAS_TRACK==1)",
+       "               c_revert((uchar *) &(now.c_state[0]));",
+       "#endif",
+       "               if (trpt->o_pm & 4)",
+       "               {",
+       "#ifdef VERBOSE",
+       "                       printf(\"Revisit of atomic not needed (%%d)\\n\",",
+       "                               trpt->o_pm);",  /* at least 1 rv succeeded */
+       "#endif",
+       "                       continue;",
+       "               }",
+       "#ifndef NOREDUCE",
+       "               nps = 0;",
+       "#endif",
+       "               if (trpt->o_pm == 8)",
+       "               {       revrv++;",
+       "                       if (trpt->tau&8)",
+       "                       {",
+               "#ifdef VERBOSE",
+       "                               printf(\"Break atomic (pm:%%d,tau:%%d)\\n\",",
+       "                                       trpt->o_pm, trpt->tau);",
+               "#endif",
+       "                               trpt->tau &= ~8;",
+       "                       }",
+       "#ifndef NOREDUCE",
+       "                       else if (trpt->tau&32)",        /* was a preselected move */
+       "                       {",
+               "#ifdef VERBOSE",
+       "                               printf(\"Void preselection (pm:%%d,tau:%%d)\\n\",",
+       "                                       trpt->o_pm, trpt->tau);",
+               "#endif",
+       "                               trpt->tau &= ~32;",
+       "                               nps = 1; /* no preselection in repeat */",
+       "                       }",
+       "#endif",
+       "               }",
+       "               trpt->o_pm &= ~(4|8);",
+       "               if (trpt->o_tt > mreached)",
+       "               {       mreached = trpt->o_tt;",
+       "                       if (mreached%%10 == 0)",
+       "                       {       snapshot();",
+       "               }       }",
+       "               depth = trpt->o_tt;",
+
+       "               if (depth >= maxdepth)",
+       "               {",
+       "#if SYNC",
+       "                       Trail *x;",
+       "                       if (boq != -1)",
+       "                       {       x = (Trail *) trpt->ostate;",
+       "                               if (x) x->o_pm |= 4; /* not failing */",
+       "                       }",
+       "#endif",
+       "                       truncs++;",
+       "                       if (!warned)",
+       "                       {       warned = 1;",
+       "                               printf(\"error: max search depth too small\\n\");",
+       "                       }",
+       "                       if (bounded)",
+       "                               uerror(\"depth limit reached\");",
+       "                       continue;",
+       "               }",
+
+/* PO */
+       "#ifndef NOREDUCE",
+       "               if (boq == -1 && !(trpt->tau&8) && 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)",  /* safe */
+       "                       {       t = trans[ot][tt];",
+       "                               if (t->qu[0] != 0)",
+       "                               {       Ccheck++;",
+       "                                       if (!q_cond(II, t))",
+       "                                               continue;",
+       "                                       Cholds++;",
+       "                               }",
+       "                               From = To = II;",
+       "                               trpt->tau |= 32; /* preselect marker */",
+               "#ifdef DEBUG",
+       "                               printf(\"%%3d: proc %%d PreSelected (tau=%%d)\\n\", ",
+       "                                       depth, II, trpt->tau);",
+               "#endif",
+       "                               goto MainLoop;",
+       "               }       }",
+       "               trpt->tau &= ~32;",     /* not preselected */
+       "#endif",
+/* PO */
+       "Repeat:",
+       "               if (trpt->tau&8)                /* atomic */",
+       "               {       From = To = (short ) trpt->pr;",
+       "                       nlinks++;",
+       "               } else",
+       "               {       From = now._nr_pr-1;",
+       "                       To = BASE;",
+       "               }",
+       "MainLoop:",
+       "               _n = _m = 0;",
+       "               for (II = From; II >= To; II -= 1)",
+       "               {",
+       "                       this = (((uchar *)&now)+proc_offset[II]);",
+       "                       tt = (int) ((P0 *)this)->_p;",
+       "                       ot = (uchar) ((P0 *)this)->_t;",
+       "#if SYNC",
+       "                       /* no rendezvous with same proc */",
+       "                       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_event = now._event;",
+       "#endif",
+       "#ifdef HAS_PROVIDED",
+       "                       if (!provided(II, ot, tt, t)) continue;",
+       "#endif",
+       "#ifdef HAS_UNLESS",
+       "                       E_state = 0;",
+       "#endif",
+       "                       for (t = trans[ot][tt]; t; t = t->nxt)",
+       "                       {",
+       "#ifdef HAS_UNLESS",
+       "                               if (E_state > 0",
+       "                               &&  E_state != t->e_trans)",
+       "                                       break;",
+       "#endif",
+       "                               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 CHECK",
+       "                               printf(\"%%3d: 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);",
+       "#endif",
+       "#ifdef HAS_UNLESS",
+       "                               E_state = t->e_trans;",
+               "#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, \"\tof an unless stmnt is not compatible with -DBFS\\n\");",
+       "                                 pan_exit(1);",
+       "                               }",
+               "#endif",
+       "#endif",
+       "                               if (t->st > 0) ((P0 *)this)->_p = t->st;",
+       "",
+       "       /* ptr to pred: */      ntrpt->ostate = (struct 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",
+       "                               now._event = trpt->o_event;",
+       "#endif",
+       "",
+       "                               /* undo move and continue */",
+       "                               trpt++; /* this is where ovals and ipt are set */",
+       "                               do_reverse(t, II, _m);  /* restore now. */",
+       "                               trpt--;",
+       "#ifdef CHECK",
+       "       #if NCORE>1",
+       "                               enter_critical(GLOBAL_LOCK);    /* in verbose mode only */",
+       "                               printf(\"cpu%%d: \", core_id);",
+       "       #endif",
+       
+       "                               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);",
+       "       #if NCORE>1",
+       "                               leave_critical(GLOBAL_LOCK);",
+       "       #endif",
+       "#endif",
+       "                               reached[ot][t->st] = 1;",
+       "                               reached[ot][tt] = 1;",
+       "",
+       "                               ((P0 *)this)->_p = tt;",
+       "                               _n |= _m;",
+       "               }       }",
+/* PO */
+       "#ifndef NOREDUCE",
+       "               /* preselected - no succ definitely outside stack */",
+       "               if ((trpt->tau&32) && !(trpt->tau&64))",
+       "               {       From = now._nr_pr-1; To = BASE;",
+       "#ifdef DEBUG",
+       "                       cpu_printf(\"%%3d: 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 MainLoop;",
+       "               }",
+       "               trpt->tau &= ~(32|64);",
+       "#endif",
+/* PO */
+       "               if (_n != 0)",
+       "                       continue;",
+       "#ifdef DEBUG",
+       "               printf(\"%%3d: no move [II=%%d, tau=%%d, boq=%%d, _nr_pr=%%d]\\n\",",
+       "                       depth, II, trpt->tau, boq, now._nr_pr);",
+       "#endif",
+       "               if (boq != -1)",
+       "               {       failedrv++;",
+       "                       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",
+       "                               printf(\"\\treset state of %%d from %%d to %%d\\n\",",
+       "                                       otrpt->pr, ((P0 *)this)->_p, otrpt->st);",
+       "#endif",
+       "                               ((P0 *)this)->_p = otrpt->st;",
+       "                               unsend(boq);    /* retract rv offer */",
+       "                               boq = -1;",
+
+       "                               push_bfs(x, x->o_tt);",
+       "#ifdef VERBOSE",
+       "                               printf(\"failed rv, repush with %%d\\n\", x->o_pm);",
+       "#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\",",
+       "                                       depth, II+1);",
+       "#endif",
+       "                               goto Repeat;",
+       "                       }",
+       "",
+       "                       if (!(trpt->tau&1)) /* didn't try timeout yet */",
+       "                       {       trpt->tau |=  1;",
+       "#ifdef DEBUG",
+       "                               printf(\"%%d: timeout\\n\", depth);",
+       "#endif",
+       "                               goto MainLoop;",
+       "                       }",
+       "#ifndef VERI",
+       "                       if (!noends && !a_cycles && !endstate())",
+       "                               uerror(\"invalid end state\");",
+       "#endif",
+       "       }       }",
+       "}",
+       "",
+       "void",
+       "putter(Trail *trpt, int fd)",
+       "{      long j;",
+       "",
+       "       if (!trpt) return;",
+       "",
+       "       if (trpt != (Trail *) trpt->ostate)",
+       "               putter((Trail *) trpt->ostate, fd);",
+       "",
+       "       if (trpt->o_t)",
+       "       {       sprintf(snap, \"%%d:%%d:%%d\\n\",",
+       "                       trcnt++, trpt->pr, trpt->o_t->t_id);",
+       "               j = strlen(snap);",
+       "               if (write(fd, snap, j) != j)",
+       "               {       printf(\"pan: error writing %%s\\n\", fnm);",
+       "                       pan_exit(1);",
+       "       }       }",
+       "}",
+       "",
+       "void",
+       "nuerror(char *str)",
+       "{      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",
+       "       trcnt = 1;",
+       "       putter(trpt, fd);",
+       "       if (ntrpt->o_t)",       /* 4.2.8 -- Alex example, missing last transition */
+       "       {       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);",
+       "       }       }",
+       "       close(fd);",
+       "       if (errors >= upto && upto != 0)",
+       "       {       wrapup();",
+       "       }",
+       "}",
+       "#endif",       /* BFS */
+       0,
+};
+
+static char *Code2d[] = {
+       "clock_t start_time;",
+       "#if NCORE>1",
+       "clock_t crash_stamp;",
+       "#endif",
+       "#if !defined(WIN32) && !defined(WIN64)",
+       "struct tms start_tm;",
+       "#endif",
+       "",
+       "void",
+       "start_timer(void)",
+       "{",
+       "#if defined(WIN32) || defined(WIN64)",
+       "       start_time = clock();",
+       "#else",
+       "       start_time = times(&start_tm);",
+       "#endif",
+       "}",
+       "",
+       "void",
+       "stop_timer(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 (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",
+       "       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));",
+       "       }       }",
+       "#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",
+       "",
+       "void",
+       "do_the_search(void)",
+       "{      int i;",
+       "       depth = mreached = 0;",
+       "       trpt = &trail[0];",
+       "#ifdef VERI",
+       "       trpt->tau |= 4; /* the claim moves first */",
+       "#endif",
+       "       for (i = 0; i < (int) now._nr_pr; i++)",
+       "       {       P0 *ptr = (P0 *) pptr(i);",
+       "#ifndef NP",
+       "               if (!(trpt->o_pm&2)",
+       "               &&  accpstate[ptr->_t][ptr->_p])",
+       "               {       trpt->o_pm |= 2;",
+       "               }",
+       "#else",
+       "               if (!(trpt->o_pm&4)",
+       "               &&  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",
+       "#ifndef NOCOMP",
+       "       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[] */",
+       "       }",
+       "#endif",
+       "#endif",
+       "#ifndef NOFAIR",
+       "       if (fairness",
+       "       &&  (a_cycles && (trpt->o_pm&2)))",
+       "       {       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\",",
+       "               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]));",
+       "#endif",
+
+       "#ifdef HAS_CODE",
+       "       if (readtrail) getrail(); /* no return */",
+       "#endif",
+       "       start_timer();",
+       "#ifdef BFS",
+       "       bfs();",
+       "#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",
+       "       #if RANDOMIZE>0",
+       "       srand(RANDOMIZE);",
+       "       #else",
+       "       srand(123);",
+       "       #endif",
+       "#endif",
+       "#if NCORE>1",
+       "       mem_get();",
+       "#else",
+       "       new_state();    /* start 1st DFS */",
+       "#endif",
+       "#endif",
+       "}",
+
+       "#ifdef INLINE_REV",
+       "uchar",
+       "do_reverse(Trans *t, short II, uchar M)",
+       "{      uchar _m = M;",
+       "       int  tt = (int) ((P0 *)this)->_p;",
+       "#include REVERSE_MOVES",
+       "R999:  return _m;",
+       "}",
+       "#endif",
+
+       "#ifndef INLINE",
+       "#ifdef EVENT_TRACE",
+       "static char _tp = 'n'; static int _qid = 0;",
+       "#endif",
+       "uchar",
+       "do_transit(Trans *t, short II)",
+       "{      uchar _m = 0;",
+       "       int  tt = (int) ((P0 *)this)->_p;",
+       "#ifdef M_LOSS",
+       "       uchar delta_m = 0;",
+       "#endif",
+       "#ifdef EVENT_TRACE",
+       "       short oboq = boq;",
+       "       uchar ot = (uchar)  ((P0 *)this)->_t;",
+       "       if (ot == EVENT_TRACE) boq = -1;",
+               "#define continue       { boq = oboq; return 0; }",
+       "#else",
+               "#define continue       return 0",
+               "#ifdef SEPARATE",
+       "       uchar ot = (uchar)  ((P0 *)this)->_t;",
+               "#endif",
+       "#endif",
+       "#include FORWARD_MOVES",
+       "P999:",
+       "#ifdef EVENT_TRACE",
+       "       if (ot == EVENT_TRACE) boq = oboq;",
+       "#endif",
+       "       return _m;",
+       "#undef continue",
+       "}",
+
+       "#ifdef EVENT_TRACE",
+       "void",
+       "require(char tp, int qid)",
+       "{      Trans *t;",
+       "       _tp = tp; _qid = qid;",
+       "",
+       "       if (now._event != endevent)",
+       "       for (t = trans[EVENT_TRACE][now._event]; t; t = t->nxt)",
+       "       {       if (do_transit(t, EVENT_TRACE))",
+       "               {       now._event = t->st;",
+       "                       reached[EVENT_TRACE][t->st] = 1;",
+       "#ifdef VERBOSE",
+       "       printf(\"       event_trace move to -> %%d\\n\", t->st);",
+       "#endif",
+       "#ifndef BFS",
+               "#ifndef NP",
+       "                       if (accpstate[EVENT_TRACE][now._event])",
+       "                               (trpt+1)->o_pm |= 2;",
+               "#else",
+       "                       if (progstate[EVENT_TRACE][now._event])",
+       "                               (trpt+1)->o_pm |= 4;",
+               "#endif",
+       "#endif",
+       "#ifdef NEGATED_TRACE",
+       "                       if (now._event == endevent)",
+       "                       {",
+               "#ifndef BFS",
+       "                               depth++; trpt++;",
+               "#endif",
+       "                               uerror(\"event_trace error (all events matched)\");",
+               "#ifndef BFS",
+       "                               trpt--; depth--;",
+               "#endif",
+       "                               break;",
+       "                       }",
+       "#endif",
+       "                       for (t = t->nxt; t; t = t->nxt)",
+       "                       {       if (do_transit(t, EVENT_TRACE))",
+       "                                Uerror(\"non-determinism in event-trace\");",
+       "                       }",
+       "                       return;",
+       "               }",
+       "#ifdef VERBOSE",
+       "                else",
+       "       printf(\"       event_trace miss '%%c' -- %%d, %%d, %%d\\n\",",
+       "                       tp, qid, now._event, t->forw);",
+       "#endif",
+       "       }",
+       "#ifdef NEGATED_TRACE",
+       "       now._event = endevent; /* only 1st try will count -- fixed 4.2.6 */",
+       "#else",        
+               "#ifndef BFS",
+       "       depth++; trpt++;",
+               "#endif",
+       "       uerror(\"event_trace error (no matching event)\");",
+               "#ifndef BFS",
+       "       trpt--; depth--;",
+               "#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",
+       "       if (pid == iam)",
+       "               Uerror(\"used: enabled(pid=thisproc)\");",
+       "       if (pid < 0 || pid >= (int) now._nr_pr)",
+       "               return 0;",
+       "       this = pptr(pid);",
+       "       TstOnly = 1;",
+       "       tt = (int) ((P0 *)this)->_p;",
+       "       ot = (uchar) ((P0 *)this)->_t;",
+       "       for (t = trans[ot][tt]; t; t = t->nxt)",
+       "               if (do_transit(t, (short) pid))",
+       "               {       res = 1;",
+       "                       break;",
+       "               }",
+       "       TstOnly = 0;",
+       "       this = othis;",
+       "       return res;",
+       "}",
+       "#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= %%6.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)",
+       "{",
+       "#if NCORE>1",
+       "       enter_critical(GLOBAL_LOCK);    /* 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);",
+       "#endif",
+       "       printf(\"Memory= %%9.3f\\t\", memcnt/1048576.);",
+       "       snap_time();",
+       "       fflush(stdout);",
+       "#if NCORE>1",
+       "       leave_critical(GLOBAL_LOCK);",
+       "#endif",
+       "}",
+
+       "#ifdef SC",
+       "void",
+       "stack2disk(void)",
+       "{",
+       "       if (!stackwrite",
+       "       &&  (stackwrite = creat(stackfile, TMODE)) < 0)",
+       "               Uerror(\"cannot create stackfile\");",
+       "",
+       "       if (write(stackwrite, trail, DDD*sizeof(Trail))",
+       "       !=  DDD*sizeof(Trail))",
+       "               Uerror(\"stackfile write error -- disk is full?\");",
+       "",
+       "       memmove(trail, &trail[DDD], (HHH-DDD+2)*sizeof(Trail));",
+       "       memset(&trail[HHH-DDD+2], 0, (omaxdepth - HHH + DDD - 2)*sizeof(Trail));",
+       "       CNT1++;",
+       "}",
+       "void",
+       "disk2stack(void)",
+       "{      long have;",
+       "",
+       "       CNT2++;",
+       "       memmove(&trail[DDD], trail, (HHH-DDD+2)*sizeof(Trail));",
+       "",
+       "       if (!stackwrite",
+       "       ||  lseek(stackwrite, -DDD* (off_t) sizeof(Trail), SEEK_CUR) == -1)",
+       "               Uerror(\"disk2stack lseek error\");",
+       "",
+       "       if (!stackread",
+       "       &&  (stackread = open(stackfile, 0)) < 0)",
+       "               Uerror(\"cannot open stackfile\");",
+       "",
+       "       if (lseek(stackread, (CNT1-CNT2)*DDD* (off_t) sizeof(Trail), SEEK_SET) == -1)",
+       "               Uerror(\"disk2stack lseek error\");",
+       "",
+       "       have = read(stackread, trail, DDD*sizeof(Trail));",
+       "       if (have !=  DDD*sizeof(Trail))",
+       "               Uerror(\"stackfile read error\");",
+       "}",
+       "#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 */
+       "               return noptr;",
+       "       else",
+       "               return (uchar *) pptr(x);",
+       "}",
+       "int qs_empty(void);",
+
+       "/*",
+       " * 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",
+       " * 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",
+       " */",
+       "#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",
+       "",
+       "void",
+       "new_state(void)",
+       "{      Trans *t;",
+       "       uchar _n, _m, ot;",
+       "#ifdef RANDOMIZE",
+       "       short ooi, eoi;",
+       "#endif",
+       "#ifdef M_LOSS",
+       "       uchar delta_m = 0;",
+       "#endif",
+       "       short II, JJ = 0, kk;",
+       "       int tt;",
+"#ifdef REVERSE",
+       "       short From = BASE, To = now._nr_pr-1;",
+"#else",
+       "       short From = now._nr_pr-1, To = BASE;",
+"#endif",
+       "Down:",
+       "#ifdef CHECK",
+       "       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 SCHED",
+       "       if (depth > 0)",
+       "       {       trpt->sched_limit = (trpt-1)->sched_limit;",
+       "       } else",
+       "       {       trpt->sched_limit = 0;",
+       "       }",
+       "#endif",
+
+       "#ifdef SC",
+       "       if (depth > hiwater)",
+       "       {       stack2disk();",
+       "               maxdepth += DDD;",
+       "               hiwater += DDD;",
+       "               trpt -= DDD;",
+       "               if(verbose)",
+       "               printf(\"zap %%d: %%d (maxdepth now %%d)\\n\",",
+       "                       CNT1, hiwater, maxdepth);",
+       "       }",
+       "#endif",
+
+       "       trpt->tau &= ~(16|32|64); /* make sure these are off */",
+       "#if defined(FULLSTACK) && defined(MA)",
+       "       trpt->proviso = 0;",
+       "#endif",
+       "#ifdef NSUCC",
+       "       trpt->n_succ = 0;",
+       "#endif",
+       "#if NCORE>1",
+       "       if (mem_hand_off())",
+       "       {",
+       "#if SYNC",
+       "               (trpt+1)->o_n = 1;      /* not a deadlock: as below  */",
+       "#endif",
+       "#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\");",
+       "               }",
+       "               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)) || NCORE>1",
+       "       /* if atomic or rv move, carry forward previous state */",
+       "       trpt->ostate = (trpt-1)->ostate;",      /* was: = (struct H_el *) 0;*/
+       "#endif",
+       "#ifdef VERI",
+       "       if ((trpt->tau&4) || ((trpt-1)->tau&128))",
+       "#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 ((now._a_t&1) && depth > A_depth)",
+       "               {       if (!memcmp((char *)&A_Root, ",
+       "                               (char *)&now, vsize))",
+       "                       {",
+       "                               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",
+       "                       printf(\"not seed\\n\");",
+               "#endif",
+       "               }",
+       "#endif",
+       "               if (!(trpt->tau&8)) /* if no atomic move */",
+       "               {",
+       "#ifdef BITSTATE",
+               "#ifdef CNTRSTACK",     /* -> bitstate, reduced, safety */
+       "                       II = bstore((char *)&now, vsize);",
+       "                       trpt->j6 = j1; trpt->j7 = j2;",
+       "                       JJ = LL[j1] && LL[j2];",
+               "#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 */
+               "#endif",
+       "#else",
+               "#ifdef MA",
+       "                       II = gstore((char *)&now, vsize, 0);",
+                       "#ifndef FULLSTACK",
+       "                       JJ = II;",
+                       "#else",
+       "                       JJ = (II == 2)?1:0;",
+                       "#endif",
+               "#else",
+       "                       II = hstore((char *)&now, vsize);",
+                       "#ifdef FULLSTACK",
+       "                       JJ = (II == 2)?1:0;",
+                       "#endif",
+               "#endif",
+       "#endif",
+       "                       kk = (II == 1 || II == 2);",
+
+                               /* II==0 new state */
+                               /* II==1 old state */
+                               /* II==2 on current dfs stack */
+                               /* II==3 on 1st dfs stack */
+       "#ifndef SAFETY",
+
+               "#if NCORE==1 || defined (SEP_STATE)",  /* or else we don't know which stack its on */
+       "                       if (II == 2 && ((trpt->o_pm&2) || ((trpt-1)->o_pm&2)))",
+       "               #ifndef NOFAIR",
+       "#if 0",
+       "                       if (!fairness || ((now._a_t&1) && now._cnt[1] == 1)) /* 5.1.4 */",
+       "#else",
+       "                       if (a_cycles && !fairness) /* 5.1.6 -- example by Hirofumi Watanabe */",
+       "#endif",
+       "               #endif",
+       "                       {",
+       "                               II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */",
+                       "#ifdef VERBOSE",
+       "                               printf(\"state match on dfs stack\\n\");",
+                       "#endif",
+       "                               goto same_case;",
+       "                       }",
+               "#endif",
+
+               "#if defined(FULLSTACK) && defined(BITSTATE)",
+       "                       if (!JJ && (now._a_t&1) && depth > A_depth)",
+       "                       {       int oj1 = j1;",
+       "                               uchar o_a_t = now._a_t;",
+       "                               now._a_t &= ~(1|16|32);", /* 1st stack  */
+       "                               if (onstack_now())",      /* changes j1 */
+       "                               {       II = 3;",
+               "#ifdef VERBOSE",
+       "                                       printf(\"state match on 1st dfs stack\\n\");",
+               "#endif",
+       "                               }",
+       "                               now._a_t = o_a_t;",     /* restore */
+       "                               j1 = oj1;",
+       "                       }",
+               "#endif",
+       "                       if (II == 3 && a_cycles && (now._a_t&1))",
+       "                       {",
+               "#ifndef NOFAIR",
+       "                          if (fairness && now._cnt[1] > 1)     /* was != 0 */",
+       "                          {",
+               "#ifdef VERBOSE",
+       "                               printf(\"\tfairness count non-zero\\n\");",
+               "#endif",
+       "                               II = 0;", /* treat as new state */
+       "                          } else",
+               "#endif",
+       "                          {",
+               "#ifndef BITSTATE",
+       "                               nShadow--;",
+               "#endif",
+       "same_case:                     if (Lstate) depthfound = Lstate->D;",
+               "#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;",
+       "                          }",
+       "                       }",
+       "#endif",
+
+       "#ifndef NOREDUCE",
+               "#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 */",
+       "#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",
+       "                       if (II)",
+       "                       {       truncs++;",
+       "#if NCORE>1 && defined(FULL_TRAIL)",
+       "                               if (upto > 0)",
+       "                               {       Pop_Stack_Tree();",
+       "                                       if (depth == 0)",
+       "                                       {       return;",
+       "                               }       }",
+       "#endif",
+       "                               goto Up;",
+       "                       }",
+       "                       if (!kk)",
+       "                       {       static long sdone = (long) 0; long ndone;",
+       "                               nstates++;",
+       "#if defined(ZAPH) && defined(BITSTATE)",
+       "                               zstates += (double) hfns;",
+       "#endif",
+       "                               ndone = (unsigned long) (nstates/((double) 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)",
+       "                               if (write(svfd, (uchar *) &now, vprefix) != vprefix)",
+       "                               {       fprintf(efd, \"writing %%s.svd failed\\n\", PanSource);",
+       "                                       wrapup();",
+       "                               }",
+       "#endif",
+       "#if defined(MA) && defined(W_XPT)",
+       "                               if ((unsigned long) nstates%%W_XPT == 0)",
+       "                               {       void w_xpoint(void);",
+       "                                       w_xpoint();",
+       "                               }",
+       "#endif",
+       "                       }",
+
+       "#if defined(FULLSTACK) || defined(CNTRSTACK)",
+       "                       onstack_put();",
+               "#ifdef DEBUG2",
+               "#if defined(FULLSTACK) && !defined(MA)",
+       "                       printf(\"%%d: putting %%u (%%d)\\n\", depth,",
+       "                               trpt->ostate, ",
+       "                               (trpt->ostate)?trpt->ostate->tagged:0);",
+               "#else",
+       "                       printf(\"%%d: putting\\n\", depth);",
+               "#endif",
+               "#endif",
+       "#else",
+       "       #if NCORE>1",
+       "                       trpt->ostate = Lstate;",
+       "       #endif",
+       "#endif",
+       "       }       }",
+
+
+       "       if (depth > mreached)",
+       "               mreached = depth;",
+       "#ifdef VERI",
+       "       if (trpt->tau&4)",
+       "#endif",
+       "       trpt->tau &= ~(1|2);    /* timeout and -request off */",
+       "       _n = 0;",
+       "#if SYNC",
+       "       (trpt+1)->o_n = 0;",
+       "#endif",
+       "#ifdef VERI",
+       "       if (now._nr_pr == 0)    /* claim terminated */",
+       "               uerror(\"end state in claim reached\");",
+       "       check_claim(((P0 *)pptr(0))->_p);",
+       "Stutter:",
+       "       if (trpt->tau&4)        /* must make a claimmove */",
+       "       {",
+
+       "#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",
+       "       printf(\"%%3d: fairness Rule 3.: _a_t = %%d\\n\",",
+       "               depth, now._a_t);",
+               "#endif",
+       "               }",
+       "#endif",
+
+       "               II = 0;         /* never */",
+       "               goto Veri0;",
+       "       }",
+       "#endif",
+       "#ifndef NOREDUCE",
+       "       /* Look for a process with only safe transitions */",
+       "       /* (special rules apply in the 2nd dfs) */",
+       "       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",
+       "       &&  (!(now._a_t&1)",
+       "           ||  (a_cycles &&",
+       " #ifndef BITSTATE",
+               "#ifdef MA",
+                       "#ifdef VERI",
+       "                !((trpt-1)->proviso))",
+                       "#else",
+       "               !(trpt->proviso))",
+                       "#endif",
+               "#else",
+                       "#ifdef VERI",
+       "                (trpt-1)->ostate &&",
+       "               !(((char *)&((trpt-1)->ostate->state))[0] & 128))", /* proviso bit in _a_t */
+                       "#else",
+       "               !(((char *)&(trpt->ostate->state))[0] & 128))",
+                       "#endif",
+               "#endif",
+       " #else",
+               "#ifdef VERI",
+       "               (trpt-1)->ostate &&",
+       "               (trpt-1)->ostate->proviso == 0)",
+               "#else",
+       "               trpt->ostate->proviso == 0)",
+               "#endif",
+       " #endif",
+       "          ))",
+       "#endif", /* SAFETY */
+       "",
+"#ifdef REVERSE",
+       "       for (II = From; II <= To; II++)",
+"#else",
+       "       for (II = From; II >= To; II--)",
+"#endif",
+       "       {",
+       "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; /* the process preselected */",
+       "#ifdef NIBIS",
+       "                       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;",
+       "#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 */",
+       "#ifndef NOFAIR",
+       "       if (fairness && boq == -1",
+               "#ifdef VERI",
+       "       && (!(trpt->tau&4) && !((trpt-1)->tau&128))",
+               "#endif",
+       "       && !(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))",
+       "                       {       /* Accepting state */",
+       "                               now._a_t |= 2;",
+       "                               now._cnt[now._a_t&1] = now._nr_pr + 1;", /* NEW +1 */
+       "                               trpt->o_pm |= 8;",
+               "#ifdef DEBUG",
+       "       printf(\"%%3d: 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)",
+       "                       {       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\",",
+       "               depth, now._a_t);",
+               "#endif",
+       "       }       }       }",
+       "#endif",
+       "",
+"#ifdef REVERSE",
+       "       for (II = From; II <= To; II++)",
+"#else",
+       "       for (II = From; II >= To; II--)",
+"#endif",
+       "       {",
+       "#if SYNC",
+       "               /* no rendezvous with same proc */",
+       "               if (boq != -1 && trpt->pr == II) continue;",
+       "#endif",
+       "#ifdef SCHED",
+       "               /* limit max nr of interleavings */",
+       "               if (From != To", /* not a PO or atomic move */
+       "               &&  depth > 0",  /* there is a prior move */
+       "       #ifdef VERI",
+       "               &&  II != 0", /* never claim can always move */
+       "       #endif",
+       "               &&  (trpt-1)->pr != II", /* context switch */
+       "               &&   trpt->sched_limit >= sched_max)",
+       "               {       continue;",
+       "               }",
+       "#endif",
+       "#ifdef VERI",
+       "Veri0:",
+       "#endif",
+       "               this = pptr(II);",
+       "               tt = (int) ((P0 *)this)->_p;",
+       "               ot = (uchar) ((P0 *)this)->_t;",
+
+       "#ifdef NIBIS",
+       "               /* don't repeat a previous preselected expansion */",
+       "               /* could hit this if reduction proviso was false */",
+       "               t = trans[ot][tt];",
+       "               if (!(trpt->tau&4)",    /* not claim */
+       "               && !(trpt->tau&1)",     /* not timeout */
+       "               && !(trpt->tau&32)",    /* not preselected */
+       "               && (t->atom & 8)",      /* local */
+       "               && boq == -1",          /* not inside rendezvous */
+       "               && From != To)",        /* not inside atomic seq */
+       "               {       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 */",
+       "               }       }",
+       "#endif",
+       "               trpt->o_pm &=  ~1; /* no move in this pid yet */",
+       "#ifdef EVENT_TRACE",
+       "               (trpt+1)->o_event = now._event;",
+       "#endif",
+       "               /* Fairness: Cnt++ when Cnt == II */",
+       "#ifndef NOFAIR",
+       "               trpt->o_pm &= ~64; /* didn't apply rule 2 */",
+       "               if (fairness",
+       "               && boq == -1",  /* not mid rv - except rcv - NEW 3.0.8 */
+       "               && !(trpt->o_pm&32)",   /* Rule 2 not in effect */
+       "               && (now._a_t&2)",       /* A-bit is set */
+       "               &&  now._cnt[now._a_t&1] == II+2)",
+       "               {       now._cnt[now._a_t&1] -= 1;",
+               "#ifdef VERI",
+       "                       /* claim need not participate */",
+       "                       if (II == 1)",
+       "                               now._cnt[now._a_t&1] = 1;",
+               "#endif",
+               "#ifdef DEBUG",
+       "               printf(\"%%3d: proc %%d fairness \", depth, II);",
+       "               printf(\"Rule 2: --cnt to %%d (%%d)\\n\",",
+       "                       now._cnt[now._a_t&1], now._a_t);",
+               "#endif",
+       "                       trpt->o_pm |= (32|64);",
+       "               }",
+       "#endif",
+       "#ifdef HAS_PROVIDED",
+       "               if (!provided(II, ot, tt, t)) continue;",
+       "#endif",
+       "               /* check all trans of proc II - escapes first */",
+       "#ifdef HAS_UNLESS",
+       "               trpt->e_state = 0;",
+       "#endif",
+       "               (trpt+1)->pr = (uchar) II;",    /* for uerror */
+       "               (trpt+1)->st = tt;",
+
+       "#ifdef RANDOMIZE",
+       "               for (ooi = eoi = 0, t = trans[ot][tt]; t; t = t->nxt, ooi++)",
+       "               {       if (strcmp(t->tp, \"else\") == 0)",
+       "                       {       eoi++;",
+       "                               break;",
+       "               }       }",
+       "               if (eoi > 0)",
+       "               {       t = trans[ot][tt];",
+       "       #ifdef VERBOSE",
+       "                       printf(\"randomizer: suppressed, saw else\\n\");",
+       "       #endif",
+       "               } else",
+       "               {       eoi = rand()%%ooi;",
+       "       #ifdef VERBOSE",
+       "                       printf(\"randomizer: skip %%d in %%d\\n\", eoi, ooi);",
+       "       #endif",
+       "                       for (t = trans[ot][tt]; t; t = t->nxt)",
+       "                               if (eoi-- <= 0) break;",
+       "               }",
+       "domore:",
+       "               for ( ; t && ooi > 0; t = t->nxt, ooi--)",
+       "#else", /* ie dont randomize */
+       "               for (t = trans[ot][tt]; t; t = t->nxt)",
+       "#endif",
+       "               {",
+       "#ifdef HAS_UNLESS",
+       "                       /* exploring all transitions from",
+       "                        * a single escape state suffices",
+       "                        */",
+       "                       if (trpt->e_state > 0",
+       "                       &&  trpt->e_state != t->e_trans)",
+       "                       {",
+               "#ifdef DEBUG",
+       "               printf(\"skip 2nd escape %%d (did %%d before)\\n\",",
+       "                       t->e_trans, trpt->e_state);",
+               "#endif",
+       "                               break;",
+       "                       }",
+       "#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;",
+       "#endif",
+       "#ifdef SCHED",
+       "                       if (depth > 0",
+       "       #ifdef VERI",
+       "                       && II != 0",
+       "       #endif",
+       "                       && (trpt-1)->pr != II)",
+       "                       {       trpt->sched_limit = 1 + (trpt-1)->sched_limit;",
+       "                       }",
+       "#endif",
+       "                       if (boq == -1)",
+               "#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;",      /* CTL */
+       "                               trpt->o_pm |= 1; /* we moved */",
+       "                       }",
+               "#else",
+       "                               trpt->o_pm |= 1; /* we moved */",
+               "#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)",
+       "       cpu_printf(\"%%3d: proc %%d exec %%d \\n\", depth, II, t->t_id);",
+               "#else",
+       "       cpu_printf(\"%%3d: 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\":\"\",",
+       "                               (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",
+               "#endif",
+               "#ifdef RANDOMIZE",
+       "                       cpu_printf(\"\\t(randomizer %%d)\\n\", ooi);",
+               "#endif",
+       "#endif",
+
+       "#ifdef HAS_LAST",
+       "#ifdef VERI",
+       "                       if (II != 0)",
+       "#endif",
+       "                               now._last = II - BASE;",
+       "#endif",
+       "#ifdef HAS_UNLESS",
+       "                       trpt->e_state = t->e_trans;",
+       "#endif",
+
+       "                       depth++; trpt++;",
+       "                       trpt->pr = (uchar) II;",
+       "                       trpt->st = tt;",
+       "                       trpt->o_pm &= ~(2|4);",
+       "                       if (t->st > 0)",
+       "                       {       ((P0 *)this)->_p = t->st;",
+       "/*     moved down              reached[ot][t->st] = 1; */",
+       "                       }",
+       "#ifndef SAFETY",
+       "                       if (a_cycles)",
+       "                       {",
+               "#if (ACCEPT_LAB>0 && !defined(NP)) || (PROG_LAB>0 && defined(HAS_NP))",
+       "                               int ii;",
+               "#endif",
+               "#define P__Q   ((P0 *)pptr(ii))",
+               "#if ACCEPT_LAB>0",
+                       "#ifdef NP",
+       "                               /* state 1 of np_ claim is accepting */",
+       "                               if (((P0 *)pptr(0))->_p == 1)",
+       "                                       trpt->o_pm |= 2;",
+                       "#else",
+       "                               for (ii = 0; ii < (int) now._nr_pr; ii++)",
+       "                               { if (accpstate[P__Q->_t][P__Q->_p])",
+       "                                 {     trpt->o_pm |= 2;",
+       "                                       break;",
+       "                               } }",
+                       "#endif",
+               "#endif",
+               "#if defined(HAS_NP) && PROG_LAB>0",
+       "                               for (ii = 0; ii < (int) now._nr_pr; ii++)",
+       "                               { if (progstate[P__Q->_t][P__Q->_p])",
+       "                                 {     trpt->o_pm |= 4;",
+       "                                       break;",
+       "                               } }",
+               "#endif",
+               "#undef P__Q",
+       "                       }",
+       "#endif",
+       "                       trpt->o_t  =  t; trpt->o_n  = _n;",
+       "                       trpt->o_ot = ot; trpt->o_tt = tt;",
+       "                       trpt->o_To = To; trpt->o_m  = _m;",
+       "                       trpt->tau = 0;",
+       "#ifdef RANDOMIZE",
+       "                       trpt->oo_i = ooi;",
+       "#endif",
+       "                       if (boq != -1 || (t->atom&2))",
+       "                       {       trpt->tau |= 8;",
+       "#ifdef VERI",
+       "                               /* atomic sequence in claim */",
+       "                               if((trpt-1)->tau&4)",
+       "                                       trpt->tau |= 4;",
+       "                               else",
+       "                                       trpt->tau &= ~4;",
+       "                       } else",
+       "                       {       if ((trpt-1)->tau&4)",
+       "                                       trpt->tau &= ~4;",
+       "                               else",
+       "                                       trpt->tau |= 4;",
+       "                       }",
+       "                       /* if claim allowed timeout, so */",
+       "                       /* does the next program-step: */",
+       "                       if (((trpt-1)->tau&1) && !(trpt->tau&4))",
+       "                               trpt->tau |= 1;",
+       "#else",
+       "                       } else",
+       "                               trpt->tau &= ~8;",
+       "#endif",
+       "                       if (boq == -1 && (t->atom&2))",
+       "                       {       From = To = II; nlinks++;",
+       "                       } else",
+"#ifdef REVERSE",
+       "                       {       From = BASE; To = now._nr_pr-1;",
+"#else",
+       "                       {       From = now._nr_pr-1; To = BASE;",
+"#endif",
+       "                       }",
+       "#if NCORE>1 && defined(FULL_TRAIL)",
+       "                       if (upto > 0)",
+       "                       {       Push_Stack_Tree(II, t->t_id);",
+       "                       }",
+       "#endif",
+       "                       goto Down;      /* pseudo-recursion */",
+       "Up:",
+       "#ifdef CHECK",
+       "                       cpu_printf(\"%%d: Up - %%s\\n\", depth,",
+       "                               (trpt->tau&4)?\"claim\":\"program\");",
+       "#endif",
+       "#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);",
+       "                       }",
+       "#endif",
+
+       "#ifndef NOFAIR",
+       "                       if (trpt->o_pm&128)     /* fairness alg */",
+       "                       {       now._cnt[now._a_t&1] = trpt->bup.oval;",
+       "                               _n = 1; trpt->o_pm &= ~128;",
+       "                               depth--; trpt--;",
+               "#if defined(VERBOSE) || defined(CHECK)",
+       "       printf(\"%%3d: reversed fairness default move\\n\", depth);",
+               "#endif",
+       "                               goto Q999;",
+       "                       }",
+       "#endif",
+
+       "#ifdef HAS_LAST",
+       "#ifdef VERI",
+       "                       { int d; Trail *trl;",
+       "                         now._last = 0;",
+       "                         for (d = 1; d < depth; d++)",
+       "                         {     trl = getframe(depth-d); /* was (trpt-d) */",
+       "                               if (trl->pr != 0)",
+       "                               { now._last = trl->pr - BASE;",
+       "                                 break;",
+       "                       } }     }",
+       "#else",
+       "                       now._last = (depth<1)?0:(trpt-1)->pr;",
+       "#endif",
+       "#endif",
+       "#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);",
+       "                       To = trpt->o_To; _m  = trpt->o_m;",
+       "#ifdef RANDOMIZE",
+       "                       ooi = trpt->oo_i;",
+       "#endif",
+       "#ifdef INLINE_REV",
+       "                       _m = do_reverse(t, II, _m);",
+       "#else",
+       "#include REVERSE_MOVES",
+       "R999:                  /* jumps here when done */",
+       "#endif",
+
+       "#ifdef VERBOSE",
+       "                       cpu_printf(\"%%3d: proc %%d reverses %%d, %%d to %%d\\n\",",
+       "                               depth, II, t->forw, tt, t->st);",
+       "                       cpu_printf(\"\\t%%s [abit=%%d,adepth=%%d,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;",  /* pass upward */
+       "#ifdef SAFETY",
+       "                       if ((trpt->tau&8)       /* rv or atomic */",
+       "                       &&  (trpt->tau&64))",
+       "                               (trpt-1)->tau |= 64;",
+       "#endif",
+       "#endif",
+       "                       depth--; trpt--;",
+       "",
+       "#ifdef NSUCC",
+       "                       trpt->n_succ++;",
+       "#endif",
+       "#ifdef NIBIS",
+       "                       (trans[ot][tt])->om = _m; /* head of list */",
+       "#endif",
+
+       "                       /* 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][tt] = 1;",
+       "                       }",
+       "#ifdef HAS_UNLESS",
+       "                       else trpt->e_state = 0; /* undo */",
+       "#endif",
+
+       "                       if (_m>_n||(_n>3&&_m!=0)) _n=_m;",
+       "                       ((P0 *)this)->_p = tt;",
+       "               } /* all options */",
+
+       "#ifdef RANDOMIZE",
+       "               if (!t && ooi > 0)",    /* means we skipped some initial options */
+       "               {       t = trans[ot][tt];",
+       "       #ifdef VERBOSE",
+       "                       printf(\"randomizer: continue for %%d more\\n\", ooi);",
+       "       #endif",
+       "                       goto domore;",
+       "               }",
+       "       #ifdef VERBOSE",
+       "                 else",
+       "                       printf(\"randomizer: done\\n\");",
+       "       #endif",
+       "#endif",
+
+       "#ifndef NOFAIR",
+       "               /* Fairness: undo Rule 2 */",
+       "               if ((trpt->o_pm&32)",/* rule 2 was applied */
+       "               &&  (trpt->o_pm&64))",/* by this process II */
+       "               {       if (trpt->o_pm&1)",/* it didn't block */
+       "                       {",
+               "#ifdef VERI",
+       "                               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(\"undo Rule 2, cnt=%%d, _a_t=%%d\\n\",",
+       "                       now._cnt[now._a_t&1], now._a_t);",
+               "#endif",
+       "                               trpt->o_pm &= ~(32|64);",
+       "                       } else",        /* process blocked  */
+       "                       {       if (_n > 0)", /* a prev proc didn't */
+       "                               {",     /* start over */
+       "                                       trpt->o_pm &= ~64;",
+"#ifdef REVERSE",
+       "                                       II = From-1;", /* after loop incr II == From */
+"#else",
+       "                                       II = From+1;", /* after loop decr II == From */
+"#endif",
+       "               }       }       }",
+       "#endif",
+
+       "#ifdef VERI",
+       "               if (II == 0) break;     /* never claim */",
+       "#endif",
+       "       } /* all processes */",
+
+       "#ifdef NSUCC",
+       "       tally_succ(trpt->n_succ);",
+       "#endif",
+
+       "#ifdef SCHED",
+       "       if (_n == 0     /* no process could move */",
+       " #ifdef VERI",
+       "       &&  II != 0",
+       " #endif",
+       "       &&  depth > 0",
+       "       &&  trpt->sched_limit >= sched_max)",
+       "       {       _n = 1; /* not a deadlock */",
+       "       }",
+       "#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)",
+       "                       now._cnt[now._a_t&1] = 2;",
+               "#endif",
+       "               now._cnt[now._a_t&1] += 1;",
+               "#ifdef VERBOSE",
+       "               printf(\"%%3d: 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",
+       /* 12/97 non-progress cycles cannot be created
+        * by stuttering extension, here or elsewhere
+        */
+       "       if (fairness",
+       "       &&  _n == 0             /* nobody moved */",
+               "#ifdef VERI",
+               "       && !(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",
+               "#endif",
+               "#ifndef NOREDUCE",
+               "       /* see below  */",
+               "       && !((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))",
+               "#endif",
+       "       && now._cnt[now._a_t&1] > 0)    /* needed more procs */",
+       "       {       depth++; trpt++;",
+       "               trpt->o_pm |= 128 | ((trpt-1)->o_pm&(2|4));",
+       "               trpt->bup.oval = now._cnt[now._a_t&1];",
+       "               now._cnt[now._a_t&1] = 1;",
+               "#ifdef VERI",
+       "               trpt->tau = 4;",
+               "#else",
+       "               trpt->tau = 0;",
+               "#endif",
+"#ifdef REVERSE",
+       "               From = BASE; To = now._nr_pr-1;",
+"#else",
+       "               From = now._nr_pr-1; To = BASE;",
+"#endif",
+               "#if defined(VERBOSE) || defined(CHECK)",
+       "               printf(\"%%3d: fairness default move \", depth);",
+       "               printf(\"(all procs block)\\n\");",
+               "#endif",
+       "               goto Down;",
+       "       }",
+"#endif",
+       "Q999:  /* returns here with _n>0 when done */;",
+
+       "       if (trpt->o_pm&8)",
+       "       {       now._a_t &= ~2;",
+       "               now._cnt[now._a_t&1] = 0;",
+       "               trpt->o_pm &= ~8;",
+               "#ifdef VERBOSE",
+       "               printf(\"%%3d: fairness undo Rule 1, _a_t=%%d\\n\",",
+       "                       depth, now._a_t);",
+               "#endif",
+       "       }",
+       "       if (trpt->o_pm&16)",
+       "       {       now._a_t |= 2;",                /* restore a-bit */
+       "               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\",",
+       "                       depth, now._a_t);",
+               "#endif",
+       "       }",
+       "#endif",
+
+       "#ifndef NOREDUCE",
+"#ifdef SAFETY",
+       "#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",
+"#ifdef REVERSE",
+       "       {       From = BASE; To = now._nr_pr-1;",
+"#else",
+       "       {       From = now._nr_pr-1; To = BASE;",
+"#endif",
+               "#ifdef DEBUG",
+       "       printf(\"%%3d: proc %%d UnSelected (_n=%%d, tau=%%d)\\n\", ",
+       "       depth, II+1, _n, trpt->tau);",
+               "#endif",
+       "               _n = 0; trpt->tau &= ~(16|32|64);",
+"#ifdef REVERSE",
+       "               if (II <= To)   /* II already decremented */",
+"#else",
+       "               if (II >= BASE) /* II already decremented */",
+"#endif",
+       "                       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",
+       "               if (a_cycles && (trpt->tau&16))",
+       "               {       if (!(now._a_t&1))",
+       "                       {",
+               "#ifdef DEBUG",
+       "       printf(\"%%3d: setting proviso bit\\n\", depth);",
+               "#endif",
+       "#ifndef BITSTATE",
+               "#ifdef MA",
+                       "#ifdef VERI",
+       "                       (trpt-1)->proviso = 1;",
+                       "#else",
+       "                       trpt->proviso = 1;",
+                       "#endif",
+               "#else",
+                       "#ifdef VERI",
+       "                       if ((trpt-1)->ostate)",
+       "                       ((char *)&((trpt-1)->ostate->state))[0] |= 128;",
+                       "#else",
+       "                       ((char *)&(trpt->ostate->state))[0] |= 128;",
+                       "#endif",
+               "#endif",
+       "#else",
+               "#ifdef VERI",
+       "                       if ((trpt-1)->ostate)",
+       "                       (trpt-1)->ostate->proviso = 1;",
+               "#else",
+       "                       trpt->ostate->proviso = 1;",
+               "#endif",
+       "#endif",
+"#ifdef REVERSE",
+       "                               From = BASE; To = now._nr_pr-1;",
+"#else",
+       "                               From = now._nr_pr-1; To = BASE;",
+"#endif",
+       "                               _n = 0; trpt->tau &= ~(16|32|64);",
+       "                               goto Again; /* do full search */",
+       "                       } /* else accept reduction */",
+       "               } else",
+"#ifdef REVERSE",
+       "               {       From = BASE; To = now._nr_pr-1;",
+"#else",
+       "               {       From = now._nr_pr-1; To = BASE;",
+"#endif",
+       "                       _n = 0; trpt->tau &= ~(16|32|64);",
+"#ifdef REVERSE",
+       "                       if (II <= To)   /* already decremented */",
+"#else",
+       "                       if (II >= BASE) /* already decremented */",
+"#endif",
+       "                               goto Resume;",
+       "                       else",
+       "                               goto Again;",
+       "       }       }",
+       "/* #endif */",
+"#endif",
+       "#endif",
+
+       "       if (_n == 0 || ((trpt->tau&4) && (trpt->tau&2)))",
+       "       {",
+               "#ifdef DEBUG",
+       "               cpu_printf(\"%%3d: no move [II=%%d, tau=%%d, boq=%%d]\\n\",",
+       "                       depth, II, trpt->tau, boq);",
+               "#endif",
+       "#if SYNC",
+       "               /* ok if a rendez-vous fails: */",
+       "               if (boq != -1) goto Done;",
+       "#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;",
+
+       "               if ((trpt->tau&8) && !(trpt->tau&4))",
+       "               {       trpt->tau &= ~(1|8);",
+       "                       /* 1=timeout, 8=atomic */",
+"#ifdef REVERSE",
+       "                       From = BASE; To = now._nr_pr-1;",
+"#else",
+       "                       From = now._nr_pr-1; To = BASE;",
+"#endif",
+               "#ifdef DEBUG",
+       "               cpu_printf(\"%%3d: atomic step proc %%d unexecutable\\n\", depth, II+1);",
+               "#endif",
+       "#ifdef VERI",
+       "                       trpt->tau |= 4; /* switch to claim */",
+       "#endif",
+       "                       goto AllOver;",
+       "               }",
+
+       "#ifdef ETIM",
+       "               if (!(trpt->tau&1)) /* didn't try timeout yet */",
+       "               {",
+       "#ifdef VERI",
+       "                       if (trpt->tau&4)",
+       "                       {",
+               "#ifndef NTIM",
+       "                               if (trpt->tau&2) /* requested */",
+               "#endif",
+       "                               {       trpt->tau |=  1;",
+       "                                       trpt->tau &= ~2;",
+                               "#ifdef DEBUG",
+       "                               cpu_printf(\"%%d: timeout\\n\", depth);",
+                               "#endif",
+       "                                       goto Stutter;",
+       "                       }       }",
+       "                       else",
+       "                       {       /* only claim can enable timeout */",
+       "                               if ((trpt->tau&8)",
+       "                               &&  !((trpt-1)->tau&4))",
+       "/* blocks inside an atomic */          goto BreakOut;",
+                               "#ifdef DEBUG",
+       "                               cpu_printf(\"%%d: req timeout\\n\",",
+       "                                       depth);",
+                               "#endif",
+       "                               (trpt-1)->tau |= 2; /* request */",
+       "#if NCORE>1 && defined(FULL_TRAIL)",
+       "                               if (upto > 0)",
+       "                               {       Pop_Stack_Tree();",
+       "                               }",
+       "#endif",
+       "                               goto Up;",
+       "                       }",
+       "#else",
+
+                               "#ifdef DEBUG",
+       "                       cpu_printf(\"%%d: timeout\\n\", depth);",
+                               "#endif",
+       "                       trpt->tau |=  1;",
+       "                       goto Again;",
+       "#endif",
+       "               }",
+       "#endif",
+
+       /* old location of atomic block code */
+       "#ifdef VERI",
+       "BreakOut:",
+               "#ifndef NOSTUTTER",
+       "               if (!(trpt->tau&4))",
+       "               {       trpt->tau |= 4;   /* claim stuttering */",
+       "                       trpt->tau |= 128; /* stutter mark */",
+                               "#ifdef DEBUG",
+       "                       cpu_printf(\"%%d: claim stutter\\n\", depth);",
+                               "#endif",
+       "                       goto Stutter;",
+       "               }",
+               "#else",
+       "               ;",
+               "#endif",
+       "#else",
+       "               if (!noends && !a_cycles && !endstate())",
+       "               {       depth--; trpt--;        /* new 4.2.3 */",
+       "                       uerror(\"invalid end state\");",
+       "                       depth++; trpt++;",
+       "               }",
+               "#ifndef NOSTUTTER",
+       "               else if (a_cycles && (trpt->o_pm&2)) /* new 4.2.4 */",
+       "               {       depth--; trpt--;",
+       "                       uerror(\"accept stutter\");",
+       "                       depth++; trpt++;",
+       "               }",
+               "#endif",
+       "#endif",
+       "       }",
+       "Done:",
+       "       if (!(trpt->tau&8))     /* not in atomic seqs */",
+       "       {",
+       "#ifndef SAFETY",
+       "               if (_n != 0",           /* we made a move */
+               "#ifdef VERI",
+       "               /* --after-- a program-step, i.e., */",
+       "               /* after backtracking a claim-step */",
+       "               && (trpt->tau&4)",
+       "               /* with at least one running process */",
+       "               /* unless in a stuttered accept state */",
+       "               && ((now._nr_pr > 1) || (trpt->o_pm&2))",
+               "#endif",
+       "               && !(now._a_t&1))",     /* not in 2nd DFS */
+       "               {",
+               "#ifndef NOFAIR",
+       "                       if (fairness)", /* implies a_cycles */
+       "                       {",
+                       "#ifdef VERBOSE",
+       "                       cpu_printf(\"Consider check %%d %%d...\\n\",",
+       "                               now._a_t, now._cnt[0]);",
+                       "#endif",
+#if 0
+               the a-bit is set, which means that the fairness
+               counter is running -- it was started in an accepting state.
+               we check that the counter reached 1, which means that all
+               processes moved least once.
+               this means we can start the search for cycles -
+               to be able to return to this state, we should be able to
+               run down the counter to 1 again -- which implies a visit to
+               the accepting state -- even though the Seed state for this
+               search is itself not necessarily accepting
+#endif
+       "                               if ((now._a_t&2) /* A-bit */",
+       "                               &&  (now._cnt[0] == 1))",
+       "                                       checkcycles();",
+       "                       } else",
+               "#endif",
+       "                       if (a_cycles && (trpt->o_pm&2))",
+       "                               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();",
+       "               }",
+       "#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",
+       "       }",
+       "       if (depth > 0)",
+       "       {",
+       "#if NCORE>1 && defined(FULL_TRAIL)",
+       "               if (upto > 0)",
+       "               {       Pop_Stack_Tree();",
+       "               }",
+       "#endif",
+       "               goto Up;",
+       "       }",
+       "}\n",
+       "#else",
+       "void new_state(void) { /* place holder */ }",
+       "#endif",       /* BFS */
+       "",
+       "void",
+       "assert(int a, char *s, int ii, int tt, Trans *t)",
+       "{",
+       "       if (!a && !noasserts)",
+       "       {       char bad[1024];",
+       "               strcpy(bad, \"assertion violated \");",
+       "               if (strlen(s) > 1000)",
+       "               {       strncpy(&bad[19], (const char *) s, 1000);",
+       "                       bad[1019] = '\\0';",
+       "               } else",
+       "                       strcpy(&bad[19], s);",
+       "               uerror(bad);",
+       "       }",
+       "}",
+       "#ifndef NOBOUNDCHECK",
+       "int",
+       "Boundcheck(int x, int y, int a1, int a2, Trans *a3)",
+       "{",
+       "       assert((x >= 0 && x < y), \"- invalid array index\",",
+       "               a1, a2, a3);",
+       "       return x;",
+       "}",
+       "#endif",
+       "void",
+       "wrap_stats(void)",
+       "{",
+       "       if (nShadow>0)",
+       "         printf(\"%%9.8g states, stored (%%g visited)\\n\",",
+       "                       nstates - nShadow, nstates);",
+       "       else",
+       "         printf(\"%%9.8g states, stored\\n\", nstates);",
+       "#ifdef BFS",
+       "#if SYNC",
+       "       printf(\"       %%8g nominal states (- rv and atomic)\\n\", nstates-midrv-nlinks+revrv);",
+       "       printf(\"       %%8g rvs succeeded\\n\", midrv-failedrv);",
+       "#else",
+       "       printf(\"       %%8g nominal states (stored-atomic)\\n\", nstates-nlinks);",
+       "#endif",
+       "#ifdef DEBUG",
+       "       printf(\"       %%8g midrv\\n\", midrv);",
+       "       printf(\"       %%8g failedrv\\n\", failedrv);",
+       "       printf(\"       %%8g revrv\\n\", revrv);",
+       "#endif",
+       "#endif",
+       "       printf(\"%%9.8g states, matched\\n\", truncs);",
+       "#ifdef CHECK",
+       "       printf(\"%%9.8g matches within stack\\n\",truncs2);",
+       "#endif",
+       "       if (nShadow>0)",
+       "       printf(\"%%9.8g transitions (= visited+matched)\\n\",",
+       "               nstates+truncs);",
+       "       else",
+       "       printf(\"%%9.8g transitions (= stored+matched)\\n\",",
+       "               nstates+truncs);",
+       "       printf(\"%%9.8g atomic steps\\n\", nlinks);",
+       "       if (nlost) printf(\"%%g lost messages\\n\", (double) nlost);",
+       "",
+       "#ifndef BITSTATE",
+       "       printf(\"hash conflicts: %%9.8g (resolved)\\n\", hcmp);",
+       "       #ifndef AUTO_RESIZE",
+       "       if (hcmp > (double) (1<<ssize))",
+       "       {       printf(\"hint: increase hashtable-size (-w) to reduce runtime\\n\");",
+       "       }       /* in multi-core: also reduces lock delays on access to hashtable */",
+       "       #endif",
+       "#else",
+               "#ifdef CHECK",
+               "       printf(\"%%8g states allocated for dfs stack\\n\", ngrabs);",
+               "#endif",
+       "       if (udmem)",
+       "       printf(\"\\nhash factor: %%4g (best if > 100.)\\n\\n\",",
+       "               (double)(((double) udmem) * 8.0) / (double) nstates);",
+       "       else",
+       "       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));",
+       "       } else",
+#endif
+       "       printf(\"total bits available: %%8g (-w%%d)\\n\",",
+       "               ((double) (ONE_L << (ssize-4)) * 16.0), ssize);",
+       "       #endif",
+       "#endif",
+"#ifdef BFS_DISK",
+       "       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;",
+       "       #endif",
+       "#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);",
+       "#endif",
+       "       printf(\"\\n(%%s)\\n\", SpinVersion);",
+       "       if (!done) printf(\"Warning: Search not completed\\n\");",
+       "#ifdef SC",
+       "       (void) unlink((const char *)stackfile);",
+       "#endif",
+       "#if NCORE>1",
+       "       if (a_cycles)",
+       "       {       printf(\"       + Multi-Core (NCORE=%%d)\\n\", NCORE);",
+       "       } else",
+       "       {       printf(\"       + Multi-Core (NCORE=%%d -z%%d)\\n\", NCORE, z_handoff);",
+       "       }",
+       "#endif",
+       "#ifdef BFS",
+       "       printf(\"       + Using Breadth-First Search\\n\");",
+       "#endif",
+       "#ifndef NOREDUCE",
+       "       printf(\"       + Partial Order Reduction\\n\");",
+       "#endif",
+       "#ifdef REVERSE",
+       "       printf(\"       + Reverse Depth-First Search Order\\n\");",
+       "#endif",
+       "#ifdef T_REVERSE",
+       "       printf(\"       + Reverse Transition Ordering\\n\");",
+       "#endif",
+       "#ifdef RANDOMIZE",
+       "       printf(\"       + Randomized Transition Ordering\\n\");",
+       "#endif",
+       "#ifdef SCHED",
+       "       printf(\"       + Scheduling Restriction (-DSCHED=%%d)\\n\", sched_max);",
+       "#endif",
+#if 0
+       "#ifdef Q_PROVISO",
+       "       printf(\"       + Queue Proviso\\n\");",
+       "#endif",
+#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\", PanSource);",
+       "  #endif",
+       "#endif",
+       "#ifdef CHECK",
+       "  #ifdef FULLSTACK",
+       "       printf(\"       + FullStack Matching\\n\");",
+       "  #endif",
+       "  #ifdef CNTRSTACK",
+       "       printf(\"       + CntrStack Matching\\n\");",
+       "  #endif",
+       "#endif",
+       "#ifdef BITSTATE",
+       "       printf(\"\\nBit statespace search for:\\n\");",
+       "#else",
+               "#ifdef HC",
+       "       printf(\"\\nHash-Compact %%d search for:\\n\", HC);",
+               "#else",
+       "       printf(\"\\nFull statespace search for:\\n\");",
+               "#endif",
+       "#endif",
+       "#ifdef EVENT_TRACE",
+       "#ifdef NEGATED_TRACE",
+       "       printf(\"\tnotrace assertion  \t+\\n\");",
+       "#else",
+       "       printf(\"\ttrace assertion    \t+\\n\");",
+       "#endif",
+       "#endif",
+       "#ifdef VERI",
+       "       printf(\"\tnever claim         \t+\\n\");",
+       "       printf(\"\tassertion violations\t\");",
+       "       if (noasserts)",
+       "               printf(\"- (disabled by -A flag)\\n\");",
+       "       else",
+       "               printf(\"+ (if within scope of claim)\\n\");",
+       "#else",
+               "#ifdef NOCLAIM",
+       "       printf(\"\tnever claim         \t- (not selected)\\n\");",
+               "#else",
+       "       printf(\"\tnever claim         \t- (none specified)\\n\");",
+               "#endif",
+       "       printf(\"\tassertion violations\t\");",
+       "       if (noasserts)",
+       "               printf(\"- (disabled by -A flag)\\n\");",
+       "       else",
+       "               printf(\"+\\n\");",
+       "#endif",
+       "#ifndef SAFETY",
+               "#ifdef NP",
+       "       printf(\"\tnon-progress cycles \t\");",
+               "#else",
+       "       printf(\"\tacceptance   cycles \t\");",
+               "#endif",
+       "       if (a_cycles)",
+       "               printf(\"+ (fairness %%sabled)\\n\",",
+       "                       fairness?\"en\":\"dis\");",
+       "       else printf(\"- (not selected)\\n\");",
+       "#else",
+       "       printf(\"\tcycle checks       \t- (disabled by -DSAFETY)\\n\");",
+       "#endif",
+       "#ifdef VERI",
+       "       printf(\"\tinvalid end states\t- \");",
+       "       printf(\"(disabled by \");",
+       "       if (noends)",
+       "               printf(\"-E flag)\\n\\n\");",
+       "       else",
+       "               printf(\"never claim)\\n\\n\");",
+       "#else",
+       "       printf(\"\tinvalid end states\t\");",
+       "       if (noends)",
+       "               printf(\"- (disabled by -E flag)\\n\\n\");",
+       "       else",
+       "               printf(\"+\\n\\n\");",
+       "#endif",
+       "       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);",
+       "               if (maxgs+a_cycles+2 < MA)",
+       "               printf(\"MA stats: -DMA=%%d is sufficient\\n\",",
+       "                       maxgs+a_cycles+2);",
+       "               dfa_stats();",
+       "       }",
+       "#endif",
+       "       wrap_stats();",
+       "#ifdef CHECK",
+       "       printf(\"stackframes: %%d/%%d\\n\\n\", smax, svmax);",
+       "       printf(\"stats: fa %%d, fh %%d, zh %%d, zn %%d - \",",
+       "               Fa, Fh, Zh, Zn);",
+       "       printf(\"check %%d holds %%d\\n\", Ccheck, Cholds);",
+       "       printf(\"stack stats: puts %%d, probes %%d, zaps %%d\\n\",",
+       "               PUT, PROBE, ZAPS);",
+       "#else",
+       "       printf(\"\\n\");",
+       "#endif",
+       "",
+       "#if defined(BITSTATE) || !defined(NOCOMP)",
+       "       nr1 = (nstates-nShadow)*",
+       "             (double)(hmax+sizeof(struct H_el)-sizeof(unsigned));",
+               "#ifdef BFS",
+       "       nr2 = 0.0;",
+               "#else",
+       "       nr2 = (double) ((maxdepth+3)*sizeof(Trail));",
+               "#endif",
+
+               "#ifndef BITSTATE",
+                       "#if !defined(MA) || defined(COLLAPSE)",
+       "       nr3 = (double) (ONE_L<<ssize)*sizeof(struct H_el *);",
+                       "#endif",
+               "#else",
+#ifndef POWOW
+       "       if (udmem)",
+       "               nr3 = (double) (udmem);",
+       "       else",
+#endif
+       "       nr3 = (double) (ONE_L<<(ssize-3));",
+                       "#ifdef CNTRSTACK",
+       "       nr5 = (double) (ONE_L<<(ssize-3));",
+                       "#endif",
+                       "#ifdef FULLSTACK",
+       "       nr5 = (double) (maxdepth*sizeof(struct H_el *));",
+                       "#endif",
+               "#endif",
+       "       nr4 = (double) (svmax * (sizeof(Svtack) + hmax))",
+       "           + (double) (smax * (sizeof(Stack) + Maxbody));",
+               "#ifndef MA",
+       "       if (mverbose || 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(\"%%9.3f\tequivalent memory usage for states\",",
+       "                       nr1/1048576.); /* 1024*1024=1048576 */",
+       "               printf(\" (stored*(State-vector + overhead))\\n\");",
+       "       #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",
+#ifndef POWOW
+       "               if (udmem)",
+       "               printf(\"%%9.3f\tmemory used for hash array (-M%%ld)\\n\",",
+       "                       nr3/1048576., udmem/(1024L*1024L));",
+       "               else",
+#endif
+       "               printf(\"%%9.3f\tmemory used for hash array (-w%%d)\\n\",",
+       "                       nr3/1048576., ssize);",
+       "               if (nr5 > 0.0)",
+       "               printf(\"%%9.3f\tmemory used for bit stack\\n\",",
+       "                       nr5/1048576.);",
+       "               remainder = remainder - nr3 - nr5;",
+               "#else",
+       "               printf(\"%%9.3f\tactual memory usage for states\",",
+       "                       tmp_nr/1048576.);",
+       "               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\",",
+       "                       (long int) sizeof(struct H_el)-sizeof(unsigned));",
+       "               }",
+                       "#endif",
+                       "#if !defined(MA) || defined(COLLAPSE)",
+       "               printf(\"%%9.3f\tmemory used for hash table (-w%%d)\\n\",",
+       "                       nr3/1048576., ssize);",
+       "               remainder -= nr3;",
+                       "#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.);",
+       "               if (fragment > 1048576.)",
+       "               printf(\"%%9.3f\tmemory lost to fragmentation\\n\",",
+       "                       fragment/1048576.);",
+       "               printf(\"%%9.3f\ttotal actual memory usage\\n\\n\",",
+       "                       memcnt/1048576.);",
+       "       }",
+               "#ifndef MA",
+       "       else",
+               "#endif",
+       "#endif",
+               "#ifndef MA",
+       "               printf(\"%%9.3f\tmemory usage (Mbyte)\\n\\n\",",
+       "                       memcnt/1048576.);",
+               "#endif",
+       "#ifdef COLLAPSE",
+       "       printf(\"nr of templates: [ globals chans procs ]\\n\");",
+       "       printf(\"collapse counts: [ \");",
+       "       { int i; for (i = 0; i < 256+2; i++)",
+       "               if (ncomps[i] != 0)",
+       "                       printf(\"%%d \", ncomps[i]);",
+       "               printf(\"]\\n\");",
+       "       }",
+       "#endif",
+
+       "       if ((done || verbose) && !no_rck) do_reach();",
+       "#ifdef PEG",
+       "       { int i;",
+       "         printf(\"\\nPeg Counts (transitions executed):\\n\");",
+       "         for (i = 1; i < NTRANS; i++)",
+       "         {     if (peg[i]) putpeg(i, peg[i]);",
+       "       } }",
+       "#endif",
+       "#ifdef VAR_RANGES",
+       "       dumpranges();",
+       "#endif",
+       "#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",
+       "       pan_exit(0);",
+       "}\n",
+       "void",
+       "stopped(int arg)",
+       "{      printf(\"Interrupted\\n\");",
+       "#if NCORE>1",
+       "       was_interrupted = 1;",
+       "#endif",
+       "       wrapup();",
+       "       pan_exit(0);",
+       "}",
+       "",
+       "#ifdef SFH",
+       "/*",
+       " * 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__)) || defined(__WATCOMC__) \\",
+       "       || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)",
+       "               #define get16bits(d) (*((const uint16_t *) (d)))",
+       "       #endif",
+       "",
+       "       #ifndef get16bits",
+       "               #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\\",
+       "                       +(uint32_t)(((const uint8_t *)(d))[0]) )",
+       "       #endif",
+       "",
+       "void",
+       "d_sfh(const char *s, int len)",
+       "{      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;",
+       "}",
+       "#endif", /* SFH */
+       "",
+       "#include <stdint.h>", /* uint32_t etc. */
+       "#if defined(HASH64) || defined(WIN64)",
+       "/* 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);  \\",
+       "  c -= a; c -= b; c ^= (b>>8);  \\",
+       "  a -= b; a -= c; a ^= (c>>38); \\",
+       "  b -= c; b -= a; b ^= (a<<23); \\",
+       "  c -= a; c -= b; c ^= (b>>5);  \\",
+       "  a -= b; a -= c; a ^= (c>>35); \\",
+       "  b -= c; b -= a; b ^= (a<<49); \\",
+       "  c -= a; c -= b; c ^= (b>>11); \\",
+       "  a -= b; a -= c; a ^= (c>>12); \\",
+       "  b -= c; b -= a; b ^= (a<<18); \\",
+       "  c -= a; c -= b; c ^= (b>>22); \\",
+       "}",
+       "#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 -= 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; \\",
+       "}",
+       "",
+       "#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)",
+       "{      uint8_t  *bp;",
+       "#if defined(HASH64) || defined(WIN64)",
+       "       uint64_t a = 0, b, c, n;",
+       "       uint64_t *k = (uint64_t *) kb;",
+       "#else",
+       "       uint32_t a, b, c, n;",
+       "       uint32_t *k = (uint32_t *) kb;",
+       "#endif",
+       "       /* extend to multiple of words, if needed */",
+       "       n = nbytes/WS;  /* nr of words */",
+       "       a = nbytes - (n*WS);",
+       "       if (a > 0)",
+       "       {       n++;",
+       "               bp = kb + nbytes;",
+       "               switch (a) {",
+       "               case 3: *bp++ = 0; /* fall thru */",
+       "               case 2: *bp++ = 0; /* fall thru */",
+       "               case 1: *bp   = 0;",
+       "               case 0: break;",
+       "       }       }",
+       "#if defined(HASH64) || defined(WIN64)",
+       "       b = HASH_CONST[HASH_NR];",
+       "       c = 0x9e3779b97f4a7c13LL; /* arbitrary value */",
+       "       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);",
+       "#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];",
+       "       case 0: break;",
+       "       }",
+       "       final(a,b,c);",
+       "#endif",
+       "       j1 = c&nmask; j3 = a&7;      /* 1st bit */",
+       "       j2 = b&nmask; j4 = (a>>3)&7; /* 2nd bit */",
+       "       K1 = c; K2 = b;",
+       "}",
+       "",
+       "void",
+       "s_hash(uchar *cp, int om)",
+       "{",
+       "#if defined(SFH)",
+       "       d_sfh((const char *) cp, om); /* sets K1 */",
+       "#else",
+       "       d_hash(cp, om); /* sets K1 etc */",
+       "#endif",
+       "#ifdef BITSTATE",
+       "       if (S_Tab == H_tab)",   /* state stack in bitstate search */
+       "               j1 = K1 %% omaxdepth;",
+       "       else",
+       "#endif", /* if (S_Tab != H_Tab) */
+       "               if (ssize < 8*WS)",
+       "                       j1 = K1&mask;",
+       "               else",
+       "                       j1 = K1;",
+       "}",
+       "#ifndef RANDSTOR",
+       "int *prerand;",
+       "void",
+       "inirand(void)",
+       "{      int i;",
+       "       srand(123);     /* fixed startpoint */",
+       "       prerand = (int *) emalloc((omaxdepth+3)*sizeof(int));",
+       "       for (i = 0; i < omaxdepth+3; i++)",
+       "               prerand[i] = rand();",
+       "}",
+       "int",
+       "pan_rand(void)",
+       "{      if (!prerand) inirand();",
+       "       return prerand[depth];",
+       "}",
+       "#endif",
+       "",
+       "void",
+       "set_masks(void)        /* 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 = ((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);",
+       "       }",
+       "}",
+       "",
+       "static long reclaim_size;",
+       "static char *reclaim_mem;",
+       "#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)",
+       "#if NCORE>1",
+       "       #error cannot combine AUTO_RESIZE with NCORE>1 yet",
+       "#endif",
+       "static struct H_el **N_tab;",
+       "void",
+       "reverse_capture(struct H_el *p)",
+       "{      if (!p) return;",
+       "       reverse_capture(p->nxt);",
+       "       /* last element of list moves first */",
+       "       /* to preserve list-order */",
+       "       j2 = p->m_K1;",
+       "       if (ssize < 8*WS) /* probably always true */",
+       "       {       j2 &= mask;",
+       "       }",
+       "       p->nxt = N_tab[j2];",
+       "       N_tab[j2] = p;",
+       "}",
+       "void",
+       "resize_hashtable(void)",
+       "{",
+       "       if (WS == 4 && ssize >= 27 - 1)",
+       "       {       return; /* canot increase further */",
+       "       }",
+       "",
+       "       ssize += 2; /* 4x size */",
+       "",
+       "       printf(\"pan: resizing hashtable to -w%%d.. \", ssize);",
+       "",
+       "       N_tab = (struct H_el **)",
+       "               emalloc((ONE_L<<ssize)*sizeof(struct H_el *));",
+       "",
+       "       set_masks();    /* they changed */",
+       "",
+       "       for (j1 = 0; j1 < (ONE_L << (ssize - 2)); j1++)",
+       "       {       reverse_capture(H_tab[j1]);",
+       "       }",
+       "       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",
+       "",
+       "int",
+       "main(int argc, char *argv[])",
+       "{      void to_compile(void);\n",
+       "       efd = stderr;   /* default */",
+       "#ifdef BITSTATE",
+       "       bstore = 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",
+       "               case 'a': a_cycles = 1; break;",
+               "#endif",
+       "#endif",
+       "               case 'A': noasserts = 1; break;",
+       "               case 'b': bounded = 1; break;",
+       "#ifdef HAS_CODE",
+       "               case 'C': coltrace = 1; goto samething;",
+       "#endif",
+       "               case 'c': upto  = atoi(&argv[1][2]); break;",
+       "               case 'd': state_tables++; break;",
+       "               case 'e': every_error = 1; Nr_Trails = 1; break;",
+       "               case 'E': noends = 1; break;",
+       "#ifdef SC",
+       "               case 'F': if (strlen(argv[1]) > 2)",
+       "                               stackfile = &argv[1][2];",
+       "                         break;",
+       "#endif",
+       "#if !defined(SAFETY) && !defined(NOFAIR)",
+       "               case 'f': fairness = 1; break;",
+       "#endif",
+       "#ifdef HAS_CODE",
+       "               case 'g': gui = 1; goto samething;",
+       "#endif",
+       "               case 'h': if (!argv[1][2]) usage(efd); else",
+       "                         HASH_NR = atoi(&argv[1][2])%%33; break;",
+       "               case 'I': iterative = 2; every_error = 1; break;",
+       "               case 'i': 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 SCHED",
+       "               case 'L': sched_max = atoi(&argv[1][2]); break;",
+       "#endif",
+       "#ifndef SAFETY",
+               "#ifdef NP",
+       "               case 'l': a_cycles = 1; break;",
+               "#else",
+       "               case 'l': fprintf(efd, \"error: -l disabled\");",
+       "                         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;",
+       "#else",
+       "               case 'M': case 'G':",
+       "                         fprintf(stderr, \"-M and -G affect only -DBITSTATE\\n\");",
+       "                         break;",
+       "#endif",
+#endif
+       "               case 'm': maxdepth = atoi(&argv[1][2]); break;",
+       "               case 'n': no_rck = 1; break;",
+       "               case 'P': readtrail = 1; onlyproc = atoi(&argv[1][2]);",
+       "                         if (argv[2][0] != '-') /* check next arg */",
+       "                         {     trailfilename = argv[2];",
+       "                               argc--; argv++; /* skip next arg */",
+       "                         }",
+       "                         break;",
+       "#ifdef SVDUMP",
+       "               case 'p': vprefix = atoi(&argv[1][2]); break;",
+       "#endif",
+       "#if NCORE==1",
+       "               case 'Q': quota = (double) 60.0 * (double) atoi(&argv[1][2]); break;",
+       "#endif",
+       "               case 'q': strict = 1; break;",
+       "               case 'R': Nrun = atoi(&argv[1][2]); break;",
+       "#ifdef HAS_CODE",
+       "               case 'r':",
+       "samething:               readtrail = 1;",
+       "                         if (isdigit(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 'S': silent = 1; goto samething;",
+       "#endif",
+       "#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': 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]); break;",
+       "               case 'Y': signoff = 1; break;",
+       "               case 'X': efd = stdout; 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 that 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 (iterative && TMODE != 0666)",
+       "       {       TMODE = 0666;",
+       "               fprintf(efd, \"warning: -T ignored when -i or -I is used\\n\");",
+       "       }",
+       "#if defined(HASH32) && !defined(SFH)",
+       "       if (WS > 4)",
+       "       {       fprintf(efd, \"strong warning: compiling -DHASH32 on a 64-bit machine\\n\");",
+       "               fprintf(efd, \" without -DSFH can slow down performance a lot\\n\");",
+       "       }",
+       "#endif",
+       "#if defined(WIN32) || defined(WIN64)",
+       "       if (TMODE == 0666)",
+       "               TMODE = _S_IWRITE | _S_IREAD;",
+       "       else",
+       "               TMODE = _S_IREAD;",
+       "#endif",
+       "#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",
+       "       #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 BITSTATE",
+       "       if (hfns <= 0)",
+       "       {       hfns = 1;",
+       "               fprintf(efd, \"warning: using -k%%d as minimal usable value\\n\", hfns);",
+       "       }",
+       "#endif",
+       "       omaxdepth = maxdepth;",
+       "#ifdef BITSTATE",
+       "       if (WS == 4 && ssize > 34)",    /* 32-bit word size */
+       "       {       ssize = 34;",
+       "               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",
+       " */",
+       "       }",
+       "#else",
+       "       if (WS == 4 && ssize > 27)",
+       "       {       ssize = 27;",
+       "               fprintf(efd, \"warning: using -w%%d as max usable value\\n\", ssize);",
+       "/*",
+       " *     for emalloc, the lookup table size multiplies by 4 for the pointers",
+       " *     the largest power of 2 that can be represented in a ulong is 1^31",
+       " *     hence the largest number of lookup table slots is 31-4 = 27",
+       " */",
+       "       }",
+
+       "#endif",
+       "#ifdef SC",
+       "       hiwater = HHH = maxdepth-10;",
+       "       DDD = HHH/2;",
+       "       if (!stackfile)",
+       "       {       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\");",
+       "               pan_exit(1);",
+       "       }",
+       "#endif",
+
+       "#if (defined(R_XPT) || defined(W_XPT)) && !defined(MA)",
+       "       #warning -DR_XPT and -DW_XPT assume -DMA (ignored)",
+       "#endif",
+
+       "       if (iterative && a_cycles)",
+       "       fprintf(efd, \"warning: -i or -I work for safety properties only\\n\");",
+
+       "#ifdef BFS",
+       "       #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 REACH",
+       "               #warning -DREACH is redundant when -DBFS is used",
+       "       #endif",
+       "#endif",
+       "#if defined(MERGED) && defined(PEG)",
+       "       #error to use -DPEG use: spin -o3 -a",
+       "#endif",
+       "#ifdef HC",
+       "       #ifdef SFH", /* cannot happen -- undef-ed in this case */
+       "               #error cannot combine -DHC and -DSFH",
+       "               /* use of NOCOMP is the real reason */",
+       "       #else",
+       "               #ifdef NOCOMP",
+       "               #error cannot combine -DHC and -DNOCOMP",
+       "               #endif",
+       "       #endif",
+       "       #ifdef BITSTATE",
+       "               #error cannot combine -DHC and -DBITSTATE",
+       "       #endif",
+       "#endif",
+       "#if defined(SAFETY) && defined(NP)",
+       "       #error cannot combine -DNP and -DBFS or -DSAFETY",
+       "#endif",
+       "#ifdef MA",
+       "       #ifdef BITSTATE",
+       "               #error cannot combine -DMA and -DBITSTATE",
+       "       #endif",
+       "       #if MA <= 0",
+       "               #error usage: -DMA=N with N > 0 and N < VECTORSZ",
+       "       #endif",
+       "#endif",
+       "#ifdef COLLAPSE",
+       "       #ifdef BITSTATE",
+       "               #error cannot combine -DBITSTATE and -DCOLLAPSE",
+       "       #endif",
+       "       #ifdef SFH",
+       "               #error cannot combine -DCOLLAPSE and -DSFH",
+       "               /* use of NOCOMP is the real reason */",
+       "       #else",
+       "               #ifdef NOCOMP",
+       "               #error cannot combine -DCOLLAPSE and -DNOCOMP",
+       "               #endif",
+       "       #endif",
+       "#endif",
+       "       if (maxdepth <= 0 || ssize <= 1) usage(efd);",
+       "#if SYNC>0 && !defined(NOREDUCE)",
+       "       if (a_cycles && fairness)",
+       "       { fprintf(efd, \"error: p.o. reduction not compatible with \");",
+       "         fprintf(efd, \"fairness (-f) in models\\n\");",
+       "         fprintf(efd, \"       with rendezvous operations: \");",
+       "         fprintf(efd, \"recompile with -DNOREDUCE\\n\");",
+       "         pan_exit(1);",
+       "       }",
+       "#endif",
+       "#if defined(REM_VARS) && !defined(NOREDUCE)",
+       "       #warning p.o. reduction not compatible with remote varrefs (use -DNOREDUCE)",
+       "#endif",
+       "#if defined(NOCOMP) && !defined(BITSTATE)",
+       "       if (a_cycles)",
+       "       { fprintf(efd, \"error: use of -DNOCOMP voids -l and -a\\n\");",
+       "         pan_exit(1);",
+       "       }",
+       "#endif",
+
+       "#ifdef MEMLIM",
+       "       memlim = ((double) MEMLIM) * (double) (1<<20);  /* size in Mbyte */",
+       "#endif",
+
+       "#ifndef BITSTATE",
+       "       if (Nrun > 1) HASH_NR = Nrun - 1;",
+       "#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)",
+       "       {       fprintf(efd, \"error: no accept labels defined \");",
+       "               fprintf(efd, \"in model (for option -a)\\n\");",
+       "               usage(efd);",
+       "       }",
+       "       #endif",
+       "#endif",
+       "#ifndef NOREDUCE",
+       "       #ifdef 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",
+       "       #ifdef HAS_LAST",
+       "               #error use of _last requires -DNOREDUCE",
+       "       #endif",
+       "#endif",
+
+       "#if SYNC>0 && !defined(NOREDUCE)",
+       "       #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",
+       "#endif",
+       "#if SYNC>0 && defined(BFS)",
+       "       #warning use of rendezvous with BFS does not preserve all invalid endstates",
+       "#endif",
+       "#if !defined(REACH) && !defined(BITSTATE)",
+       "       if (iterative != 0 && a_cycles == 0)",
+       "       {       fprintf(efd, \"warning: -i and -I need -DREACH to work accurately\\n\");",
+       "       }",
+       "#endif",
+       "#if defined(BITSTATE) && defined(REACH)",
+       "       #warning -DREACH is voided by -DBITSTATE",
+       "#endif",
+       "#if defined(MA) && defined(REACH)",
+       "       #warning -DREACH is voided by -DMA",
+       "#endif",
+       "#if defined(FULLSTACK) && defined(CNTRSTACK)",
+       "       #error cannot combine -DFULLSTACK and -DCNTRSTACK",
+       "#endif",
+       "#if defined(VERI)",
+       "       #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 (!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",
+       "#ifndef SAFETY",
+       "       if (!a_cycles",
+       "       #ifdef HAS_CODE",
+       "       && !readtrail",
+       "       #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",
+       "       if (!a_cycles)",
+       "       {       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;",
+       "               /* -2 because first two uchars in now are masked */",
+       "               #endif",
+       "       }       }",
+       "       #endif",
+       "#endif",
+       "       signal(SIGINT, stopped);",
+       "       set_masks();",
+       "#ifdef BFS",
+       "       trail = (Trail *) emalloc(6*sizeof(Trail));",
+       "       trail += 3;",
+       "#else",
+       "       trail = (Trail *) emalloc((maxdepth+3)*sizeof(Trail));",
+       "       trail++;        /* protect trpt-1 refs at depth 0 */",
+       "#endif",
+       "#ifdef SVDUMP",
+       "       if (vprefix > 0)",
+       "       {       char nm[64];",
+       "               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);",
+       "#endif",
+       "#if SYNC>0 && ASYNC==0",
+       "       set_recvs();",
+       "#endif",
+       "       run();",
+       "       done = 1;",
+       "       wrapup();",
+       "       return 0;",
+       "}",    /* end of main() */
+       "",
+       "void",
+       "usage(FILE *fd)",
+       "{",
+       "       fprintf(fd, \"%%s\\n\", SpinVersion);",
+       "       fprintf(fd, \"Valid Options are:\\n\");",
+       "#ifndef SAFETY",
+               "#ifdef NP",
+       "       fprintf(fd, \"\t-a  -> is disabled by -DNP \");",
+       "       fprintf(fd, \"(-DNP compiles for -l only)\\n\");",
+               "#else",
+       "       fprintf(fd, \"\t-a  find acceptance cycles\\n\");",
+               "#endif",
+       "#else",
+       "       fprintf(fd, \"\t-a,-l,-f  -> are disabled by -DSAFETY\\n\");",
+       "#endif",
+       "       fprintf(fd, \"\t-A  ignore assert() violations\\n\");",
+       "       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 and stop\\n\");",
+       "       fprintf(fd, \"\t-e  create trails for all errors\\n\");",
+       "       fprintf(fd, \"\t-E  ignore invalid end states\\n\");",
+       "#ifdef SC",
+       "       fprintf(fd, \"\t-Ffile  use 'file' to store disk-stack\\n\");",
+       "#endif",
+       "#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-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\");",
+       "#ifdef BITSTATE",
+       "       fprintf(fd, \"\t-kN set N bits per state (defaults to 3)\\n\");",
+       "#endif",
+       "#ifdef SCHED",
+       "       fprintf(fd, \"\t-LN set scheduling restriction to N (default 10)\\n\");",
+       "#endif",
+       "#ifndef SAFETY",
+               "#ifdef NP",
+       "       fprintf(fd, \"\t-l  find non-progress cycles\\n\");",
+               "#else",
+       "       fprintf(fd, \"\t-l  find non-progress cycles -> \");",
+       "       fprintf(fd, \"disabled, requires \");",
+       "       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\");",
+       "       fprintf(fd, \"\t-n  no listing of unreached states\\n\");",
+       "#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-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-g  read and execute trail + msc gui support\\n\");",
+       "       fprintf(fd, \"\t-S  silent replay: only user defined printfs show\\n\");",
+       "#endif",
+       "#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\");",
+       "#endif",
+       "       fprintf(fd, \"\t-T  create trail files in read-only mode\\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)",
+       "{      char *tmp;",
+       "#ifdef MEMLIM",
+       "       if (memcnt+ (double) n > memlim) 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 *) -ONE_L)",
+"#endif",
+       "       {",
+       "#ifdef MEMLIM",
+       "err:",
+       "#endif",
+       "               printf(\"pan: out of memory\\n\");",
+       "#ifdef MEMLIM",
+       "               printf(\"\t%%g bytes used\\n\", memcnt);",
+       "               printf(\"\t%%g bytes more needed\\n\", (double) n);",
+       "               printf(\"\t%%g bytes limit\\n\",",
+       "                       memlim);",
+       "#endif",
+       "#ifdef COLLAPSE",
+       "               printf(\"hint: to reduce memory, recompile with\\n\");",
+               "#ifndef MA",
+       "               printf(\"  -DMA=%%d   # better/slower compression, or\\n\", hmax);",
+               "#endif",
+       "               printf(\"  -DBITSTATE # supertrace, approximation\\n\");",
+       "#else",
+       "#ifndef BITSTATE",
+       "               printf(\"hint: to reduce memory, recompile with\\n\");",
+               "#ifndef HC",
+       "               printf(\"  -DCOLLAPSE # good, fast compression, or\\n\");",
+                       "#ifndef MA",
+       "               printf(\"  -DMA=%%d   # better/slower compression, or\\n\", hmax);",
+                       "#endif",
+       "               printf(\"  -DHC # hash-compaction, approximation\\n\");",
+               "#endif",
+       "               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;",
+       "       return tmp;",
+       "}",
+       "",
+       "#define CHUNK  (100*VECTORSZ)",
+       "",
+       "char *",
+       "emalloc(unsigned long 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) */
+       "       {       grow = (n < CHUNK) ? CHUNK : n;",
+#if 1
+       "               have = Malloc(grow);",
+#else
+       "               /* gcc's sbrk can give non-aligned result */",
+       "               grow += sizeof(void *); /* allow realignment */",
+       "               have = Malloc(grow);",
+       "               if (((unsigned) have)&(sizeof(void *)-1))",
+       "               {       have += (long) (sizeof(void *) ",
+       "                               - (((unsigned) have)&(sizeof(void *)-1)));",
+       "                       grow -= sizeof(void *);",
+       "               }",
+#endif
+       "               fragment += (double) left;",
+       "               left = grow;",
+       "       }",
+       "       tmp = have;",
+       "       have += (long) n;",
+       "       left -= (long) n;",
+       "       memset(tmp, 0, n);",
+       "       return tmp;",
+       "}",
+
+       "void",
+       "Uerror(char *str)",
+       "{      /* always fatal */",
+       "       uerror(str);",
+       "#if NCORE>1",
+       "       sudden_stop(\"Uerror\");",
+       "#endif",
+       "       wrapup();",
+       "}\n",
+       "#if defined(MA) && !defined(SAFETY)",
+       "int",
+       "Unwind(void)",
+       "{      Trans *t; uchar ot, _m; int tt; short II;",
+       "#ifdef VERBOSE",
+       "       int i;",
+       "#endif",
+       "       uchar oat = now._a_t;",
+       "       now._a_t &= ~(1|16|32);",
+       "       memcpy((char *) &comp_now, (char *) &now, vsize);",
+       "       now._a_t = oat;",
+       "Up:",
+       "#ifdef SC",
+       "       trpt = getframe(depth);",
+       "#endif",
+       "#ifdef VERBOSE",
+       "       printf(\"%%d     State: \", depth);",
+       "       for (i = 0; i < vsize; i++) printf(\"%%d%%s,\",",
+       "               ((char *)&now)[i], Mask[i]?\"*\":\"\");",
+       "       printf(\"\\n\");",
+       "#endif",
+       "#ifndef NOFAIR",
+       "       if (trpt->o_pm&128)     /* fairness alg */",
+       "       {       now._cnt[now._a_t&1] = trpt->bup.oval;",
+       "               depth--;",
+       "#ifdef SC",
+       "               trpt = getframe(depth);",
+       "#else",
+       "               trpt--;",
+       "#endif",
+       "               goto Q999;",
+       "       }",
+       "#endif",
+       "#ifdef HAS_LAST",
+       "#ifdef VERI",
+       "       { int d; Trail *trl;",
+       "         now._last = 0;",
+       "         for (d = 1; d < depth; d++)",
+       "         {     trl = getframe(depth-d); /* was trl = (trpt-d); */",
+       "               if (trl->pr != 0)",
+       "               { now._last = trl->pr - BASE;",
+       "                 break;",
+       "       } }     }",
+       "#else",
+       "       now._last = (depth<1)?0:(trpt-1)->pr;",
+       "#endif",
+       "#endif",
+       "#ifdef EVENT_TRACE",
+       "       now._event = trpt->o_event;",
+       "#endif",
+       "       if ((now._a_t&1) && depth <= A_depth)",
+       "       {       now._a_t &= ~(1|16|32);",
+       "               if (fairness) now._a_t |= 2;    /* ? */",
+       "               A_depth = 0;",
+       "               goto CameFromHere;      /* checkcycles() */",
+       "       }",
+       "       t  = trpt->o_t;",
+       "       ot = trpt->o_ot; II = trpt->pr;",
+       "       tt = trpt->o_tt; this = pptr(II);",
+       "       _m = do_reverse(t, II, trpt->o_m);",
+       "#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] <unwind>\\n\", ",
+       "               trpt->tau, (trpt-1)->tau);",
+       "#endif",
+       "       depth--;",
+       "#ifdef SC",
+       "       trpt = getframe(depth);",
+       "#else",
+       "       trpt--;",
+       "#endif",
+       "       /* reached[ot][t->st] = 1;      3.4.13 */",
+       "       ((P0 *)this)->_p = tt;",
+       "#ifndef NOFAIR",
+       "       if ((trpt->o_pm&32))",
+       "       {",
+               "#ifdef VERI",
+       "               if (now._cnt[now._a_t&1] == 0)",
+       "                       now._cnt[now._a_t&1] = 1;",
+               "#endif",
+       "               now._cnt[now._a_t&1] += 1;",
+       "       }",
+       "Q999:",
+       "       if (trpt->o_pm&8)",
+       "       {       now._a_t &= ~2;",
+       "               now._cnt[now._a_t&1] = 0;",
+       "       }",
+       "       if (trpt->o_pm&16)",
+       "               now._a_t |= 2;",
+       "#endif",
+       "CameFromHere:",
+       "       if (memcmp((char *) &now, (char *) &comp_now, vsize) == 0)",
+       "               return depth;",
+       "       if (depth > 0) goto Up;",
+       "       return 0;",
+       "}",
+       "#endif",
+       "static char unwinding;",
+       "void",
+       "uerror(char *str)",
+       "{      static char laststr[256];",
+       "       int is_cycle;",
+       "",
+       "       if (unwinding) return; /* 1.4.2 */",
+       "       if (strncmp(str, laststr, 254))",
+       "#if NCORE>1",
+       "       cpu_printf(\"pan: %%s (at depth %%ld)\\n\", str,",
+       "#else",
+       "       printf(\"pan: %%s (at depth %%ld)\\n\", str,",
+       "#endif",
+       "#if NCORE>1",
+       "               (nr_handoffs * z_handoff) + ",
+       "#endif",
+       "               ((depthfound==-1)?depth:depthfound));",
+       "       strncpy(laststr, str, 254);",
+       "       errors++;",
+       "#ifdef HAS_CODE",
+       "       if (readtrail) { wrap_trail(); return; }",
+       "#endif",
+       "       is_cycle = (strstr(str, \" cycle\") != (char *) 0);",
+       "       if (!is_cycle)",
+       "       {       depth++; trpt++;",      /* include failed step */
+       "       }",
+       "       if ((every_error != 0)",
+       "       ||  errors == upto)",
+       "       {",
+       "#if defined(MA) && !defined(SAFETY)",
+       "               if (is_cycle)",
+       "               {       int od = depth;",
+       "                       unwinding = 1;",
+       "                       depthfound = Unwind();",
+       "                       unwinding = 0;",
+       "                       depth = od;",
+       "               }",
+       "#endif",
+       "#if NCORE>1",
+       "               writing_trail = 1;",
+       "#endif",
+"#ifdef BFS",
+       "               if (depth > 1) trpt--;",
+       "               nuerror(str);",
+       "               if (depth > 1) trpt++;",
+"#else",
+       "               putrail();",
+"#endif",
+       "#if defined(MA) && !defined(SAFETY)",
+       "               if (strstr(str, \" cycle\"))",
+       "               {       if (every_error)",
+       "                       printf(\"sorry: MA writes 1 trail max\\n\");",
+       "                       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",
+       "       if (iterative != 0 && maxdepth > 0)",
+       "       {       maxdepth = (iterative == 1)?(depth-1):(depth/2);",
+       "               warned = 1;",
+       "               printf(\"pan: reducing search depth to %%ld\\n\",",
+       "                       maxdepth);",
+       "       } else",
+"#endif",
+       "       if (errors >= upto && upto != 0)",
+       "       {",
+       "#if NCORE>1",
+       "               sudden_stop(\"uerror\");",
+       "#endif",
+       "               wrapup();",
+       "       }",
+       "       depthfound = -1;",
+       "}\n",
+       "int",
+       "xrefsrc(int lno, S_F_MAP *mp, int M, int i)",
+       "{      Trans *T; int j, retval=1;",
+       "       for (T = trans[M][i]; T; T = T->nxt)",
+       "       if (T && T->tp)",
+       "       {       if (strcmp(T->tp, \".(goto)\") == 0",
+       "               ||  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);",
+       "                               break;",
+       "                       }",
+       "               printf(\", state %%d\", i);",
+       "               if (strcmp(T->tp, \"\") != 0)",
+       "               {       char *q;",
+       "                       q = transmognify(T->tp);",
+       "                       printf(\", \\\"%%s\\\"\", q?q:\"\");",
+       "               } else if (stopstate[M][i])",
+       "                       printf(\", -end state-\");",
+       "               printf(\"\\n\");",
+       "               retval = 0; /* reported */",
+       "       }",
+       "       return retval;",
+       "}\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]);",
+       "       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++;",
+       "       printf(\"\t(%%d of %%d states)\\n\", N-1-m, N-1);",
+       "}",
+       "#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)",
+       "               {       write(fd, \"-1:-1:-1\\n\", 9);",
+       "       }       }",
+       "}",
+       "#endif", /* FULL_TRAIL */
+       "#endif", /* NCORE>1 */
+       "",
+       "void",
+       "putrail(void)",
+       "{      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));",
+       "#endif",
+       "#ifdef MERGED",
+       "       sprintf(snap, \"-4:-4:-4\\n\");",
+       "       write(fd, snap, strlen(snap));",
+       "#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);",
+       "               trl = getframe(i);",
+       "               if (!trl->o_t) continue;",
+       "               if (trl->o_pm&128) continue;",
+       "               sprintf(snap, \"%%ld:%%d:%%d\\n\", ",
+       "                       i, trl->pr, trl->o_t->t_id);",
+       "               j = strlen(snap);",
+       "               if (write(fd, snap, j) != j)",
+       "               {       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 */",
+       "{      if (!svtack->nxt)",
+       "       {  svtack->nxt = (Svtack *) emalloc(sizeof(Svtack));",
+       "          svtack->nxt->body = emalloc(vsize*sizeof(char));",
+       "          svtack->nxt->lst = svtack;",
+       "          svtack->nxt->m_delta = vsize;",
+       "          svmax++;",
+       "       } else if (vsize > svtack->nxt->m_delta)",
+       "       {  svtack->nxt->body = emalloc(vsize*sizeof(char));",
+       "          svtack->nxt->lst = svtack;",
+       "          svtack->nxt->m_delta = vsize;",
+       "          svmax++;",
+       "       }",
+       "       svtack = svtack->nxt;",
+       "#if SYNC",
+       "       svtack->o_boq = boq;",
+       "#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)",
+       "       c_stack((uchar *) &(svtack->c_stack[0]));",
+       "#endif",
+       "#ifdef DEBUG",
+       "       cpu_printf(\"%%d:       sv_save\\n\", depth);",
+       "#endif",
+       "}\n",
+       "void",
+       "sv_restor(void)        /* pop state vector from save stack */",
+       "{",
+       "       memcpy((char *)&now, svtack->body, svtack->o_delta);",
+       "#if SYNC",
+       "       boq = svtack->o_boq;",
+       "#endif",
+
+       "#if defined(C_States) && (HAS_TRACK==1)",
+       "#ifdef HAS_STACK",
+       "       c_unstack((uchar *) &(svtack->c_stack[0]));",
+       "#endif",
+       "       c_revert((uchar *) &(now.c_state[0]));",
+       "#endif",
+
+       "       if (vsize != svtack->o_delta)",
+       "               Uerror(\"sv_restor\");",
+       "       if (!svtack->lst)",
+       "               Uerror(\"error: v_restor\");",
+       "       svtack  = svtack->lst;",
+       "#ifdef DEBUG",
+       "       cpu_printf(\"   sv_restor\\n\");",
+       "#endif",
+       "}\n",
+       "void",
+       "p_restor(int h)",
+       "{      int i; char *z = (char *) &now;\n",
+       "       proc_offset[h] = stack->o_offset;",
+       "       proc_skip[h]   = (uchar) stack->o_skip;",
+       "#ifndef XUSAFE",
+       "       p_name[h] = stack->o_name;",
+       "#endif",
+       "#ifndef NOCOMP",
+       "       for (i = vsize + stack->o_skip; i > vsize; i--)",
+       "               Mask[i-1] = 1; /* align */",
+       "#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 (BASE > 0 && h > 0)",
+       "               ((P0 *)pptr(h))->_pid = h-BASE;",
+       "       else",
+       "               ((P0 *)pptr(h))->_pid = h;",
+       "       i = stack->o_delqs;",
+       "       now._nr_pr += 1;",
+       "       if (!stack->lst)        /* debugging */",
+       "               Uerror(\"error: p_restor\");",
+       "       stack = stack->lst;",
+       "       this = pptr(h);",
+       "       while (i-- > 0)",
+       "               q_restor();",
+       "}\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",
+       "       vsize += stack->o_skip;",
+       "       memcpy(z+vsize, stack->body, stack->o_delta);",
+       "       vsize += stack->o_delta;",
+       "#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;",
+       "#endif",
+       "#endif",
+       "       for ( ; k < k_end; k++)",
+       "               Mask[k] = 1;",
+       "#endif",
+       "       if (!stack->lst)        /* debugging */",
+       "               Uerror(\"error: q_restor\");",
+       "       stack = stack->lst;",
+       "}",
+
+       "typedef struct IntChunks {",
+       "       int     *ptr;",
+       "       struct  IntChunks *nxt;",
+       "} IntChunks;",
+       "IntChunks *filled_chunks[512];",
+       "IntChunks *empty_chunks[512];",
+
+       "int *",
+       "grab_ints(int nr)",
+       "{      IntChunks *z;",
+       "       if (nr >= 512) Uerror(\"cannot happen grab_int\");",
+       "       if (filled_chunks[nr])",
+       "       {       z = filled_chunks[nr];",
+       "               filled_chunks[nr] = filled_chunks[nr]->nxt;",
+       "       } else ",
+       "       {       z = (IntChunks *) emalloc(sizeof(IntChunks));",
+       "               z->ptr = (int *) emalloc(nr * sizeof(int));",
+       "       }",
+       "       z->nxt = empty_chunks[nr];",
+       "       empty_chunks[nr] = z;",
+       "       return z->ptr;",
+       "}",
+       "void",
+       "ungrab_ints(int *p, int nr)",
+       "{      IntChunks *z;",
+       "       if (!empty_chunks[nr]) Uerror(\"cannot happen ungrab_int\");",
+       "       z = empty_chunks[nr];",
+       "       empty_chunks[nr] = empty_chunks[nr]->nxt;",
+       "       z->ptr = p;",
+       "       z->nxt = filled_chunks[nr];",
+       "       filled_chunks[nr] = z;",
+       "}",
+       "int",
+       "delproc(int sav, int h)",
+       "{      int d, i=0;",
+       "#ifndef NOCOMP",
+       "       int o_vsize = vsize;",
+       "#endif",
+       "       if (h+1 != (int) now._nr_pr) return 0;\n",
+       "       while (now._nr_qs",
+       "       &&     q_offset[now._nr_qs-1] > proc_offset[h])",
+       "       {       delq(sav);",
+       "               i++;",
+       "       }",
+       "       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->lst = stack;",
+       "                       smax++;",
+       "               }",
+       "               stack = stack->nxt;",
+       "               stack->o_offset = proc_offset[h];",
+       "#if VECTORSZ>32000",
+       "               stack->o_skip   = (int) proc_skip[h];",
+       "#else",
+       "               stack->o_skip   = (short) proc_skip[h];",
+       "#endif",
+       "#ifndef XUSAFE",
+       "               stack->o_name   = p_name[h];",
+       "#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;",
+       "       memset((char *)pptr(h), 0, d);",
+       "       vsize -= (int) proc_skip[h];",
+       "#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;",
+       "       int d = vsize - q_offset[now._nr_qs - 1];",
+       "#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->lst = stack;",
+       "                       smax++;",
+       "               }",
+       "               stack = stack->nxt;",
+       "               stack->o_offset = q_offset[h];",
+       "#if VECTORSZ>32000",
+       "               stack->o_skip   = (int) q_skip[h];",
+       "#else",
+       "               stack->o_skip   = (short) q_skip[h];",
+       "#endif",
+       "#ifndef XUSAFE",
+       "               stack->o_name   = q_name[h];",
+       "#endif",
+       "               stack->o_delta  = d;",
+       "               memcpy(stack->body, (char *)qptr(h), d);",
+       "       }",
+       "       vsize = q_offset[h];",
+       "       now._nr_qs = now._nr_qs - 1;",
+       "       memset((char *)qptr(h), 0, d);",
+       "       vsize -= (int) q_skip[h];",
+       "#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)",
+       "{      int i;",
+       "       for (i = 0; i < (int) now._nr_qs; i++)",
+       "       {       if (q_sz(i) > 0)",
+       "                       return 0;",
+       "       }",
+       "       return 1;",
+       "}\n",
+       "int",
+       "endstate(void)",
+       "{      int i; P0 *ptr;",
+       "       for (i = BASE; i < (int) now._nr_pr; i++)",
+       "       {       ptr = (P0 *) pptr(i);",
+       "               if (!stopstate[ptr->_t][ptr->_p])",
+       "                       return 0;",
+       "       }",
+       "       if (strict) return qs_empty();",
+       "#if defined(EVENT_TRACE) && !defined(OTIM)",
+       "       if (!stopstate[EVENT_TRACE][now._event] && !a_cycles)",
+       "       {       printf(\"pan: event_trace not completed\\n\");",
+       "               return 0;",
+       "       }",
+       "#endif",
+       "       return 1;",
+       "}\n",
+       "#ifndef SAFETY",
+       "void",
+       "checkcycles(void)",
+       "{      uchar o_a_t = now._a_t;",
+       "#ifdef SCHED",
+       "       int o_limit;",
+       "#endif",
+       "#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",
+       "       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",
+       "       memcpy((char *)&A_Root, (char *)&now, vsize);",
+       "       A_depth = depthfound = depth;",
+
+       "#if NCORE>1",
+       "       mem_put_acc();", /* handoff accept states */
+       "#else",
+       "       #ifdef SCHED",
+       "       o_limit = trpt->sched_limit;",
+       "       trpt->sched_limit = 0;",
+       "       #endif",
+       "       new_state();    /* start 2nd DFS */",
+       "       #ifdef SCHED",
+       "       trpt->sched_limit = o_limit;",
+       "       #endif",
+       "#endif",
+
+       "       now._a_t = o_a_t;",
+       "#ifndef NOFAIR",
+       "       now._cnt[1] = o_cnt;",
+       "#endif",
+       "       A_depth = 0; depthfound = -1;",
+               "#ifdef DEBUG",
+       "       printf(\"%%d: cycle check returns\\n\", depth);",
+               "#endif",
+               "#ifdef FULLSTACK",
+               "#ifndef MA",
+       "       trpt->ostate = sv;      /* restore */",
+               "#else",
+       "       trpt->proviso = prov;",
+               "#endif",
+               "#endif",
+       "}",
+       "#endif\n",
+       "#if defined(FULLSTACK) && defined(BITSTATE)",
+       "struct H_el *Free_list = (struct 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 *));",
+       "}",
+       "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",
+
+       "#if NCORE>1",
+       "struct H_el *",
+       "grab_state(int n)",
+       "{      struct H_el *grab_shared(int);",
+       "       return grab_shared(sizeof(struct H_el)+n-sizeof(unsigned));",
+       "}",
+       "#else",
+       " #ifndef AUTO_RESIZE",
+       "  #define grab_state(n) (struct H_el *) \\",
+       "               emalloc(sizeof(struct H_el)+n-sizeof(unsigned long));",
+       " #else",
+       "  struct H_el *",
+       "  grab_state(int n)",
+       "  {    struct H_el *p;",
+       "       int cnt = sizeof(struct H_el)+n-sizeof(unsigned long);",
+       "",
+       "       if (reclaim_size >= cnt+WS)",
+       "       {       if ((cnt & (WS-1)) != 0) /* alignment */",
+       "               {       cnt += WS - (cnt & (WS-1));",
+       "               }",
+       "               p = (struct H_el *) reclaim_mem;",
+       "               reclaim_mem  += cnt;",
+       "               reclaim_size -= cnt;",
+       "               memset(p, 0, cnt);",
+       "       } else",
+       "       {       p = (struct H_el *) emalloc(cnt);",
+       "       }",
+       "       return p;",
+       "  }",
+       " #endif",
+       "#endif",
+
+       "#endif",
+"#ifdef COLLAPSE",
+       "unsigned long",
+       "ordinal(char *v, long n, short tp)",
+       "{      struct H_el *tmp, *ntmp; long m;",
+       "       struct H_el *olst = (struct H_el *) 0;",
+       "       s_hash((uchar *)v, n);",
+
+       "#if NCORE>1 && !defined(SEP_STATE)",
+       "       enter_critical(CS_ID);  /* uses spinlock - 1..128 */",
+       "#endif",
+
+       "       tmp = H_tab[j1];",
+       "       if (!tmp)",
+       "       {       tmp = grab_state(n);",
+       "               H_tab[j1] = tmp;",
+       "       } else",
+       "       for ( ;; olst = tmp, tmp = tmp->nxt)",
+       "       {       m = memcmp(((char *)&(tmp->state)), v, n);",
+       "               if (n == tmp->ln)",
+       "               {",
+       "                       if (m == 0)",
+       "                               goto done;",
+       "                       if (m < 0)",
+       "                       {",
+       "Insert:                        ntmp = grab_state(n);",
+       "                               ntmp->nxt = tmp;",
+       "                               if (!olst)",
+       "                                       H_tab[j1] = ntmp;",
+       "                               else",
+       "                                       olst->nxt = ntmp;",
+       "                               tmp = ntmp;",
+       "                               break;",
+       "                       } else if (!tmp->nxt)",
+       "                       {",
+       "Append:                        tmp->nxt = grab_state(n);",
+       "                               tmp = tmp->nxt;",
+       "                               break;",
+       "                       }",
+       "                       continue;",
+       "               }",
+       "               if (n < tmp->ln)",
+       "                       goto Insert;",
+       "               else if (!tmp->nxt)",
+       "                       goto Append;",
+       "       }",
+       "       m = ++ncomps[tp];",
+       "#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);  /* uses spinlock */",
+       "#endif",
+
+       "#ifdef FULLSTACK",
+       "       return tmp->tagged;",
+       "#else",
+       "       return tmp->st_id;",
+       "#endif",
+       "}",
+       "",
+       "int",
+       "compress(char *vin, int nin)   /* collapse compression */",
+       "{      char    *w, *v = (char *) &comp_now;",
+       "       int     i, j;",
+       "       unsigned long   n;",
+       "       static char     *x;",
+       "       static uchar    nbytes[513]; /* 1 + 256 + 256 */",
+       "       static unsigned short nbytelen;",
+       "       long col_q(int, char *);",
+       "       long col_p(int, char *);",
+       "#ifndef SAFETY",
+       "       if (a_cycles)",
+       "               *v++ = now._a_t;",
+               "#ifndef NOFAIR",
+       "       if (fairness)",
+       "       for (i = 0; i < NFAIR; i++)",
+       "               *v++ = now._cnt[i];",
+               "#endif",
+       "#endif",
+       "       nbytelen = 0;",
+
+       "#ifndef JOINPROCS",
+       "       for (i = 0; i < (int) now._nr_pr; i++)",
+       "       {       n = col_p(i, (char *) 0);",
+       "#ifdef NOFIX",
+       "               nbytes[nbytelen] = 0;",
+       "#else",
+       "               nbytes[nbytelen] = 1;",
+       "               *v++ = ((P0 *) pptr(i))->_t;",
+       "#endif",
+       "               *v++ = n&255;",
+       "               if (n >= (1<<8))",
+       "               {       nbytes[nbytelen]++;",
+       "                       *v++ = (n>>8)&255;",
+       "               }",
+       "               if (n >= (1<<16))",
+       "               {       nbytes[nbytelen]++;",
+       "                       *v++ = (n>>16)&255;",
+       "               }",
+       "               if (n >= (1<<24))",
+       "               {       nbytes[nbytelen]++;",
+       "                       *v++ = (n>>24)&255;",
+       "               }",
+       "               nbytelen++;",
+       "       }",
+       "#else",
+       "       x = scratch;",
+       "       for (i = 0; i < (int) now._nr_pr; i++)",
+       "               x += col_p(i, x);",
+       "       n = ordinal(scratch, x-scratch, 2); /* procs */",
+       "       *v++ = n&255;",
+       "       nbytes[nbytelen] = 0;",
+       "       if (n >= (1<<8))",
+       "       {       nbytes[nbytelen]++;",
+       "               *v++ = (n>>8)&255;",
+       "       }",
+       "       if (n >= (1<<16))",
+       "       {       nbytes[nbytelen]++;",
+       "               *v++ = (n>>16)&255;",
+       "       }",
+       "       if (n >= (1<<24))",
+       "       {       nbytes[nbytelen]++;",
+       "               *v++ = (n>>24)&255;",
+       "       }",
+       "       nbytelen++;",
+       "#endif",
+       "#ifdef SEPQS",
+       "       for (i = 0; i < (int) now._nr_qs; i++)",
+       "       {       n = col_q(i, (char *) 0);",
+       "               nbytes[nbytelen] = 0;",
+       "               *v++ = n&255;",
+       "               if (n >= (1<<8))",
+       "               {       nbytes[nbytelen]++;",
+       "                       *v++ = (n>>8)&255;",
+       "               }",
+       "               if (n >= (1<<16))",
+       "               {       nbytes[nbytelen]++;",
+       "                       *v++ = (n>>16)&255;",
+       "               }",
+       "               if (n >= (1<<24))",
+       "               {       nbytes[nbytelen]++;",
+       "                       *v++ = (n>>24)&255;",
+       "               }",
+       "               nbytelen++;",
+       "       }",
+       "#endif",
+
+       "#ifdef NOVSZ",
+       "       /* 3 = _a_t, _nr_pr, _nr_qs */",
+       "       w = (char *) &now + 3 * sizeof(uchar);",
+               "#ifndef NOFAIR",
+               "       w += NFAIR;",
+               "#endif",
+       "#else",
+               "#if VECTORSZ<65536",
+               "       w = (char *) &(now._vsz) + sizeof(unsigned short);",
+               "#else",
+               "       w = (char *) &(now._vsz) + sizeof(unsigned long);",
+               "#endif",
+       "#endif",
+       "       x = scratch;",
+       "       *x++ = now._nr_pr;",
+       "       *x++ = now._nr_qs;",
+
+       "       if (now._nr_qs > 0 && qptr(0) < pptr(0))",
+       "               n = qptr(0) - (uchar *) w;",
+       "       else",
+       "               n = pptr(0) - (uchar *) w;",
+       "       j = w - (char *) &now;",
+       "       for (i = 0; i < (int) n; i++, w++)",
+       "               if (!Mask[j++]) *x++ = *w;",
+       "#ifndef SEPQS",
+       "       for (i = 0; i < (int) now._nr_qs; i++)",
+       "               x += col_q(i, x);",
+       "#endif",
+
+       "       x--;",
+       "       for (i = 0, j = 6; i < nbytelen; i++)",
+       "       {       if (j == 6)",
+       "               {       j = 0;",
+       "                       *(++x) = 0;",
+       "               } else",
+       "                       j += 2;",
+       "               *x |= (nbytes[i] << j);",
+       "       }",
+       "       x++;",
+       "       for (j = 0; j < WS-1; j++)",
+       "               *x++ = 0;",
+       "       x -= j; j = 0;",
+       "       n = ordinal(scratch, x-scratch, 0); /* globals */",
+       "       *v++ = n&255;",
+       "       if (n >= (1<< 8)) { *v++ = (n>> 8)&255; j++; }",
+       "       if (n >= (1<<16)) { *v++ = (n>>16)&255; j++; }",
+       "       if (n >= (1<<24)) { *v++ = (n>>24)&255; j++; }",
+       "       *v++ = j;       /* add last count as a byte */",
+
+       "       for (i = 0; i < WS-1; i++)",
+       "               *v++ = 0;",
+       "       v -= i;",
+       "#if 0",
+       "       printf(\"collapse %%d -> %%d\\n\",",
+       "               vsize, v - (char *)&comp_now);",
+       "#endif",
+       "       return v - (char *)&comp_now;",
+       "}",
+
+"#else",
+"#if !defined(NOCOMP)",
+       "int",
+       "compress(char *vin, int n)     /* default compression */",
+       "{",
+       "#ifdef HC",
+       "       int delta = 0;",
+       "       s_hash((uchar *)vin, n); /* sets K1 and K2 */",
+               "#ifndef SAFETY",
+       "       if (S_A)",
+       "       {       delta++;        /* _a_t  */",
+                       "#ifndef NOFAIR",
+       "               if (S_A > NFAIR)",
+       "                       delta += NFAIR; /* _cnt[] */",
+                       "#endif",
+       "       }",
+               "#endif",
+       "       memcpy((char *) &comp_now + delta, (char *) &K1, WS);",
+       "       delta += WS;",
+               "#if HC>0",
+       "       memcpy((char *) &comp_now + delta, (char *) &K2, HC);",
+       "       delta += HC;",
+               "#endif",
+       "       return delta;",
+       "#else",
+       "       char *vv = vin;",
+       "       char *v = (char *) &comp_now;",
+       "       int 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;",
+       "               }",
+       "               r = (n+WS-1)/WS; /* words rounded up */",
+       "               r *= WS;         /* bytes */",
+       "               i = r - i;       /* remainder */",
+       "               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);",
+               "#endif",
+       "       return v - (char *)&comp_now;",
+       "#endif",
+       "}",
+"#endif",
+"#endif",
+       "#if defined(FULLSTACK) && defined(BITSTATE)",
+"#if defined(MA)",
+       "#if !defined(onstack_now)",
+       "int  onstack_now(void) {}", /* to suppress compiler errors */
+       "#endif",
+       "#if !defined(onstack_put)",
+       "void onstack_put(void) {}", /* for this invalid combination */
+       "#endif",
+       "#if !defined(onstack_zap)",
+       "void onstack_zap(void) {}", /* of directives */
+       "#endif",
+"#else",
+       "void",
+       "onstack_zap(void)",
+       "{      struct H_el *v, *w, *last = 0;",
+       "       struct H_el **tmp = H_tab;",
+       "       char *nv; int n, m;\n",
+       "       static char warned = 0;",
+       "",
+       "       H_tab = S_Tab;",
+       "#ifndef NOCOMP",
+       "       nv = (char *) &comp_now;",
+       "       n = compress((char *)&now, vsize);",
+       "#else",
+               "#if defined(BITSTATE) && defined(LC)",
+       "       nv = (char *) &comp_now;",
+       "       n = compact_stack((char *)&now, vsize);",
+               "#else",
+       "       nv = (char *) &now;",
+       "       n = vsize;",
+               "#endif",
+       "#endif",
+       "#if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
+       "       s_hash((uchar *)nv, n);",
+       "#endif",
+       "       H_tab = tmp;",
+       "       for (v = S_Tab[j1]; v; Zh++, last=v, v=v->nxt)",
+       "       {       m = memcmp(&(v->state), nv, n);",
+       "               if (m == 0)",
+       "                       goto Found;",
+       "               if (m < 0)",
+       "                       break;",
+       "       }",
+       "/* NotFound: */",
+       "#ifndef ZAPH",
+       "       #if defined(BITSTATE) && NCORE>1",
+       "       /* seen this happen, likely harmless, but not yet understood */",
+       "       if (warned == 0)",
+       "       #endif",
+       "       {       /* Uerror(\"stack out of wack - zap\"); */",
+       "               cpu_printf(\"pan: warning, stack incomplete\\n\");",
+       "               warned = 1;",
+       "       }",
+       "#endif",
+       "       return;",
+       "Found:",
+       "       ZAPS++;",
+       "       if (last)",
+       "               last->nxt = v->nxt;",
+       "       else",
+       "               S_Tab[j1] = v->nxt;",
+       "       v->tagged = (unsigned) n;",
+       "#if !defined(NOREDUCE) && !defined(SAFETY)",
+       "       v->proviso = 0;",
+       "#endif",
+       "       v->nxt = last = (struct H_el *) 0;",
+       "       for (w = Free_list; w; Fa++, last=w, w = w->nxt)",
+       "       {       if ((int) w->tagged <= n)",
+       "               {       if (last)",
+       "                       {       v->nxt = w;",
+       "                               last->nxt = v;",
+       "                       } else",
+       "                       {       v->nxt = Free_list;",
+       "                               Free_list = v;",
+       "                       }",
+       "                       return;",
+       "               }",
+       "               if (!w->nxt)",
+       "               {       w->nxt = v;",
+       "                       return;",
+       "       }       }",
+       "       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",
+       "       #ifndef ZAPH",
+       "               Uerror(\"cannot happen - unstack_put\");",
+       "       #endif",
+       "#endif",
+       "       H_tab = tmp;",
+       "       trpt->ostate = Lstate;",
+       "       PUT++;",
+       "}",
+       "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 BITSTATE",
+       "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(unsigned long);",
+                       "               init_HT(0L);",
+                       "       }",
+                       "#endif",
+               "#endif",
+       "  #endif",
+       "  #if !defined(MA) || defined(COLLAPSE)",
+               "#if NCORE>1",
+                       "       if (!readtrail)",
+                       "       {       void init_HT(unsigned long);",
+                       "               init_HT((unsigned long) (ONE_L<<ssize)*sizeof(struct H_el *));",
+                       "       } else",
+               "#endif",
+                       "       H_tab = (struct H_el **)",
+                       "               emalloc((ONE_L<<ssize)*sizeof(struct H_el *));",
+       "  #endif",
+       "}",
+       "#endif\n",
+
+       "#if !defined(BITSTATE) || defined(FULLSTACK)",
+
+       "#ifdef DEBUG",
+       "void",
+       "dumpstate(int wasnew, char *v, int n, int tag)",
+       "{      int i;",
+       "#ifndef SAFETY",
+       "       if (S_A)",
+       "       {       printf(\"\tstate tags %%d (%%d::%%d): \",",
+       "                       V_A, wasnew, v[0]);",
+               "#ifdef FULLSTACK",
+       "               printf(\" %%d \", tag);",
+               "#endif",
+       "               printf(\"\\n\");",
+       "       }",
+       "#endif",
+       "#ifdef SDUMP",
+       "#ifndef NOCOMP",
+       "       printf(\"\t State: \");",
+       "       for (i = 0; i < vsize; i++) printf(\"%%d%%s,\",",
+       "               ((char *)&now)[i], Mask[i]?\"*\":\"\");",
+       "#endif",
+       "       printf(\"\\n\tVector: \");",
+       "       for (i = 0; i < n; i++) printf(\"%%d,\", v[i]);",
+       "       printf(\"\\n\");",
+       "#endif",
+       "}",
+       "#endif",
+
+"#ifdef MA",
+       "int",
+       "gstore(char *vin, int nin, uchar pbit)",
+       "{      int n, i;",
+       "       int ret_val = 1;",
+       "       uchar *v;",
+       "       static uchar Info[MA+1];",
+       "#ifndef NOCOMP",
+       "       n = compress(vin, nin);",
+       "       v = (uchar *) &comp_now;",
+       "#else",
+       "       n = nin;",
+       "       v = vin;",
+       "#endif",
+       "       if (n >= MA)",
+       "       {       printf(\"pan: error, MA too small, recompile pan.c\");",
+       "               printf(\" with -DMA=N with N>%%d\\n\", n);",
+       "               Uerror(\"aborting\");",
+       "       }",
+       "       if (n > (int) maxgs)",
+       "       {       maxgs = (unsigned int) n;",
+       "       }",
+       "       for (i = 0; i < n; i++)",
+       "       {       Info[i] = v[i];",
+       "       }",
+       "       for ( ; i < MA-1; i++)",
+       "       {       Info[i] = 0;",
+       "       }",
+       "       Info[MA-1] = pbit;",
+       "       if (a_cycles)   /* place _a_t at the end */",
+       "       {       Info[MA] = Info[0];",
+       "               Info[0]  = 0;",
+       "       }",
+       "",
+       "#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)",
+       "               &&  depth > A_depth)",
+       "               {       Info[MA] &= ~(1|16|32); /* _a_t */",
+       "                       if (dfa_member(MA))",   /* was !dfa_member(MA) */
+       "                       {       Info[MA-1] = 4; /* off-stack bit */",
+       "                               nShadow++;",
+       "                               if (!dfa_member(MA-1))",
+       "                               {       ret_val = 3;",
+       "                       #ifdef VERBOSE",
+       "                                       printf(\"intersected 1st dfs stack\\n\");",
+       "                       #endif",
+       "                                       goto done;",
+       "               }       }       }",
+       "               ret_val = 0;",
+       "       #ifdef VERBOSE",
+       "               printf(\"new state\\n\");",
+       "       #endif",
+       "               goto done;",
+       "       }",
+       "#ifdef FULLSTACK",
+       "       if (pbit == 0)",
+       "       {       Info[MA-1] = 1; /* proviso bit */",
+       "#ifndef BFS",
+       "               trpt->proviso = dfa_member(MA-1);",
+       "#endif",
+       "               Info[MA-1] = 4; /* off-stack bit */",
+       "               if (dfa_member(MA-1))",
+       "               {       ret_val = 1; /* off-stack */",
+       "       #ifdef VERBOSE",
+       "                       printf(\"old state\\n\");",
+       "       #endif",
+       "               } else",
+       "               {       ret_val = 2; /* on-stack */",
+       "       #ifdef VERBOSE",
+       "                       printf(\"on-stack\\n\");",
+       "       #endif",
+       "               }",
+       "               goto done;",
+       "       }",
+       "#endif",
+       "       ret_val = 1;",
+       "#ifdef VERBOSE",
+       "       printf(\"old state\\n\");",
+       "#endif",
+       "done:",
+       "#if NCORE>1 && !defined(SEP_STATE)",
+       "       leave_critical(GLOBAL_LOCK);",
+       "#endif",
+       "       return ret_val; /* old state */",
+       "}",
+"#endif",
+
+       "#if defined(BITSTATE) && defined(LC)",
+       "int",
+       "compact_stack(char *vin, int n)",      /* special case of HC4 */
+       "{      int delta = 0;",
+       "       s_hash((uchar *)vin, n); /* sets K1 and K2 */",
+               "#ifndef SAFETY",
+       "       delta++;        /* room for state[0] |= 128 */",
+               "#endif",
+       "       memcpy((char *) &comp_now + delta, (char *) &K1, WS);",
+       "       delta += WS;",
+       "       memcpy((char *) &comp_now + delta, (char *) &K2, WS);",
+       "       delta += WS; /* use all available bits */",
+       "       return delta;",
+       "}",
+       "#endif",
+
+       "int",
+       "hstore(char *vin, int nin)     /* hash table storage */",
+       "{      struct H_el *ntmp;",
+       "       struct H_el *tmp, *olst = (struct H_el *) 0;",
+       "       char *v; int n, m=0;",
+       "#ifdef HC",
+       "       uchar rem_a;",
+       "#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);",
+       "       } else",
+       "       {       v = vin; n = nin;",
+       "       }",
+               "#else",
+       "       v = vin; n = nin;",
+               "#endif",
+       "#else",
+       "       v = (char *) &comp_now;",
+       "       #ifdef HC",
+       "       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 -- but on vin, not on v... */
+       "       #ifdef HC",
+       "       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  */",
+                       "#ifndef NOFAIR",
+       "               if (S_A > NFAIR)",
+       "               for (m = 0; m < NFAIR; m++)",
+       "                       v[m+1] = 0;     /* _cnt[] */",
+                       "#endif",
+       "               m = 0;",
+       "       }",
+       "       #endif",
+       "#endif",
+       "#if !defined(HC) && !(defined(BITSTATE) && defined(LC))",
+       "       s_hash((uchar *)v, n);",
+       "#endif",
+       "#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+       "       enter_critical(CS_ID);  /* uses spinlock */",
+       "#endif",
+
+       "       tmp = H_tab[j1];",
+       "       if (!tmp)",
+       "       {  tmp = grab_state(n);",
+       "#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] = tmp;",
+       "       } else",
+       "       {  for (;; hcmp++, olst = tmp, tmp = tmp->nxt)",
+       "          {   /* skip the _a_t and the _cnt bytes */",
+       "#ifdef COLLAPSE",
+       "               if (tmp->ln != 0)",
+       "               {       if (!tmp->nxt) goto Append;",
+       "                       continue;",
+       "               }",
+       "#endif",
+       "               m = memcmp(((char *)&(tmp->state)) + S_A, ",
+       "                       v + S_A, n - S_A);",
+       "               if (m == 0) {",
+       "#ifdef SAFETY",
+                       "#define wasnew 0",
+       "#else",
+       "               int wasnew = 0;",
+       "#endif",
+
+       "#ifndef SAFETY",
+       "#ifndef NOCOMP",
+       "               if (S_A)",
+       "               { if ((((char *)&(tmp->state))[0] & V_A) != V_A)",
+       "                 {     wasnew = 1; nShadow++;",
+       "                       ((char *)&(tmp->state))[0] |= V_A;",
+       "                 }",
+               "#ifndef NOFAIR",
+       "                 if (S_A > NFAIR)",
+       "                 {     /* 0 <= now._cnt[now._a_t&1] < MAXPROC */",
+       "                       unsigned 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 */",
+       "                       {       ci = (NFAIR - 1) - ci;",
+       "                               bp = 7 - bp; /* bp = 0..7 */",
+       "                       }",
+       "                       ci++;   /* skip over _a_t */",
+       "                       bp = 1 << bp;   /* the bit mask */",
+       "                       if ((((char *)&(tmp->state))[ci] & bp)==0)",
+       "                       {       if (!wasnew)",
+       "                               {       wasnew = 1;",
+       "                                       nShadow++;",
+       "                               }",
+       "                               ((char *)&(tmp->state))[ci] |= bp;",
+       "                       }",
+       "                  }",
+       "                  /* else: wasnew == 0, i.e., old state */",
+               "#endif",
+       "               }",
+       "#endif",
+       "#endif",
+
+       "#if NCORE>1",
+       "               Lstate = (struct H_el *) tmp;",
+       "#endif",
+
+       "#ifdef FULLSTACK",
+               "#ifndef SAFETY",       /* or else wasnew == 0 */
+       "               if (wasnew)",
+       "               {       Lstate = (struct H_el *) tmp;",
+       "                       tmp->tagged |= V_A;",
+       "                       if ((now._a_t&1)",
+       "                       && (tmp->tagged&A_V)",
+       "                       && depth > A_depth)",
+       "                       {",
+       "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 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 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;",
+               "#ifndef SAFETY",
+       "                       /* already on current dfs stack */",
+       "                       /* but may also be on 1st dfs stack */",
+       "                       if ((now._a_t&1)",
+       "                       && (tmp->tagged&A_V)",
+
+       "                       && depth > A_depth",
+               /* new (Zhang's example) */
+               "#ifndef NOFAIR",
+       "                       && (!fairness || now._cnt[1] <= 1)",
+               "#endif",
+       "                       )",
+
+       "                               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 NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+       "                       leave_critical(CS_ID);",
+       "#endif",
+       "                       return 2; /* match on stack */",
+       "               }",
+       "#else",
+       "               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 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",
+       "#if NCORE>1",
+       "       printf(\"cpu%%d: \", core_id);",
+       "#endif",
+       "       printf(\"\t\tReVisiting (from smaller depth)\\n\");",
+               "#endif",
+       "                       nstates--;",
+#if 0
+  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
+  can be found
+  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 */
+#endif
+       "#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)",
+       "                       leave_critical(CS_ID);",
+       "#endif",
+       "                       return 0;",
+       "               }",
+       "#endif",
+       "#if (defined(BFS) && defined(Q_PROVISO)) || NCORE>1",
+       "               Lstate = (struct H_el *) tmp;",
+       "#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;",
+       "                       else",
+       "                               olst->nxt = ntmp;",
+       "                       tmp = ntmp;",
+       "                       break;",
+       "              } else if (!tmp->nxt)",
+       "              {        /* append after tmp */",
+       "#ifdef COLLAPSE",
+       "Append:",
+       "#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",
+       "       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",
+       "       printf(\"       New state %%d\\n\", (int) nstates);",
+               "#endif",
+       "#endif",
+       "#if !defined(SAFETY) || defined(REACH)",
+       "       tmp->D = depth;",
+       "#endif",
+       "#ifndef SAFETY",
+       "#ifndef NOCOMP",
+       "       if (S_A)",
+       "       {       v[0] = V_A;",
+               "#ifndef NOFAIR",
+       "               if (S_A > NFAIR)",
+       "               {       unsigned 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)",
+       "                       {       ci = (NFAIR - 1) - ci;",
+       "                               bp = 7 - bp; /* bp = 0..7 */",
+       "                       }",
+       "                       v[1+ci] = 1 << bp;",
+       "               }",
+               "#endif",
+       "       }",
+       "#endif",
+       "#endif",
+       "#if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+       "       tmp->m_K1 = K1;",
+       "#endif",
+       "       memcpy(((char *)&(tmp->state)), v, n);",
+       "#ifdef FULLSTACK",
+       "       tmp->tagged = (S_A)?V_A:(depth+1);",
+               "#ifdef DEBUG",
+       "               dumpstate(-1, v, n, tmp->tagged);",
+               "#endif",
+       "       Lstate = (struct H_el *) tmp;",
+       "#else",
+       "       #ifdef DEBUG",
+       "               dumpstate(-1, v, n, 0);",
+       "       #endif",
+       "       #if NCORE>1",
+       "               Lstate = (struct H_el *) tmp;",
+       "       #endif",
+       "#endif",
+
+       "/* #if NCORE>1 && !defined(SEP_STATE) */",
+       "#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;",
+       "}",
+       "#endif",
+       "#include TRANSITIONS",
+       "void",
+       "do_reach(void)",
+       "{",
+       0,
+};
diff --git a/trunk/verif/Spin/Src5.1.6/pangen2.c b/trunk/verif/Spin/Src5.1.6/pangen2.c
new file mode 100755 (executable)
index 0000000..bc61413
--- /dev/null
@@ -0,0 +1,3095 @@
+/***** 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            */
+/* (c) 2007: small additions for V5.0 to support multi-core verifications */
+
+#include "spin.h"
+#include "version.h"
+#include "y.tab.h"
+#include "pangen2.h"
+#include "pangen4.h"
+#include "pangen5.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", \
+                               m, e->n->fn->name, e->n->ln); }
+
+extern ProcList        *rdy;
+extern RunList *run;
+extern Symbol  *Fname, *oFname, *context;
+extern char    *claimproc, *eventmap;
+extern int     lineno, verbose, Npars, Mpars;
+extern int     m_loss, has_remote, has_remvar, merger, rvopt, separate;
+extern int     Ntimeouts, Etimeouts, deadvar;
+extern int     u_sync, u_async, nrRdy, Unique;
+extern int     GenCode, IsGuard, Level, TestOnly;
+extern short   has_stack;
+extern char    *NextLab[];
+
+FILE   *tc, *th, *tt, *tb;
+static FILE    *tm;
+
+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_badelse=0;  /* spec contains else combined with chan refs */
+short  has_enabled=0;  /* spec contains enabled() */
+short  has_pcvalue=0;  /* spec contains pc_value() */
+short  has_np=0;       /* spec contains np_ */
+short  has_sorted=0;   /* spec contains `!!' (sorted-send) operator */
+short  has_random=0;   /* spec contains `??' (random-recv) operator */
+short  has_xu=0;       /* spec contains xr or xs assertions */
+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  evalindex=0;    /* evaluate index of var names */
+int    mst=0;          /* max nr of state/process */
+int    claimnr = -1;   /* claim process, if any */
+int    eventmapnr = -1; /* event trace, if any */
+int    Pid;            /* proc currently processed */
+int    multi_oval;     /* set in merges, used also in pangen4.c */
+
+#define MAXMERGE       256     /* max nr of bups per merge sequence */
+
+static short   CnT[MAXMERGE];
+static Lextok  XZ, YZ[MAXMERGE];
+static int     didcase, YZmax, YZcnt;
+
+static Lextok  *Nn[2];
+static int     Det;    /* set if deterministic */
+static int     T_sum, T_mus, t_cyc;
+static int     TPE[2], EPT[2];
+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 _ */
+
+int    has_global(Lextok *);
+void   Fatal(char *, char *);
+static int     getweight(Lextok *);
+static int     scan_seq(Sequence *);
+static void    genconditionals(void);
+static void    mark_seq(Sequence *);
+static void    patch_atomic(Sequence *);
+static void    put_seq(Sequence *, int, int);
+static void    putproc(ProcList *);
+static void    Tpe(Lextok *);
+extern void    spit_recvs(FILE *, FILE*);
+
+static int
+fproc(char *s)
+{      ProcList *p;
+
+       for (p = rdy; p; p = p->nxt)
+               if (strcmp(p->n->name, s) == 0)
+                       return p->tn;
+
+       fatal("proctype %s not found", s);
+       return -1;
+}
+
+static void
+reverse_procs(RunList *q)
+{
+       if (!q) return;
+       reverse_procs(q->nxt);
+       fprintf(tc, "   Addproc(%d);\n", q->tn);
+}
+
+static void
+forward_procs(RunList *q)
+{
+       if (!q) return;
+       fprintf(tc, "   Addproc(%d);\n", q->tn);
+       forward_procs(q->nxt);
+}
+
+static void
+tm_predef_np(void)
+{
+       fprintf(th, "#define _T5        %d\n", uniq++);
+       fprintf(th, "#define _T2        %d\n", uniq++);
+
+       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");
+       }
+
+       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\t\tcontinue;\n");
+       fprintf(tm, "\t\t/* else fall through */\n");
+       fprintf(tm, "\tcase  _T2:\t/* true */\n");
+       fprintf(tm, "\t\t_m = 3; goto P999;\n");
+}
+
+static void
+tt_predef_np(void)
+{
+       fprintf(tt, "\t/* np_ demon: */\n");
+       fprintf(tt, "\ttrans[_NP_] = ");
+       fprintf(tt, "(Trans **) emalloc(2*sizeof(Trans *));\n");
+       fprintf(tt, "\tT = trans[_NP_][0] = ");
+       fprintf(tt, "settr(9997,0,1,_T5,0,\"(np_)\", 1,2,0);\n");
+       fprintf(tt, "\t    T->nxt         = ");
+       fprintf(tt, "settr(9998,0,0,_T2,0,\"(1)\",   0,2,0);\n");
+       fprintf(tt, "\tT = trans[_NP_][1] = ");
+       fprintf(tt, "settr(9999,0,1,_T5,0,\"(np_)\", 1,2,0);\n");
+}
+
+static struct {
+       char *nm[3];
+} Cfile[] = {
+       { { "pan.c", "pan_s.c", "pan_t.c" } },
+       { { "pan.h", "pan_s.h", "pan_t.h" } },
+       { { "pan.t", "pan_s.t", "pan_t.t" } },
+       { { "pan.m", "pan_s.m", "pan_t.m" } },
+       { { "pan.b", "pan_s.b", "pan_t.b" } }
+};
+
+void
+gensrc(void)
+{      ProcList *p;
+
+       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 */
+       {       printf("spin: cannot create pan.[chtmfb]\n");
+               alldone(1);
+       }
+
+       fprintf(th, "#define SpinVersion        \"%s\"\n", SpinVersion);
+       fprintf(th, "#define PanSource  \"%s\"\n\n", oFname->name);
+
+       fprintf(th, "#ifdef WIN64\n");
+       fprintf(th, "#define ONE_L      ((unsigned long) 1)\n");
+       fprintf(th, "#define long       long long\n");
+       fprintf(th, "#else\n");
+       fprintf(th, "#define ONE_L      (1L)\n");
+       fprintf(th, "#endif\n");
+
+       if (separate != 2)
+       {       fprintf(th, "char *TrailFile = PanSource; /* default */\n");
+               fprintf(th, "char *trailfilename;\n");
+       }
+
+       fprintf(th, "#if defined(BFS)\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 uchar\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, "#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));
+               claimproc = n->name = "_:never_template:_";
+               ready(n, ZN, s, 0, ZN);
+       }
+       if (separate == 2)
+       {       if (has_remote)
+               {       printf("spin: warning, make sure that the S1 model\n");
+                       printf("      includes the same remote references\n");
+               }
+               fprintf(th, "#ifndef NFAIR\n");
+               fprintf(th, "#define NFAIR      2       /* must be >= 2 */\n");
+               fprintf(th, "#endif\n");
+               if (has_last)
+               fprintf(th, "#define HAS_LAST   %d\n", has_last);
+               goto doless;
+       }
+
+       fprintf(th, "#define DELTA      %d\n", DELTA);
+       fprintf(th, "#ifdef MA\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#define MA      100\n");
+       fprintf(th, "#endif\n#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, "#ifndef NFAIR\n");
+       fprintf(th, "#define NFAIR      2       /* must be >= 2 */\n");
+       fprintf(th, "#endif\n");
+       if (Ntimeouts)
+       fprintf(th, "#define NTIM       %d\n", Ntimeouts);
+       if (Etimeouts)
+       fprintf(th, "#define ETIM       %d\n", Etimeouts);
+       if (has_remvar)
+       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);
+       if (has_last)
+       fprintf(th, "#define HAS_LAST   %d\n", has_last);
+       if (has_sorted)
+       fprintf(th, "#define HAS_SORTED %d\n", has_sorted);
+       if (m_loss)
+       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_stack)
+       fprintf(th, "#define HAS_STACK  %d\n", has_stack);
+       if (has_enabled)
+       fprintf(th, "#define HAS_ENABLED        1\n");
+       if (has_unless)
+       fprintf(th, "#define HAS_UNLESS %d\n", has_unless);
+       if (has_provided)
+       fprintf(th, "#define HAS_PROVIDED       %d\n", has_provided);
+       if (has_pcvalue)
+       fprintf(th, "#define HAS_PCVALUE        %d\n", has_pcvalue);
+       if (has_badelse)
+       fprintf(th, "#define HAS_BADELSE        %d\n", has_badelse);
+       if (has_enabled
+       ||  has_pcvalue
+       ||  has_badelse
+       ||  has_last)
+       {       fprintf(th, "#ifndef NOREDUCE\n");
+               fprintf(th, "#define NOREDUCE   1\n");
+               fprintf(th, "#endif\n");
+       }
+       if (has_np)
+       fprintf(th, "#define HAS_NP     %d\n", has_np);
+       if (merger)
+       fprintf(th, "#define MERGED     1\n");
+
+doless:
+       fprintf(th, "#ifdef NP  /* includes np_ demon */\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, "#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);
+               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);
+               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, "} S_F_MAP;\n");
+
+       fprintf(tc, "/*** Generated by %s ***/\n", SpinVersion);
+       fprintf(tc, "/*** From source: %s ***/\n\n", oFname->name);
+
+       ntimes(tc, 0, 1, Pre0);
+
+       plunk_c_decls(tc);      /* types can be refered to in State */
+
+       switch (separate) {
+       case 0: fprintf(tc, "#include \"pan.h\"\n"); break;
+       case 1: fprintf(tc, "#include \"pan_s.h\"\n"); break;
+       case 2: fprintf(tc, "#include \"pan_t.h\"\n"); break;
+       }
+
+       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");
+       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");
+
+       fprintf(tc, "#ifndef NOBOUNDCHECK\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, "#endif\n");
+
+       c_preview();    /* sets hastrack */
+
+       for (p = rdy; p; p = p->nxt)
+               mst = max(p->s->maxel, mst);
+
+       if (separate != 2)
+       {       fprintf(tt, "#ifdef PEG\n");
+               fprintf(tt, "struct T_SRC {\n");
+               fprintf(tt, "   char *fl; int ln;\n");
+               fprintf(tt, "} T_SRC[NTRANS];\n\n");
+               fprintf(tt, "void\ntr_2_src(int m, char *file, int ln)\n");
+               fprintf(tt, "{  T_SRC[m].fl = file;\n");
+               fprintf(tt, "   T_SRC[m].ln = ln;\n");
+               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, "           T_SRC[n].fl, T_SRC[n].ln);\n");
+               fprintf(tt, "}\n");
+               if (!merger)
+               {       fprintf(tt, "#else\n");
+                       fprintf(tt, "#define tr_2_src(m,f,l)\n");
+               }
+               fprintf(tt, "#endif\n\n");
+               fprintf(tt, "void\nsettable(void)\n{\tTrans *T;\n");
+               fprintf(tt, "\tTrans *settr(int, int, int, int, int,");
+               fprintf(tt, " char *, int, int, int);\n\n");
+               fprintf(tt, "\ttrans = (Trans ***) ");
+               fprintf(tt, "emalloc(%d*sizeof(Trans **));\n", nrRdy+1);
+                               /* +1 for np_ automaton */
+
+               if (separate == 1)
+               {
+               fprintf(tm, "   if (II == 0)\n");
+               fprintf(tm, "   { _m = step_claim(trpt->o_pm, trpt->tau, tt, ot, t);\n");
+               fprintf(tm, "     if (_m) goto P999; else continue;\n");
+               fprintf(tm, "   } else\n");
+               }
+
+               fprintf(tm, "#define rand       pan_rand\n");
+               fprintf(tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
+               fprintf(tm, "   cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, t->forw);\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, "#endif\n");
+               fprintf(tt, "void\nset_claim(void)\n{\tTrans *T;\n");
+               fprintf(tt, "\textern Trans ***trans;\n");
+               fprintf(tt, "\textern Trans *settr(int, int, int, int, int,");
+               fprintf(tt, " char *, int, int, int);\n\n");
+
+               fprintf(tm, "#define rand       pan_rand\n");
+               fprintf(tm, "#if defined(HAS_CODE) && defined(VERBOSE)\n");
+               fprintf(tm, "   cpu_printf(\"Pr: %%d Tr: %%d\\n\", II, forw);\n");
+               fprintf(tm, "#endif\n");
+               fprintf(tm, "   switch (forw) {\n");
+       }
+
+       fprintf(tm, "   default: Uerror(\"bad forward move\");\n");
+       fprintf(tm, "   case 0: /* if without executable clauses */\n");
+       fprintf(tm, "           continue;\n");
+       fprintf(tm, "   case 1: /* generic 'goto' or 'skip' */\n");
+       if (separate != 2)
+               fprintf(tm, "           IfNotBlocked\n");
+       fprintf(tm, "           _m = 3; goto P999;\n");
+       fprintf(tm, "   case 2: /* generic 'else' */\n");
+       if (separate == 2)
+               fprintf(tm, "           if (o_pm&1) continue;\n");
+       else
+       {       fprintf(tm, "           IfNotBlocked\n");
+               fprintf(tm, "           if (trpt->o_pm&1) continue;\n");
+       }
+       fprintf(tm, "           _m = 3; goto P999;\n");
+       uniq = 3;
+
+       if (separate == 1)
+               fprintf(tb, "   if (II == 0) goto R999;\n");
+
+       fprintf(tb, "   switch (t->back) {\n");
+       fprintf(tb, "   default: Uerror(\"bad return move\");\n");
+       fprintf(tb, "   case  0: goto R999; /* nothing to undo */\n");
+
+       for (p = rdy; p; p = p->nxt)
+               putproc(p);
+
+
+       if (separate != 2)
+       {       fprintf(th, "struct {\n");
+               fprintf(th, "   int tp; short *src;\n");
+               fprintf(th, "} src_all[] = {\n");
+               for (p = rdy; p; p = p->nxt)
+                       fprintf(th, "   { %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 */
+       } else
+       {       fprintf(th, "extern short *frm_st0;\n");
+       }
+
+       gencodetable(th);
+
+       if (separate != 1)
+       {       tm_predef_np();
+               tt_predef_np();
+       }
+       fprintf(tt, "}\n\n");   /* end of settable() */
+
+       fprintf(tm, "#undef rand\n");
+       fprintf(tm, "   }\n\n");
+       fprintf(tb, "   }\n\n");
+
+       if (separate != 2)
+       {       ntimes(tt, 0, 1, Tail);
+               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 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 TRANSITIONS\t\"pan.t\"\n");
+               }
+               genaddproc();
+               genother();
+               genaddqueue();
+               genunio();
+               genconditionals();
+               gensvmap();
+               if (!run) fatal("no runable process", (char *)0);
+               fprintf(tc, "void\n");
+               fprintf(tc, "active_procs(void)\n{\n");
+#if 1
+               fprintf(tc, "   if (!permuted) {\n");
+                       reverse_procs(run);
+               fprintf(tc, "   } else {\n");
+                       forward_procs(run);
+               fprintf(tc, "   }\n");
+#else
+                       reverse_procs(run);
+#endif
+               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);
+       } 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 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, "#else\n");
+               fprintf(tc, "extern short proc_offset[];\n");
+               fprintf(tc, "#endif\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 *stopstate[];\n");
+               fprintf(tc, "extern uchar *visstate[];\n\n");
+               fprintf(tc, "extern short *mapstate[];\n");
+
+               fprintf(tc, "void\nini_claim(int n, int h)\n{");
+               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, "#endif\n");
+               fprintf(tc, "\tset_claim();\n");
+               genother();
+               fprintf(tc, "\n\tswitch (n) {\n");
+               genaddproc();
+               fprintf(tc, "\t}\n");
+               fprintf(tc, "\n}\n");
+               fprintf(tc, "int\nstep_claim(int o_pm, int tau, int tt, int ot, Trans *t)\n");
+               fprintf(tc, "{  int forw = t->forw; int _m = 0; extern char *noptr; int II=0;\n");
+               fprintf(tc, "   extern State now;\n");
+               fprintf(tc, "#define continue   return 0\n");
+               fprintf(tc, "#include \"pan_t.m\"\n");
+               fprintf(tc, "P999:\n\treturn _m;\n}\n");
+               fprintf(tc, "#undef continue\n");
+               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);
+       }
+}
+
+static int
+find_id(Symbol *s)
+{      ProcList *p;
+
+       if (s)
+       for (p = rdy; p; p = p->nxt)
+               if (s == p->n)
+                       return p->tn;
+       return 0;
+}
+
+static void
+dolen(Symbol *s, char *pre, int pid, int ai, int qln)
+{
+       if (ai > 0)
+               fprintf(tc, "\n\t\t\t ||    ");
+       fprintf(tc, "%s(", pre);
+       if (!(s->hidden&1))
+       {       if (s->context)
+                       fprintf(tc, "((P%d *)this)->", pid);
+               else
+                       fprintf(tc, "now.");
+       }
+       fprintf(tc, "%s", s->name);
+       if (qln > 1) fprintf(tc, "[%d]", ai);
+       fprintf(tc, ")");
+}
+
+struct AA {    char TT[9];     char CC[8]; };
+
+static struct AA BB[4] = {
+       { "Q_FULL_F",   " q_full" },
+       { "Q_FULL_T",   "!q_full" },
+       { "Q_EMPT_F",   " !q_len" },
+       { "Q_EMPT_T",   "  q_len" }
+       };
+
+static struct AA DD[4] = {
+       { "Q_FULL_F",   " q_e_f" },     /* empty or full */
+       { "Q_FULL_T",   "!q_full" },
+       { "Q_EMPT_F",   " q_e_f" },
+       { "Q_EMPT_T",   " q_len" }
+       };
+       /* this reduces the number of cases where 's' and 'r'
+          are considered conditionally safe under the
+          partial order reduction rules;  as a price for
+          this simple implementation, it also affects the
+          cases where nfull and nempty can be considered
+          safe -- since these are labeled the same way as
+          's' and 'r' respectively
+          it only affects reduction, not functionality
+        */
+
+void
+bb_or_dd(int j, int which)
+{
+       if (which)
+       {       if (has_unless)
+                       fprintf(tc, "%s", DD[j].CC);
+               else
+                       fprintf(tc, "%s", BB[j].CC);
+       } else
+       {       if (has_unless)
+                       fprintf(tc, "%s", DD[j].TT);
+               else
+                       fprintf(tc, "%s", BB[j].TT);
+       }
+}
+
+void
+Done_case(char *nm, Symbol *z)
+{      int j, k;
+       int nid = z->Nid;
+       int qln = z->nel;
+
+       fprintf(tc, "\t\tcase %d: if (", nid);
+       for (j = 0; j < 4; j++)
+       {       fprintf(tc, "\t(t->ty[i] == ");
+               bb_or_dd(j, 0);
+               fprintf(tc, " && (");
+               for (k = 0; k < qln; k++)
+               {       if (k > 0)
+                               fprintf(tc, "\n\t\t\t ||    ");
+                       bb_or_dd(j, 1);
+                       fprintf(tc, "(%s%s", nm, z->name);
+                       if (qln > 1)
+                               fprintf(tc, "[%d]", k);
+                       fprintf(tc, ")");
+               }
+               fprintf(tc, "))\n\t\t\t ");
+               if (j < 3)
+                       fprintf(tc, "|| ");
+               else
+                       fprintf(tc, "   ");
+       }
+       fprintf(tc, ") return 0; break;\n");
+}
+
+static void
+Docase(Symbol *s, int pid, int nid)
+{      int i, j;
+
+       fprintf(tc, "\t\tcase %d: if (", nid);
+       for (j = 0; j < 4; j++)
+       {       fprintf(tc, "\t(t->ty[i] == ");
+               bb_or_dd(j, 0);
+               fprintf(tc, " && (");
+               if (has_unless)
+               {       for (i = 0; i < s->nel; i++)
+                               dolen(s, DD[j].CC, pid, i, s->nel);
+               } else
+               {       for (i = 0; i < s->nel; i++)
+                               dolen(s, BB[j].CC, pid, i, s->nel);
+               }
+               fprintf(tc, "))\n\t\t\t ");
+               if (j < 3)
+                       fprintf(tc, "|| ");
+               else
+                       fprintf(tc, "   ");
+       }
+       fprintf(tc, ") return 0; break;\n");
+}
+
+static void
+genconditionals(void)
+{      Symbol *s;
+       int last=0, j;
+       extern Ordered  *all_names;
+       Ordered *walk;
+
+       fprintf(th, "#define LOCAL      1\n");
+       fprintf(th, "#define Q_FULL_F   2\n");
+       fprintf(th, "#define Q_EMPT_F   3\n");
+       fprintf(th, "#define Q_EMPT_T   4\n");
+       fprintf(th, "#define Q_FULL_T   5\n");
+       fprintf(th, "#define TIMEOUT_F  6\n");
+       fprintf(th, "#define GLOBAL     7\n");
+       fprintf(th, "#define BAD        8\n");
+       fprintf(th, "#define ALPHA_F    9\n");
+
+       fprintf(tc, "int\n");
+       fprintf(tc, "q_cond(short II, Trans *t)\n");
+       fprintf(tc, "{  int i = 0;\n");
+       fprintf(tc, "   for (i = 0; i < 6; i++)\n");
+       fprintf(tc, "   {       if (t->ty[i] == TIMEOUT_F) return %s;\n",
+                                       (Etimeouts)?"(!(trpt->tau&1))":"1");
+       fprintf(tc, "           if (t->ty[i] == ALPHA_F)\n");
+       fprintf(tc, "#ifdef GLOB_ALPHA\n");
+       fprintf(tc, "                   return 0;\n");
+       fprintf(tc, "#else\n\t\t\treturn ");
+       fprintf(tc, "(II+1 == (short) now._nr_pr && II+1 < MAXPROC);\n");
+       fprintf(tc, "#endif\n");
+
+       /* we switch on the chan name from the spec (as identified by
+        * the corresponding Nid number) rather than the actual qid
+        * because we cannot predict at compile time which specific qid
+        * will be accessed by the statement at runtime.  that is:
+        * we do not know which qid to pass to q_cond at runtime
+        * but we do know which name is used.  if it's a chan array, we
+        * must check all elements of the array for compliance (bummer)
+        */
+       fprintf(tc, "           switch (t->qu[i]) {\n");
+       fprintf(tc, "           case 0: break;\n");
+
+       for (walk = all_names; walk; walk = walk->next)
+       {       s = walk->entry;
+               if (s->owner) continue;
+               j = find_id(s->context);
+               if (s->type == CHAN)
+               {       if (last == s->Nid) continue;   /* chan array */
+                       last = s->Nid;
+                       Docase(s, j, last);
+               } else if (s->type == STRUCT)
+               {       /* struct may contain a chan */
+                       char pregat[128];
+                       extern void walk2_struct(char *, Symbol *);
+                       strcpy(pregat, "");
+                       if (!(s->hidden&1))
+                       {       if (s->context)
+                                       sprintf(pregat, "((P%d *)this)->",j);
+                               else
+                                       sprintf(pregat, "now.");
+                       }
+                       walk2_struct(pregat, s);
+               }
+       }
+       fprintf(tc, "   \tdefault: Uerror(\"unknown qid - q_cond\");\n");
+       fprintf(tc, "   \t\t\treturn 0;\n");
+       fprintf(tc, "   \t}\n");
+       fprintf(tc, "   }\n");
+       fprintf(tc, "   return 1;\n");
+       fprintf(tc, "}\n");
+}
+
+static void
+putproc(ProcList *p)
+{      Pid = p->tn;
+       Det = p->det;
+
+       if (Pid == claimnr
+       &&  separate == 1)
+       {       fprintf(th, "extern uchar reached%d[];\n", Pid);
+#if 0
+               fprintf(th, "extern short nstates%d;\n", Pid);
+#else
+               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",
+                       Pid, p->s->last?p->s->last->seqno:0);
+               fprintf(th, "#define src_claim  src_ln%d\n", claimnr);
+
+               return;
+       }
+       if (Pid != claimnr
+       &&  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",
+               Pid, p->s->maxel, p->n->name);
+       if (Pid == claimnr)
+       fprintf(th, "#define nstates_claim      nstates%d\n", Pid);
+       if (Pid == eventmapnr)
+       fprintf(th, "#define nstates_event      nstates%d\n", Pid);
+
+       fprintf(th, "#define endstate%d %d\n",
+               Pid, p->s->last?p->s->last->seqno:0);
+       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);
+
+       if (Pid == eventmapnr)
+       {       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");
+               fprintf(tc, "\n\n");
+       }
+       dumpsrc(p->s->maxel, Pid);
+}
+
+static void
+addTpe(int x)
+{      int i;
+
+       if (x <= 2) return;
+
+       for (i = 0; i < T_sum; i++)
+               if (TPE[i] == x)
+                       return;
+       TPE[(T_sum++)%2] = x;
+}
+
+static void
+cnt_seq(Sequence *s)
+{      Element *f;
+       SeqList *h;
+
+       if (s)
+       for (f = s->frst; f; f = f->nxt)
+       {       Tpe(f->n);      /* sets EPT */
+               addTpe(EPT[0]);
+               addTpe(EPT[1]);
+               for (h = f->sub; h; h = h->nxt)
+                       cnt_seq(h->this);
+               if (f == s->last)
+                       break;
+       }
+}
+
+static void
+typ_seq(Sequence *s)
+{
+       T_sum = 0;
+       TPE[0] = 2; TPE[1] = 0;
+       cnt_seq(s);
+       if (T_sum > 2)          /* more than one type */
+       {       TPE[0] = 5*DELTA;       /* non-mixing */
+               TPE[1] = 0;
+       }
+}
+
+static int
+hidden(Lextok *n)
+{
+       if (n)
+       switch (n->ntyp) {
+       case  FULL: case  EMPTY:
+       case NFULL: case NEMPTY: case TIMEOUT:
+               Nn[(T_mus++)%2] = n;
+               break;
+       case '!': case UMIN: case '~': case ASSERT: case 'c':
+               (void) hidden(n->lft);
+               break;
+       case '/': case '*': case '-': case '+':
+       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:
+               (void) hidden(n->lft);
+               (void) hidden(n->rgt);
+               break;
+       }
+       return T_mus;
+}
+
+static int
+getNid(Lextok *n)
+{
+       if (n->sym
+       &&  n->sym->type == STRUCT
+       &&  n->rgt && n->rgt->lft)
+               return getNid(n->rgt->lft);
+
+       if (!n->sym || n->sym->Nid == 0)
+       {       fatal("bad channel name '%s'",
+               (n->sym)?n->sym->name:"no name");
+       }
+       return n->sym->Nid;
+}
+
+static int
+valTpe(Lextok *n)
+{      int res = 2;
+       /*
+       2 = local
+       2+1         .. 2+1*DELTA = nfull,  's'  - require q_full==false
+       2+1+1*DELTA .. 2+2*DELTA = nempty, 'r'  - require q_len!=0
+       2+1+2*DELTA .. 2+3*DELTA = empty        - require q_len==0
+       2+1+3*DELTA .. 2+4*DELTA = full         - require q_full==true
+       5*DELTA = non-mixing (i.e., always makes the selection global)
+       6*DELTA = timeout (conditionally safe)
+       7*DELTA = @, process deletion (conditionally safe)
+        */
+       switch (n->ntyp) { /* a series of fall-thru cases: */
+       case   FULL:    res += DELTA;           /* add 3*DELTA + chan nr */
+       case  EMPTY:    res += DELTA;           /* add 2*DELTA + chan nr */
+       case    'r':
+       case NEMPTY:    res += DELTA;           /* add 1*DELTA + chan nr */
+       case    's':
+       case  NFULL:    res += getNid(n->lft);  /* add channel nr */
+                       break;
+
+       case TIMEOUT:   res = 6*DELTA; break;
+       case '@':       res = 7*DELTA; break;
+       default:        break;
+       }
+       return res;
+}
+
+static void
+Tpe(Lextok *n) /* mixing in selections */
+{
+       EPT[0] = 2; EPT[1] = 0;
+
+       if (!n) return;
+
+       T_mus = 0;
+       Nn[0] = Nn[1] = ZN;
+
+       if (n->ntyp == 'c')
+       {       if (hidden(n->lft) > 2)
+               {       EPT[0] = 5*DELTA; /* non-mixing */
+                       EPT[1] = 0;
+                       return;
+               }
+       } else
+               Nn[0] = n;
+
+       if (Nn[0]) EPT[0] = valTpe(Nn[0]);
+       if (Nn[1]) EPT[1] = valTpe(Nn[1]);
+}
+
+static void
+put_escp(Element *e)
+{      int n;
+       SeqList *x;
+
+       if (e->esc /* && e->n->ntyp != GOTO */ && e->n->ntyp != '.')
+       {       for (x = e->esc, n = 0; x; x = x->nxt, n++)
+               {       int i = huntele(x->this->frst, e->status, -1)->seqno;
+                       fprintf(tt, "\ttrans[%d][%d]->escp[%d] = %d;\n",
+                               Pid, e->seqno, n, i);
+                       fprintf(tt, "\treached%d[%d] = 1;\n",
+                               Pid, i);
+               }
+               for (x = e->esc, n=0; x; x = x->nxt, n++)
+               {       fprintf(tt, "   /* escape #%d: %d */\n", n,
+                               huntele(x->this->frst, e->status, -1)->seqno);
+                       put_seq(x->this, 2, 0); /* args?? */
+               }
+               fprintf(tt, "   /* end-escapes */\n");
+       }
+}
+
+static void
+put_sub(Element *e, int Tt0, int Tt1)
+{      Sequence *s = e->n->sl->this;
+       Element *g = ZE;
+       int a;
+
+       patch_atomic(s);
+       putskip(s->frst->seqno);
+       g = huntstart(s->frst);
+       a = g->seqno;
+
+       if (0) printf("put_sub %d -> %d -> %d\n", e->seqno, s->frst->seqno, a);
+
+       if ((e->n->ntyp == ATOMIC
+       ||  e->n->ntyp == D_STEP)
+       &&  scan_seq(s))
+               mark_seq(s);
+       s->last->nxt = e->nxt;
+
+       typ_seq(s);     /* sets TPE */
+
+       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);
+               comment(tm, e->n, 0);
+               fprintf(tm, "] */\n\t\t");
+
+               if (s->last->n->ntyp == BREAK)
+                       OkBreak = target(huntele(s->last->nxt,
+                               s->last->status, -1))->Seqno;
+               else
+                       OkBreak = -1;
+
+               if (!putcode(tm, s, e->nxt, 0, e->n->ln, e->seqno))
+               {
+                       fprintf(tm, "\n#if defined(C_States) && (HAS_TRACK==1)\n");
+                       fprintf(tm, "\t\tc_update((uchar *) &(now.c_state[0]));\n");
+                       fprintf(tm, "#endif\n");
+
+                       fprintf(tm, "\t\t_m = %d", getweight(s->frst->n));
+                       if (m_loss && s->frst->n->ntyp == 's')
+                               fprintf(tm, "+delta_m; delta_m = 0");
+                       fprintf(tm, "; goto P999;\n\n");
+               }
+       
+               fprintf(tb, "\tcase %d: ", uniq-1);
+               fprintf(tb, "/* STATE %d */\n", e->seqno);
+               fprintf(tb, "\t\tsv_restor();\n");
+               fprintf(tb, "\t\tgoto R999;\n");
+               if (e->nxt)
+                       a = huntele(e->nxt, e->status, -1)->seqno;
+               else
+                       a = 0;
+               tr_map(uniq-1, e);
+               fprintf(tt, "/*->*/\ttrans[%d][%d]\t= ",
+                       Pid, e->seqno);
+               fprintf(tt, "settr(%d,%d,%d,%d,%d,\"",
+                       e->Seqno, D_ATOM|inherit, a, uniq-1, uniq-1);
+               comment(tt, e->n, e->seqno);
+               fprintf(tt, "\", %d, ", (s->frst->status&I_GLOB)?1:0);
+               fprintf(tt, "%d, %d);\n", TPE[0], TPE[1]);
+               put_escp(e);
+       } else
+       {       /* ATOMIC or NON_ATOMIC */
+               fprintf(tt, "\tT = trans[ %d][%d] = ", Pid, e->seqno);
+               fprintf(tt, "settr(%d,%d,0,0,0,\"",
+                       e->Seqno, (e->n->ntyp == ATOMIC)?ATOM:0);
+               comment(tt, e->n, e->seqno);
+               if ((e->status&CHECK2)
+               ||  (g->status&CHECK2))
+                       s->frst->status |= I_GLOB;
+               fprintf(tt, "\", %d, %d, %d);",
+                       (s->frst->status&I_GLOB)?1:0, Tt0, Tt1);
+               blurb(tt, e);
+               fprintf(tt, "\tT->nxt\t= ");
+               fprintf(tt, "settr(%d,%d,%d,0,0,\"",
+                       e->Seqno, (e->n->ntyp == ATOMIC)?ATOM:0, a);
+               comment(tt, e->n, e->seqno);
+               fprintf(tt, "\", %d, ", (s->frst->status&I_GLOB)?1:0);
+               if (e->n->ntyp == NON_ATOMIC)
+               {       fprintf(tt, "%d, %d);", Tt0, Tt1);
+                       blurb(tt, e);
+                       put_seq(s, Tt0, Tt1);
+               } else
+               {       fprintf(tt, "%d, %d);", TPE[0], TPE[1]);
+                       blurb(tt, e);
+                       put_seq(s, TPE[0], TPE[1]);
+               }
+       }
+}
+
+typedef struct CaseCache {
+       int m, b, owner;
+       Element *e;
+       Lextok *n;
+       FSM_use *u;
+       struct CaseCache *nxt;
+} CaseCache;
+
+static CaseCache *casing[6];
+
+static int
+identical(Lextok *p, Lextok *q)
+{
+       if ((!p && q) || (p && !q))
+               return 0;
+       if (!p)
+               return 1;
+
+       if (p->ntyp    != q->ntyp
+       ||  p->ismtyp  != q->ismtyp
+       ||  p->val     != q->val
+       ||  p->indstep != q->indstep
+       ||  p->sym     != q->sym
+       ||  p->sq      != q->sq
+       ||  p->sl      != q->sl)
+               return 0;
+
+       return  identical(p->lft, q->lft)
+       &&      identical(p->rgt, q->rgt);
+}
+
+static int
+samedeads(FSM_use *a, FSM_use *b)
+{      FSM_use *p, *q;
+
+       for (p = a, q = b; p && q; p = p->nxt, q = q->nxt)
+               if (p->var != q->var
+               ||  p->special != q->special)
+                       return 0;
+       return (!p && !q);
+}
+
+static Element *
+findnext(Element *f)
+{      Element *g;
+
+       if (f->n->ntyp == GOTO)
+       {       g = get_lab(f->n, 1);
+               return huntele(g, f->status, -1);
+       }
+       return f->nxt;
+}
+
+static Element *
+advance(Element *e, int stopat)
+{      Element *f = e;
+
+       if (stopat)
+       while (f && f->seqno != stopat)
+       {       f = findnext(f);
+               if (!f)
+               {       break;
+               }
+               switch (f->n->ntyp) {
+               case GOTO:
+               case '.':
+               case PRINT:
+               case PRINTM:
+                       break;
+               default:
+                       return f;
+       }       }
+       return (Element *) 0;
+}
+
+static int
+equiv_merges(Element *a, Element *b)
+{      Element *f, *g;
+       int stopat_a, stopat_b;
+
+       if (a->merge_start)
+               stopat_a = a->merge_start;
+       else
+               stopat_a = a->merge;
+
+       if (b->merge_start)
+               stopat_b = b->merge_start;
+       else
+               stopat_b = b->merge;
+
+       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;       /* not reached */
+}
+
+static CaseCache *
+prev_case(Element *e, int owner)
+{      int j; CaseCache *nc;
+
+       switch (e->n->ntyp) {
+       case 'r':       j = 0; break;
+       case 's':       j = 1; break;
+       case 'c':       j = 2; break;
+       case ASGN:      j = 3; break;
+       case ASSERT:    j = 4; break;
+       default:        j = 5; break;
+       }
+       for (nc = casing[j]; nc; nc = nc->nxt)
+               if (identical(nc->n, e->n)
+               &&  samedeads(nc->u, e->dead)
+               &&  equiv_merges(nc->e, e)
+               &&  nc->owner == owner)
+                       return nc;
+
+       return (CaseCache *) 0;
+}
+
+static void
+new_case(Element *e, int m, int b, int owner)
+{      int j; CaseCache *nc;
+
+       switch (e->n->ntyp) {
+       case 'r':       j = 0; break;
+       case 's':       j = 1; break;
+       case 'c':       j = 2; break;
+       case ASGN:      j = 3; break;
+       case ASSERT:    j = 4; break;
+       default:        j = 5; break;
+       }
+       nc = (CaseCache *) emalloc(sizeof(CaseCache));
+       nc->owner = owner;
+       nc->m = m;
+       nc->b = b;
+       nc->e = e;
+       nc->n = e->n;
+       nc->u = e->dead;
+       nc->nxt = casing[j];
+       casing[j] = nc;
+}
+
+static int
+nr_bup(Element *e)
+{      FSM_use *u;
+       Lextok *v;
+       int nr = 0;
+
+       switch (e->n->ntyp) {
+       case ASGN:
+               nr++;
+               break;
+       case  'r':
+               if (e->n->val >= 1)
+                       nr++;   /* random recv */
+               for (v = e->n->rgt; v; v = v->rgt)
+               {       if ((v->lft->ntyp == CONST
+                       ||   v->lft->ntyp == EVAL))
+                               continue;
+                       nr++;
+               }
+               break;
+       default:
+               break;
+       }
+       for (u = e->dead; u; u = u->nxt)
+       {       switch (u->special) {
+               case 2:         /* dead after write */
+                       if (e->n->ntyp == ASGN
+                       &&  e->n->rgt->ntyp == CONST
+                       &&  e->n->rgt->val == 0)
+                               break;
+                       nr++;
+                       break;
+               case 1:         /* dead after read */
+                       nr++;
+                       break;
+       }       }
+       return nr;
+}
+
+static int
+nrhops(Element *e)
+{      Element *f = e, *g;
+       int cnt = 0;
+       int stopat;
+
+       if (e->merge_start)
+               stopat = e->merge_start;
+       else
+               stopat = e->merge;
+#if 0
+       printf("merge: %d merge_start %d - seqno %d\n",
+               e->merge, e->merge_start, e->seqno);
+#endif
+       do {
+               cnt += nr_bup(f);
+
+               if (f->n->ntyp == GOTO)
+               {       g = get_lab(f->n, 1);
+                       if (g->seqno == stopat)
+                               f = g;
+                       else
+                               f = huntele(g, f->status, stopat);
+               } else
+               {
+                       f = f->nxt;
+               }
+
+               if (f && !f->merge && !f->merge_single && f->seqno != stopat)
+               {       fprintf(tm, "\n\t\tbad 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",
+                               stopat, f->merge, f->merge_start, f->merge_single);
+                       break;
+               }
+       } while (f && f->seqno != stopat);
+
+       return cnt;
+}
+
+static void
+check_needed(void)
+{
+       if (multi_needed)
+       {       fprintf(tm, "(trpt+1)->bup.ovals = grab_ints(%d);\n\t\t",
+                       multi_needed);
+               multi_undo = multi_needed;
+               multi_needed = 0;
+       }
+}
+
+static void
+doforward(FILE *tm_fd, Element *e)
+{      FSM_use *u;
+
+       putstmnt(tm_fd, e->n, e->seqno);
+
+       if (e->n->ntyp != ELSE && Det)
+       {       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_fd, ";\n\t\t/* dead %d: %s */  ",
+                       u->special, u->var->name);
+
+               switch (u->special) {
+               case 2:         /* dead after write -- lval already bupped */
+                       if (e->n->ntyp == ASGN) /* could be recv or asgn */
+                       {       if (e->n->rgt->ntyp == CONST
+                               &&  e->n->rgt->val == 0)
+                                       continue;       /* already set to 0 */
+                       }
+                       if (e->n->ntyp != 'r')
+                       {       XZ.sym = u->var;
+                               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 */
+                       YZ[YZmax].sym = u->var; /* store for pan.b */
+                       CnT[YZcnt]++;           /* this step added bups */
+                       if (multi_oval)
+                       {       check_needed();
+                               fprintf(tm_fd, "(trpt+1)->bup.ovals[%d] = ",
+                                       multi_oval-1);
+                               multi_oval++;
+                       } else
+                               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_fd, ";\n\t\t");
+}
+
+static int
+dobackward(Element *e, int casenr)
+{
+       if (!any_undo(e->n) && CnT[YZcnt] == 0)
+       {       YZcnt--;
+               return 0;
+       }
+
+       if (!didcase)
+       {       fprintf(tb, "\n\tcase %d: ", casenr);
+               fprintf(tb, "/* STATE %d */\n\t\t", e->seqno);
+               didcase++;
+       }
+
+       _isok++;
+       while (CnT[YZcnt] > 0)  /* undo dead variable resets */
+       {       CnT[YZcnt]--;
+               YZmax--;
+               if (YZmax < 0)
+                       fatal("cannot happen, dobackward", (char *)0);
+               fprintf(tb, ";\n\t/* %d */\t", YZmax);
+               putname(tb, "", &YZ[YZmax], 0, " = trpt->bup.oval");
+               if (multi_oval > 0)
+               {       multi_oval--;
+                       fprintf(tb, "s[%d]", multi_oval-1);
+               }
+       }
+
+       if (e->n->ntyp != '.')
+       {       fprintf(tb, ";\n\t\t");
+               undostmnt(e->n, e->seqno);
+       }
+       _isok--;
+
+       YZcnt--;
+       return 1;
+}
+
+static void
+lastfirst(int stopat, Element *fin, int casenr)
+{      Element *f = fin, *g;
+
+       if (f->n->ntyp == GOTO)
+       {       g = get_lab(f->n, 1);
+               if (g->seqno == stopat)
+                       f = g;
+               else
+                       f = huntele(g, f->status, stopat);
+       } else
+               f = f->nxt;
+
+       if (!f || f->seqno == stopat
+       || (!f->merge && !f->merge_single))
+               return;
+       lastfirst(stopat, f, casenr);
+#if 0
+       fprintf(tb, "\n\t/* merge %d -- %d:%d %d:%d:%d (casenr %d)      ",
+               YZcnt,
+               f->merge_start, f->merge,
+               f->seqno, f?f->seqno:-1, stopat,
+               casenr);
+       comment(tb, f->n, 0);
+       fprintf(tb, " */\n");
+       fflush(tb);
+#endif
+       dobackward(f, casenr);
+}
+
+static int modifier;
+
+static void
+lab_transfer(Element *to, Element *from)
+{      Symbol *ns, *s = has_lab(from, (1|2|4));
+       Symbol *oc;
+       int ltp, usedit=0;
+
+       if (!s) return;
+
+       /* "from" could have all three labels -- rename
+        * to prevent jumps to the transfered copies
+        */
+       oc = context;   /* remember */
+       for (ltp = 1; ltp < 8; ltp *= 2)        /* 1, 2, and 4 */
+               if ((s = has_lab(from, ltp)) != (Symbol *) 0)
+               {       ns = (Symbol *) emalloc(sizeof(Symbol));
+                       ns->name = (char *) emalloc((int) strlen(s->name) + 4);
+                       sprintf(ns->name, "%s%d", s->name, modifier);
+
+                       context = s->context;
+                       set_lab(ns, to);
+                       usedit++;
+               }
+       context = oc;   /* restore */
+       if (usedit)
+       {       if (modifier++ > 990)
+                       fatal("modifier overflow error", (char *) 0);
+       }
+}
+
+static int
+case_cache(Element *e, int a)
+{      int bupcase = 0, casenr = uniq, fromcache = 0;
+       CaseCache *Cached = (CaseCache *) 0;
+       Element *f, *g;
+       int j, nrbups, mark, ntarget;
+       extern int ccache;
+
+       mark = (e->status&ATOM); /* could lose atomicity in a merge chain */
+
+       if (e->merge_mark > 0
+       ||  (merger && e->merge_in == 0))
+       {       /* state nominally unreachable (part of merge chains) */
+               if (e->n->ntyp != '.'
+               &&  e->n->ntyp != GOTO)
+               {       fprintf(tt, "\ttrans[%d][%d]\t= ", Pid, e->seqno);
+                       fprintf(tt, "settr(0,0,0,0,0,\"");
+                       comment(tt, e->n, e->seqno);
+                       fprintf(tt, "\",0,0,0);\n");
+               } else
+               {       fprintf(tt, "\ttrans[%d][%d]\t= ", Pid, e->seqno);
+                       casenr = 1; /* mhs example */
+                       j = a;
+                       goto haveit; /* pakula's example */
+               }
+
+               return -1;
+       }
+
+       fprintf(tt, "\ttrans[%d][%d]\t= ", Pid, e->seqno);
+
+       if (ccache
+       &&  Pid != claimnr
+       &&  Pid != eventmapnr
+       && (Cached = prev_case(e, Pid)))
+       {       bupcase = Cached->b;
+               casenr  = Cached->m;
+               fromcache = 1;
+
+               fprintf(tm, "/* STATE %d - line %d %s - [",
+                       e->seqno, e->n->ln, e->n->fn->name);
+               comment(tm, e->n, 0);
+               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);
+
+               goto gotit;
+       }
+
+       fprintf(tm, "\tcase %d: /* STATE %d - line %d %s - [",
+               uniq++, e->seqno, e->n->ln, e->n->fn->name);
+       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",
+               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)
+               fprintf(tm, "IfNotBlocked\n\t\t");
+
+       if (multi_needed != 0 || multi_undo != 0)
+               fatal("cannot happen, case_cache", (char *) 0);
+
+       if (nrbups > 1)
+       {       multi_oval = 1;
+               multi_needed = nrbups; /* allocated after edge condition */
+       } else
+               multi_oval = 0;
+
+       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");
+               fprintf(tm, "#endif\n\t\t");
+       }
+/* end */
+
+       /* the src xrefs have the numbers in e->seqno builtin */
+       fprintf(tm, "reached[%d][%d] = 1;\n\t\t", Pid, e->seqno);
+
+       doforward(tm, e);
+
+       if (e->merge_start)
+               ntarget = e->merge_start;
+       else
+               ntarget = e->merge;
+
+       if (ntarget)
+       {       f = e;
+
+more:          if (f->n->ntyp == GOTO)
+               {       g = get_lab(f->n, 1);
+                       if (g->seqno == ntarget)
+                               f = g;
+                       else
+                               f = huntele(g, f->status, ntarget);
+               } else
+                       f = f->nxt;
+
+
+               if (f && f->seqno != ntarget)
+               {       if (!f->merge && !f->merge_single)
+                       {       fprintf(tm, "/* stop at bad hop %d, %d */\n\t\t",
+                                       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, ntarget);
+                       fprintf(tm, "reached[%d][%d] = 1;\n\t\t", Pid, f->seqno);
+                       YZcnt++;
+                       lab_transfer(e, f);
+                       mark = f->status&(ATOM|L_ATOM); /* last step wins */
+                       doforward(tm, f);
+                       if (f->merge_in == 1) f->merge_mark++;
+
+                       goto more;
+       }       }
+out:
+       fprintf(tm, "_m = %d", getweight(e->n));
+       if (m_loss && e->n->ntyp == 's') fprintf(tm, "+delta_m; delta_m = 0");
+       fprintf(tm, "; goto P999; /* %d */\n", YZcnt);
+
+       multi_needed = 0;
+       didcase = 0;
+
+       if (ntarget)
+               lastfirst(ntarget, e, casenr); /* mergesteps only */
+
+       dobackward(e, casenr);                  /* the original step */
+
+       fprintf(tb, ";\n\t\t");
+
+       if (e->merge || e->merge_start)
+       {       if (!didcase)
+               {       fprintf(tb, "\n\tcase %d: ", casenr);
+                       fprintf(tb, "/* STATE %d */", e->seqno);
+                       didcase++;
+               } else
+                       fprintf(tb, ";");
+       } else
+               fprintf(tb, ";");
+       fprintf(tb, "\n\t\t");
+
+       if (multi_undo)
+       {       fprintf(tb, "ungrab_ints(trpt->bup.ovals, %d);\n\t\t",
+                       multi_undo);
+               multi_undo = 0;
+       }
+       if (didcase)
+       {       fprintf(tb, "goto R999;\n");
+               bupcase = casenr;
+       }
+
+       if (!e->merge && !e->merge_start)
+               new_case(e, casenr, bupcase, Pid);
+
+gotit:
+       j = a;
+       if (e->merge_start)
+               j = e->merge_start;
+       else if (e->merge)
+               j = e->merge;
+haveit:
+       fprintf(tt, "%ssettr(%d,%d,%d,%d,%d,\"", fromcache?"/* c */ ":"",
+               e->Seqno, mark, j, casenr, bupcase);
+
+       return (fromcache)?0:casenr;
+}
+
+static void
+put_el(Element *e, int Tt0, int Tt1)
+{      int a, casenr, Global_ref;
+       Element *g = ZE;
+
+       if (e->n->ntyp == GOTO)
+       {       g = get_lab(e->n, 1);
+               g = huntele(g, e->status, -1);
+               cross_dsteps(e->n, g->n);
+               a = g->seqno;
+       } else if (e->nxt)
+       {       g = huntele(e->nxt, e->status, -1);
+               a = g->seqno;
+       } else
+               a = 0;
+       if (g
+       &&  (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 */
+       if (e->merge_start || e->merge)
+               goto non_generic;
+
+       /*** avoid duplicate or redundant cases in pan.m ***/
+       switch (e->n->ntyp) {
+       case ELSE:
+               casenr = 2; /* standard else */
+               putskip(e->seqno);
+               goto generic_case;
+               /* break; */
+       case '.':
+       case GOTO:
+       case BREAK:
+               putskip(e->seqno); 
+               casenr = 1; /* standard goto */
+generic_case:  fprintf(tt, "\ttrans[%d][%d]\t= ", Pid, e->seqno);
+               fprintf(tt, "settr(%d,%d,%d,%d,0,\"",
+                       e->Seqno, e->status&ATOM, a, casenr);
+               break;
+#ifndef PRINTF
+       case PRINT:
+               goto non_generic;
+       case PRINTM:
+               goto non_generic;
+#endif
+       case 'c':
+               if (e->n->lft->ntyp == CONST
+               &&  e->n->lft->val == 1)        /* skip or true */
+               {       casenr = 1;
+                       putskip(e->seqno);
+                       goto generic_case;
+               }
+               goto non_generic;
+
+       default:
+non_generic:
+               casenr = case_cache(e, a);
+               if (casenr < 0) return; /* unreachable state */
+               break;
+       }
+       /* tailend of settr(...); */
+       Global_ref = (e->status&I_GLOB)?1:has_global(e->n);
+       comment(tt, e->n, e->seqno);
+       fprintf(tt, "\", %d, ", Global_ref);
+       if (Tt0 != 2)
+       {       fprintf(tt, "%d, %d);", Tt0, Tt1);
+       } else
+       {       Tpe(e->n);      /* sets EPT */
+               fprintf(tt, "%d, %d);", EPT[0], EPT[1]);
+       }
+       if ((e->merge_start && e->merge_start != a)
+       ||  (e->merge && e->merge != a))
+       {       fprintf(tt, " /* m: %d -> %d,%d */\n",
+                       a, e->merge_start, e->merge);
+               fprintf(tt, "   reached%d[%d] = 1;",
+                       Pid, a); /* Sheinman's example */
+       }
+       fprintf(tt, "\n");
+
+       if (casenr > 2)
+               tr_map(casenr, e);
+       put_escp(e);
+}
+
+static void
+nested_unless(Element *e, Element *g)
+{      struct SeqList *y = e->esc, *z = g->esc;
+
+       for ( ; y && z; y = y->nxt, z = z->nxt)
+               if (z->this != y->this)
+                       break;
+       if (!y && !z)
+               return;
+
+       if (g->n->ntyp != GOTO
+       &&  g->n->ntyp != '.'
+       &&  e->sub->nxt)
+       {       printf("error: (%s:%d) saw 'unless' on a guard:\n",
+                       (e->n)?e->n->fn->name:"-",
+                       (e->n)?e->n->ln:0);
+               printf("=====>instead of\n");
+               printf("        do (or if)\n");
+               printf("        :: ...\n");
+               printf("        :: stmnt1 unless stmnt2\n");
+               printf("        od (of fi)\n");
+               printf("=====>use\n");
+               printf("        do (or if)\n");
+               printf("        :: ...\n");
+               printf("        :: stmnt1\n");
+               printf("        od (or fi) unless stmnt2\n");
+               printf("=====>or rewrite\n");
+       }
+}
+
+static void
+put_seq(Sequence *s, int Tt0, int Tt1)
+{      SeqList *h;
+       Element *e, *g;
+       int a, deadlink;
+
+       if (0) printf("put_seq %d\n", s->frst->seqno);
+
+       for (e = s->frst; e; e = e->nxt)
+       {
+               if (0) printf(" step %d\n", e->seqno);
+               if (e->status & DONE)
+               {
+                       if (0) printf("         done before\n");
+                       goto checklast;
+               }
+               e->status |= DONE;
+
+               if (e->n->ln)
+                       putsrc(e);
+
+               if (e->n->ntyp == UNLESS)
+               {
+                       if (0) printf("         an unless\n");
+                       put_seq(e->sub->this, Tt0, Tt1);
+               } else if (e->sub)
+               {
+                       if (0) printf("         has sub\n");
+                       fprintf(tt, "\tT = trans[%d][%d] = ",
+                               Pid, e->seqno);
+                       fprintf(tt, "settr(%d,%d,0,0,0,\"",
+                               e->Seqno, e->status&ATOM);
+                       comment(tt, e->n, e->seqno);
+                       if (e->status&CHECK2)
+                               e->status |= I_GLOB;
+                       fprintf(tt, "\", %d, %d, %d);",
+                               (e->status&I_GLOB)?1:0, Tt0, Tt1);
+                       blurb(tt, e);
+                       for (h = e->sub; h; h = h->nxt)
+                       {       putskip(h->this->frst->seqno);
+                               g = huntstart(h->this->frst);
+                               if (g->esc)
+                                       nested_unless(e, g);
+                               a = g->seqno;
+
+                               if (g->n->ntyp == 'c'
+                               &&  g->n->lft->ntyp == CONST
+                               &&  g->n->lft->val == 0         /* 0 or false */
+                               && !g->esc)
+                               {       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:"");
+                               } else
+                                       deadlink = 0;
+                               if (0) printf("                 settr %d %d\n", a, 0);
+                               if (h->nxt)
+                                       fprintf(tt, "\tT = T->nxt\t= ");
+                               else
+                                       fprintf(tt, "\t    T->nxt\t= ");
+                               fprintf(tt, "settr(%d,%d,%d,0,0,\"",
+                                       e->Seqno, e->status&ATOM, a);
+                               comment(tt, e->n, e->seqno);
+                               if (g->status&CHECK2)
+                                       h->this->frst->status |= I_GLOB;
+                               fprintf(tt, "\", %d, %d, %d);",
+                                       (h->this->frst->status&I_GLOB)?1:0,
+                                       Tt0, Tt1);
+                               blurb(tt, e);
+                               if (deadlink)
+                                       fprintf(tt, "#endif\n");
+                       }
+                       for (h = e->sub; h; h = h->nxt)
+                               put_seq(h->this, Tt0, Tt1);
+               } else
+               {
+                       if (0) printf("         [non]atomic %d\n", e->n->ntyp);
+                       if (e->n->ntyp == ATOMIC
+                       ||  e->n->ntyp == D_STEP
+                       ||  e->n->ntyp == NON_ATOMIC)
+                               put_sub(e, Tt0, Tt1);
+                       else 
+                       {
+                               if (0) printf("                 put_el %d\n", e->seqno);
+                               put_el(e, Tt0, Tt1);
+                       }
+               }
+checklast:     if (e == s->last)
+                       break;
+       }
+       if (0) printf("put_seq done\n");
+}
+
+static void
+patch_atomic(Sequence *s)      /* catch goto's that break the chain */
+{      Element *f, *g;
+       SeqList *h;
+
+       for (f = s->frst; f ; f = f->nxt)
+       {
+               if (f->n && f->n->ntyp == GOTO)
+               {       g = get_lab(f->n,1);
+                       cross_dsteps(f->n, g->n);
+                       if ((f->status & (ATOM|L_ATOM))
+                       && !(g->status & (ATOM|L_ATOM)))
+                       {       f->status &= ~ATOM;
+                               f->status |= L_ATOM;
+                       }
+                       /* bridge atomics */
+                       if ((f->status & L_ATOM)
+                       &&  (g->status & (ATOM|L_ATOM)))
+                       {       f->status &= ~L_ATOM;
+                               f->status |= ATOM;
+                       }
+               } else
+               for (h = f->sub; h; h = h->nxt)
+                       patch_atomic(h->this);
+               if (f == s->extent)
+                       break;
+       }
+}
+
+static void
+mark_seq(Sequence *s)
+{      Element *f;
+       SeqList *h;
+
+       for (f = s->frst; f; f = f->nxt)
+       {       f->status |= I_GLOB;
+
+               if (f->n->ntyp == ATOMIC
+               ||  f->n->ntyp == NON_ATOMIC
+               ||  f->n->ntyp == D_STEP)
+                       mark_seq(f->n->sl->this);
+
+               for (h = f->sub; h; h = h->nxt)
+                       mark_seq(h->this);
+               if (f == s->last)
+                       return;
+       }
+}
+
+static Element *
+find_target(Element *e)
+{      Element *f;
+
+       if (!e) return e;
+
+       if (t_cyc++ > 32)
+       {       fatal("cycle of goto jumps", (char *) 0);
+       }
+       switch (e->n->ntyp) {
+       case  GOTO:
+               f = get_lab(e->n,1);
+               cross_dsteps(e->n, f->n);
+               f = find_target(f);
+               break;
+       case BREAK:
+               if (e->nxt)
+               {       f = find_target(huntele(e->nxt, e->status, -1));
+                       break;  /* new 5.0 -- was missing */
+               }
+               /* else fall through */
+       default:
+               f = e;
+               break;
+       }
+       return f;
+}
+
+Element *
+target(Element *e)
+{
+       if (!e) return e;
+       lineno = e->n->ln;
+       Fname  = e->n->fn;
+       t_cyc = 0;
+       return find_target(e);
+}
+
+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;
+
+       for (f = s->frst; f; f = f->nxt)
+       {       if ((f->status&CHECK2)
+               ||  has_global(f->n))
+                       return 1;
+               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, "\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)
+                       if (scan_seq(h->this))
+                               return 1;
+               if (f == s->last)
+                       break;
+       }
+       return 0;
+}
+
+static int
+glob_args(Lextok *n)
+{      int result = 0;
+       Lextok *v;
+
+       for (v = n->rgt; v; v = v->rgt)
+       {       if (v->lft->ntyp == CONST)
+                       continue;
+               if (v->lft->ntyp == EVAL)
+                       result += has_global(v->lft->lft);
+               else
+                       result += has_global(v->lft);
+       }
+       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;
+
+       if (!n) return 0;
+       if (AllGlobal) return 1;        /* global provided clause */
+
+       switch (n->ntyp) {
+       case ATOMIC:
+       case D_STEP:
+       case NON_ATOMIC:
+               return scan_seq(n->sl->this);
+
+       case '.':
+       case BREAK:
+       case GOTO:
+       case CONST:
+               return 0;
+
+       case   ELSE: return n->val; /* true if combined with chan refs */
+
+       case    's': return glob_args(n)!=0 || ((n->sym->xu&(XS|XX)) != XS);
+       case    'r': return glob_args(n)!=0 || ((n->sym->xu&(XR|XX)) != XR);
+       case    'R': return glob_args(n)!=0 || (((n->sym->xu)&(XR|XS|XX)) != (XR|XS));
+       case NEMPTY: return ((n->sym->xu&(XR|XX)) != XR);
+       case  NFULL: return ((n->sym->xu&(XS|XX)) != XS);
+       case   FULL: return ((n->sym->xu&(XR|XX)) != XR);
+       case  EMPTY: return ((n->sym->xu&(XS|XX)) != XS);
+       case  LEN:   return (((n->sym->xu)&(XR|XS|XX)) != (XR|XS));
+
+       case   NAME:
+               if (n->sym->context
+               || (n->sym->hidden&64)
+               ||  strcmp(n->sym->name, "_pid") == 0
+               ||  strcmp(n->sym->name, "_") == 0)
+                       return 0;
+               return 1;
+
+       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:
+               return 1;
+
+       /*      @ was 1 (global) since 2.8.5
+               in 3.0 it is considered local and
+               conditionally safe, provided:
+                       II is the youngest process
+                       and nrprocs < MAXPROCS
+       */
+       case '@': return 0;
+
+       case '!': case UMIN: case '~': case ASSERT:
+               return has_global(n->lft);
+
+       case '/': case '*': case '-': case '+':
+       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 ASGN:
+               return has_global(n->lft) || has_global(n->rgt);
+
+       case PRINT:
+               for (v = n->lft; v; v = v->rgt)
+                       if (has_global(v->lft)) return 1;
+               return 0;
+       case PRINTM:
+               return has_global(n->lft);
+       }
+       return 0;
+}
+
+static void
+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);
+}
+
+#define cat0(x)        putstmnt(fd,now->lft,m); fprintf(fd, x); \
+                       putstmnt(fd,now->rgt,m)
+#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)
+
+void
+putstmnt(FILE *fd, Lextok *now, int m)
+{      Lextok *v;
+       int i, j;
+
+       if (!now) { fprintf(fd, "0"); return; }
+       lineno = now->ln;
+       Fname  = now->fn;
+
+       switch (now->ntyp) {
+       case CONST:     fprintf(fd, "%d", now->val); break;
+       case '!':       cat3(" !(", now->lft, ")"); break;
+       case UMIN:      cat3(" -(", now->lft, ")"); break;
+       case '~':       cat3(" ~(", now->lft, ")"); break;
+
+       case '/':       cat1("/");  break;
+       case '*':       cat1("*");  break;
+       case '-':       cat1("-");  break;
+       case '+':       cat1("+");  break;
+       case '%':       cat1("%%"); break;
+       case '&':       cat1("&");  break;
+       case '^':       cat1("^");  break;
+       case '|':       cat1("|");  break;
+       case LT:        cat1("<");  break;
+       case GT:        cat1(">");  break;
+       case LE:        cat1("<="); break;
+       case GE:        cat1(">="); break;
+       case NE:        cat1("!="); break;
+       case EQ:        cat1("=="); break;
+       case OR:        cat1("||"); break;
+       case AND:       cat1("&&"); break;
+       case LSHIFT:    cat1("<<"); break;
+       case RSHIFT:    cat1(">>"); break;
+
+       case TIMEOUT:
+               if (separate == 2)
+                       fprintf(fd, "((tau)&1)");
+               else
+                       fprintf(fd, "((trpt->tau)&1)");
+               if (GenCode)
+                printf("spin: line %3d, warning: 'timeout' in d_step sequence\n",
+                       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);
+               if (eventmap
+               &&  strcmp(now->sym->name, eventmap) == 0)
+                       fatal("eventmap %s, (not runnable)", eventmap);
+
+               if (GenCode)
+                 fatal("'run' in d_step sequence (use atomic)",
+                       (char *)0);
+
+               fprintf(fd,"addproc(%d", fproc(now->sym->name));
+               for (v = now->lft, i = 0; v; v = v->rgt, i++)
+               {       cat2(", ", v->lft);
+               }
+               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);
+               }
+               for ( ; i < Npars; i++)
+                       fprintf(fd, ", 0");
+               fprintf(fd, ")");
+               break;
+
+       case ENABLED:
+               cat3("enabled(II, ", now->lft, ")");
+               break;
+
+       case NONPROGRESS:
+               /* o_pm&4=progress, tau&128=claim stutter */
+               if (separate == 2)
+               fprintf(fd, "(!(o_pm&4) && !(tau&128))");
+               else
+               fprintf(fd, "(!(trpt->o_pm&4) && !(trpt->tau&128))");
+               break;
+
+       case PC_VAL:
+               cat3("((P0 *) Pptr(", now->lft, "+BASE))->_p");
+               break;
+
+       case LEN:
+               if (!terse && !TestOnly && has_xu)
+               {       fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
+                       putname(fd, "q_R_check(", now->lft, m, "");
+                       fprintf(fd, ", II)) &&\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
+                       putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
+                       fprintf(fd, "\n#endif\n\t\t");
+               }
+               putname(fd, "q_len(", now->lft, m, ")");
+               break;
+
+       case FULL:
+               if (!terse && !TestOnly && has_xu)
+               {       fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
+                       putname(fd, "q_R_check(", now->lft, m, "");
+                       fprintf(fd, ", II)) &&\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
+                       putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
+                       fprintf(fd, "\n#endif\n\t\t");
+               }
+               putname(fd, "q_full(", now->lft, m, ")");
+               break;
+
+       case EMPTY:
+               if (!terse && !TestOnly && has_xu)
+               {       fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
+                       putname(fd, "q_R_check(", now->lft, m, "");
+                       fprintf(fd, ", II)) &&\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
+                       putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
+                       fprintf(fd, "\n#endif\n\t\t");
+               }
+               putname(fd, "(q_len(", now->lft, m, ")==0)");
+               break;
+
+       case NFULL:
+               if (!terse && !TestOnly && has_xu)
+               {       fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
+                       putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
+                       fprintf(fd, "\n#endif\n\t\t");
+               }
+               putname(fd, "(!q_full(", now->lft, m, "))");
+               break;
+
+       case NEMPTY:
+               if (!terse && !TestOnly && has_xu)
+               {       fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
+                       putname(fd, "q_R_check(", now->lft, m, ", II)) &&");
+                       fprintf(fd, "\n#endif\n\t\t");
+               }
+               putname(fd, "(q_len(", now->lft, m, ")>0)");
+               break;
+
+       case 's':
+               if (Pid == eventmapnr)
+               {       fprintf(fd, "if ((ot == 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
+                               &&  v->lft->ntyp != EVAL)
+                                       continue;
+                               fprintf(fd, " \\\n\t\t|| qrecv(");
+                               putname(fd, "", now->lft, m, ", ");
+                               putname(fd, "q_len(", now->lft, m, ")-1, ");
+                               fprintf(fd, "%d, 0) != ", i);
+                               if (v->lft->ntyp == CONST)
+                                       putstmnt(fd, v->lft, m);
+                               else /* EVAL */
+                                       putstmnt(fd, v->lft->lft, m);
+                       }
+                       fprintf(fd, ")\n");
+                       fprintf(fd, "\t\t       continue");
+                       putname(th, " || (x_y3_ == ", now->lft, m, ")");
+                       break;
+               }
+               if (TestOnly)
+               {       if (m_loss)
+                               fprintf(fd, "1");
+                       else
+                               putname(fd, "!q_full(", now->lft, m, ")");
+                       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, "if (q_%s",
+                       (u_sync > 0 && u_async == 0)?"len":"full");
+               putname(fd, "(", now->lft, m, "))\n");
+
+               if (m_loss)
+                       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 (u_sync && !u_async && rvopt)
+                       fprintf(fd, "\n\n\t\tif (no_recvs(II)) continue;\n");
+
+               fprintf(fd, "\n#ifdef HAS_CODE\n");
+               fprintf(fd, "\t\tif (readtrail && gui) {\n");
+               fprintf(fd, "\t\t\tchar simtmp[32];\n");
+               putname(fd, "\t\t\tsprintf(simvals, \"%%d!\", ", now->lft, m, ");\n");
+               _isok++;
+               for (v = now->rgt, i = 0; v; v = v->rgt, i++)
+               {       cat3("\t\tsprintf(simtmp, \"%%d\", ", v->lft, "); strcat(simvals, simtmp);");
+                       if (v->rgt)
+                       fprintf(fd, "\t\tstrcat(simvals, \",\");\n");
+               }
+               _isok--;
+               fprintf(fd, "\t\t}\n");
+               fprintf(fd, "#endif\n\t\t");
+
+               putname(fd, "\n\t\tqsend(", now->lft, m, "");
+               fprintf(fd, ", %d", now->val);
+               for (v = now->rgt, i = 0; v; v = v->rgt, i++)
+               {       cat2(", ", v->lft);
+               }
+               if (i > Mpars)
+               {       terse++;
+                       putname(stdout, "channel name: ", now->lft, m, "\n");
+                       terse--;
+                       printf("        %d msg parameters sent, %d expected\n", i, Mpars);
+                       fatal("too many pars in send", "");
+               }
+               for (j = i; i < Mpars; i++)
+                       fprintf(fd, ", 0");
+               fprintf(fd, ", %d)", j);
+               if (u_sync)
+               {       fprintf(fd, ";\n\t\t");
+                       if (u_async)
+                         putname(fd, "if (q_zero(", now->lft, m, ")) ");
+                       putname(fd, "{ boq = ", now->lft, m, "");
+                       if (GenCode)
+                         fprintf(fd, "; Uerror(\"rv-attempt in d_step\")");
+                       fprintf(fd, "; }");
+               }
+               if (m_loss)
+                       fprintf(fd, ";\n\t\t}\n\t\t"); /* end of m_loss else */
+               break;
+
+       case 'r':
+               if (Pid == eventmapnr)
+               {       fprintf(fd, "if ((ot == 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
+                               &&  v->lft->ntyp != EVAL)
+                                       continue;
+                               fprintf(fd, " \\\n\t\t|| qrecv(");
+                               putname(fd, "", now->lft, m, ", ");
+                               fprintf(fd, "0, %d, 0) != ", i);
+                               if (v->lft->ntyp == CONST)
+                                       putstmnt(fd, v->lft, m);
+                               else /* EVAL */
+                                       putstmnt(fd, v->lft->lft, m);
+                       }
+                       fprintf(fd, ")\n");
+                       fprintf(fd, "\t\t       continue");
+
+                       putname(tc, " || (x_y3_ == ", now->lft, m, ")");
+
+                       break;
+               }
+               if (TestOnly)
+               {       fprintf(fd, "((");
+                       if (u_sync) fprintf(fd, "(boq == -1 && ");
+
+                       putname(fd, "q_len(", now->lft, m, ")");
+
+                       if (u_sync && now->val <= 1)
+                       { putname(fd, ") || (boq == ",  now->lft,m," && ");
+                         putname(fd, "q_zero(", now->lft,m,"))");
+                       }
+
+                       fprintf(fd, ")");
+                       if (now->val == 0 || now->val == 2)
+                       {       for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
+                               { if (v->lft->ntyp == CONST)
+                                 { cat3("\n\t\t&& (", v->lft, " == ");
+                                   putname(fd, "qrecv(", now->lft, m, ", ");
+                                   fprintf(fd, "0, %d, 0))", i);
+                                 } else if (v->lft->ntyp == EVAL)
+                                 { cat3("\n\t\t&& (", v->lft->lft, " == ");
+                                   putname(fd, "qrecv(", now->lft, m, ", ");
+                                   fprintf(fd, "0, %d, 0))", i);
+                                 } else
+                                 {     j++; continue;
+                                 }
+                               }
+                       } else
+                       {       fprintf(fd, "\n\t\t&& Q_has(");
+                               putname(fd, "", now->lft, m, "");
+                               for (v = now->rgt, i=0; v; v = v->rgt, i++)
+                               {       if (v->lft->ntyp == CONST)
+                                       {       fprintf(fd, ", 1, ");
+                                               putstmnt(fd, v->lft, m);
+                                       } else if (v->lft->ntyp == EVAL)
+                                       {       fprintf(fd, ", 1, ");
+                                               putstmnt(fd, v->lft->lft, m);
+                                       } else
+                                       {       fprintf(fd, ", 0, 0");
+                               }       }
+                               for ( ; i < Mpars; i++)
+                                       fprintf(fd, ", 0, 0");
+                               fprintf(fd, ")");
+                       }
+                       fprintf(fd, ")");
+                       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");
+               }
+               if (u_sync)
+               {       if (now->val >= 2)
+                       {       if (u_async)
+                               { fprintf(fd, "if (");
+                                 putname(fd, "q_zero(", now->lft,m,"))");
+                                 fprintf(fd, "\n\t\t{\t");
+                               }
+                               fprintf(fd, "uerror(\"polling ");
+                               fprintf(fd, "rv chan\");\n\t\t");
+                               if (u_async)
+                                 fprintf(fd, " continue;\n\t\t}\n\t\t");
+                               fprintf(fd, "IfNotBlocked\n\t\t");
+                       } else
+                       {       fprintf(fd, "if (");
+                               if (u_async == 0)
+                                 putname(fd, "boq != ", now->lft,m,") ");
+                               else
+                               { putname(fd, "q_zero(", now->lft,m,"))");
+                                 fprintf(fd, "\n\t\t{\tif (boq != ");
+                                 putname(fd, "",  now->lft,m,") ");
+                                 Bailout(fd, ";\n\t\t} else\n\t\t");
+                                 fprintf(fd, "{\tif (boq != -1) ");
+                               }
+                               Bailout(fd, ";\n\t\t");
+                               if (u_async)
+                                       fprintf(fd, "}\n\t\t");
+               }       }
+               putname(fd, "if (q_len(", now->lft, m, ") == 0) ");
+               Bailout(fd, "");
+
+               for (v = now->rgt, j=0; v; v = v->rgt)
+               {       if (v->lft->ntyp != CONST
+                       &&  v->lft->ntyp != EVAL)
+                               j++;    /* count settables */
+               }
+               fprintf(fd, ";\n\n\t\tXX=1");
+/* test */     if (now->val == 0 || now->val == 2)
+               {       for (v = now->rgt, i=0; v; v = v->rgt, i++)
+                       {       if (v->lft->ntyp == CONST)
+                               { fprintf(fd, ";\n\t\t");
+                                 cat3("if (", v->lft, " != ");
+                                 putname(fd, "qrecv(", now->lft, m, ", ");
+                                 fprintf(fd, "0, %d, 0)) ", i);
+                                 Bailout(fd, "");
+                               } else if (v->lft->ntyp == EVAL)
+                               { fprintf(fd, ";\n\t\t");
+                                 cat3("if (", v->lft->lft, " != ");
+                                 putname(fd, "qrecv(", now->lft, m, ", ");
+                                 fprintf(fd, "0, %d, 0)) ", i);
+                                 Bailout(fd, "");
+                       }       }
+               } else  /* random receive: val 1 or 3 */
+               {       fprintf(fd, ";\n\t\tif (!(XX = Q_has(");
+                       putname(fd, "", now->lft, m, "");
+                       for (v = now->rgt, i=0; v; v = v->rgt, i++)
+                       {       if (v->lft->ntyp == CONST)
+                               {       fprintf(fd, ", 1, ");
+                                       putstmnt(fd, v->lft, m);
+                               } else if (v->lft->ntyp == EVAL)
+                               {       fprintf(fd, ", 1, ");
+                                       putstmnt(fd, v->lft->lft, m);
+                               } else
+                               {       fprintf(fd, ", 0, 0");
+                       }       }
+                       for ( ; i < Mpars; i++)
+                               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 (j == 0 && now->val >= 2)
+               {       fprintf(fd, ";\n\t\t");
+                       break;  /* poll without side-effect */
+               }
+
+               if (!GenCode)
+               {       int jj = 0;
+                       fprintf(fd, ";\n\t\t");
+                       /* no variables modified */
+                       if (j == 0 && now->val == 0)
+                       {       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");
+                       }
+
+                       for (v = now->rgt; v; v = v->rgt)
+                               if ((v->lft->ntyp != CONST
+                               &&   v->lft->ntyp != EVAL))
+                                       jj++;   /* nr of vars needing bup */
+
+                       if (jj)
+                       for (v = now->rgt, i = 0; v; v = v->rgt, i++)
+                       {       char tempbuf[64];
+
+                               if ((v->lft->ntyp == CONST
+                               ||   v->lft->ntyp == EVAL))
+                                       continue;
+
+                               if (multi_oval)
+                               {       check_needed();
+                                       sprintf(tempbuf, "(trpt+1)->bup.ovals[%d] = ",
+                                               multi_oval-1);
+                                       multi_oval++;
+                               } else
+                                       sprintf(tempbuf, "(trpt+1)->bup.oval = ");
+
+                               if (v->lft->sym && !strcmp(v->lft->sym->name, "_"))
+                               {       fprintf(fd, tempbuf);
+                                       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");
+                                       _isok--;
+                               }
+                       }
+
+                       if (jj) /* check for double entries q?x,x */
+                       {       Lextok *w;
+
+                               for (v = now->rgt; v; v = v->rgt)
+                               {       if (v->lft->ntyp != CONST
+                                       &&  v->lft->ntyp != EVAL
+                                       &&  v->lft->sym
+                                       &&  v->lft->sym->type != STRUCT /* not a struct */
+                                       &&  v->lft->sym->nel == 1       /* not an array */
+                                       &&  strcmp(v->lft->sym->name, "_") != 0)
+                                       for (w = v->rgt; w; w = w->rgt)
+                                               if (v->lft->sym == w->lft->sym)
+                                               {       fatal("cannot use var ('%s') in multiple msg fields",
+                                                               v->lft->sym->name);
+                       }       }               }
+               }
+/* set */      for (v = now->rgt, i = 0; v; v = v->rgt, i++)
+               {       if ((v->lft->ntyp == CONST
+                       ||   v->lft->ntyp == EVAL) && v->rgt)
+                               continue;
+                       fprintf(fd, ";\n\t\t");
+
+                       if (v->lft->ntyp != CONST
+                       &&  v->lft->ntyp != EVAL
+                       &&  v->lft->sym != NULL
+                       &&  strcmp(v->lft->sym->name, "_") != 0)
+                       {       nocast=1;
+                               _isok++;
+                               putstmnt(fd, v->lft, m);
+                               _isok--;
+                               nocast=0;
+                               fprintf(fd, " = ");
+                       }
+                       putname(fd, "qrecv(", now->lft, m, ", ");
+                       fprintf(fd, "XX-1, %d, ", i);
+                       fprintf(fd, "%d)", (v->rgt || now->val >= 2)?0:1);
+
+                       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))
+                       {       fprintf(fd, ";\n#ifdef VAR_RANGES");
+                               fprintf(fd, "\n\t\tlogval(\"");
+                               withprocname = terse = nocast = 1;
+                               _isok++;
+                               putstmnt(fd,v->lft,m);
+                               withprocname = terse = nocast = 0;
+                               fprintf(fd, "\", ");
+                               putstmnt(fd,v->lft,m);
+                               _isok--;
+                               fprintf(fd, ");\n#endif\n");
+                               fprintf(fd, "\t\t");
+                       }
+               }
+               fprintf(fd, ";\n\t\t");
+
+               fprintf(fd, "\n#ifdef HAS_CODE\n");
+               fprintf(fd, "\t\tif (readtrail && gui) {\n");
+               fprintf(fd, "\t\t\tchar simtmp[32];\n");
+               putname(fd, "\t\t\tsprintf(simvals, \"%%d?\", ", now->lft, m, ");\n");
+               _isok++;
+               for (v = now->rgt, i = 0; v; v = v->rgt, i++)
+               {       if (v->lft->ntyp != EVAL)
+                       { cat3("\t\tsprintf(simtmp, \"%%d\", ", v->lft, "); strcat(simvals, simtmp);");
+                       } else
+                       { cat3("\t\tsprintf(simtmp, \"%%d\", ", v->lft->lft, "); strcat(simvals, simtmp);");
+                       }
+                       if (v->rgt)
+                       fprintf(fd, "\t\tstrcat(simvals, \",\");\n");
+               }
+               _isok--;
+               fprintf(fd, "\t\t}\n");
+               fprintf(fd, "#endif\n\t\t");
+
+               if (u_sync)
+               {       putname(fd, "if (q_zero(", now->lft, m, "))");
+                       fprintf(fd, "\n\t\t{    boq = -1;\n");
+
+                       fprintf(fd, "#ifndef NOFAIR\n"); /* NEW 3.0.8 */
+                       fprintf(fd, "\t\t\tif (fairness\n");
+                       fprintf(fd, "\t\t\t&& !(trpt->o_pm&32)\n");
+                       fprintf(fd, "\t\t\t&& (now._a_t&2)\n");
+                       fprintf(fd, "\t\t\t&&  now._cnt[now._a_t&1] == II+2)\n");
+                       fprintf(fd, "\t\t\t{    now._cnt[now._a_t&1] -= 1;\n");
+                       fprintf(fd, "#ifdef VERI\n");
+                       fprintf(fd, "\t\t\t     if (II == 1)\n");
+                       fprintf(fd, "\t\t\t             now._cnt[now._a_t&1] = 1;\n");
+                       fprintf(fd, "#endif\n");
+                       fprintf(fd, "#ifdef DEBUG\n");
+                       fprintf(fd, "\t\t\tprintf(\"%%3d: proc %%d fairness \", depth, II);\n");
+                       fprintf(fd, "\t\t\tprintf(\"Rule 2: --cnt to %%d (%%d)\\n\",\n");
+                       fprintf(fd, "\t\t\t     now._cnt[now._a_t&1], now._a_t);\n");
+                       fprintf(fd, "#endif\n");
+                       fprintf(fd, "\t\t\t     trpt->o_pm |= (32|64);\n");
+                       fprintf(fd, "\t\t\t}\n");
+                       fprintf(fd, "#endif\n");
+
+                       fprintf(fd, "\n\t\t}");
+               }
+               break;
+
+       case 'R':
+               if (!terse && !TestOnly && has_xu)
+               {       fprintf(fd, "\n#ifndef XUSAFE\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&1) || ");
+                       fprintf(fd, "q_R_check(");
+                       putname(fd, "", now->lft, m, ", II)) &&\n\t\t");
+                       putname(fd, "(!(q_claim[", now->lft, m, "]&2) || ");
+                       putname(fd, "q_S_check(", now->lft, m, ", II)) &&");
+                       fprintf(fd, "\n#endif\n\t\t");
+               }
+               if (u_sync>0)
+                       putname(fd, "not_RV(", now->lft, m, ") && \\\n\t\t");
+
+               for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
+                       if (v->lft->ntyp != CONST
+                       &&  v->lft->ntyp != EVAL)
+                       {       j++; continue;
+                       }
+               if (now->val == 0 || i == j)
+               {       putname(fd, "(q_len(", now->lft, m, ") > 0");
+                       for (v = now->rgt, i=0; v; v = v->rgt, i++)
+                       {       if (v->lft->ntyp != CONST
+                               &&  v->lft->ntyp != EVAL)
+                                       continue;
+                               fprintf(fd, " \\\n\t\t&& qrecv(");
+                               putname(fd, "", now->lft, m, ", ");
+                               fprintf(fd, "0, %d, 0) == ", i);
+                               if (v->lft->ntyp == CONST)
+                                       putstmnt(fd, v->lft, m);
+                               else /* EVAL */
+                                       putstmnt(fd, v->lft->lft, m);
+                       }
+                       fprintf(fd, ")");
+               } else
+               {       putname(fd, "Q_has(", now->lft, m, "");
+                       for (v = now->rgt, i=0; v; v = v->rgt, i++)
+                       {       if (v->lft->ntyp == CONST)
+                               {       fprintf(fd, ", 1, ");
+                                       putstmnt(fd, v->lft, m);
+                               } else if (v->lft->ntyp == EVAL)
+                               {       fprintf(fd, ", 1, ");
+                                       putstmnt(fd, v->lft->lft, m);
+                               } else
+                                       fprintf(fd, ", 0, 0");
+                       }       
+                       for ( ; i < Mpars; i++)
+                               fprintf(fd, ", 0, 0");
+                       fprintf(fd, ")");
+               }
+               break;
+
+       case 'c':
+               preruse(fd, now->lft);  /* preconditions */
+               cat3("if (!(", now->lft, "))\n\t\t\t");
+               Bailout(fd, "");
+               break;
+
+       case  ELSE:
+               if (!GenCode)
+               {       if (separate == 2)
+                               fprintf(fd, "if (o_pm&1)\n\t\t\t");
+                       else
+                               fprintf(fd, "if (trpt->o_pm&1)\n\t\t\t");
+                       Bailout(fd, "");
+               } else
+               {       fprintf(fd, "/* else */");
+               }
+               break;
+
+       case '?':
+               if (now->lft)
+               {       cat3("( (", now->lft, ") ? ");
+               }
+               if (now->rgt)
+               {       cat3("(", now->rgt->lft, ") : ");
+                       cat3("(", now->rgt->rgt, ") )");
+               }
+               break;
+
+       case ASGN:
+               if (has_enabled)
+               fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+               _isok++;
+
+               if (!GenCode)
+               {       if (multi_oval)
+                       {       char tempbuf[64];
+                               check_needed();
+                               sprintf(tempbuf, "(trpt+1)->bup.ovals[%d] = ",
+                                       multi_oval-1);
+                               multi_oval++;
+                               cat3(tempbuf, now->lft, ";\n\t\t");
+                       } else
+                       {       cat3("(trpt+1)->bup.oval = ", now->lft, ";\n\t\t");
+               }       }
+               nocast = 1; putstmnt(fd,now->lft,m); nocast = 0;
+               fprintf(fd," = ");
+               _isok--;
+               putstmnt(fd,now->rgt,m);
+
+               if (now->sym->type != CHAN
+               ||  verbose > 0)
+               {       fprintf(fd, ";\n#ifdef VAR_RANGES");
+                       fprintf(fd, "\n\t\tlogval(\"");
+                       withprocname = terse = nocast = 1;
+                       _isok++;
+                       putstmnt(fd,now->lft,m);
+                       withprocname = terse = nocast = 0;
+                       fprintf(fd, "\", ");
+                       putstmnt(fd,now->lft,m);
+                       _isok--;
+                       fprintf(fd, ");\n#endif\n");
+                       fprintf(fd, "\t\t");
+               }
+               break;
+
+       case PRINT:
+               if (has_enabled)
+               fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+#ifdef PRINTF
+               fprintf(fd, "printf(%s", now->sym->name);
+#else
+               fprintf(fd, "Printf(%s", now->sym->name);
+#endif
+               for (v = now->lft; v; v = v->rgt)
+               {       cat2(", ", v->lft);
+               }
+               fprintf(fd, ")");
+               break;
+
+       case PRINTM:
+               if (has_enabled)
+               fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+               fprintf(fd, "printm(");
+               if (now->lft && now->lft->ismtyp)
+                       fprintf(fd, "%d", now->lft->val);
+               else
+                       putstmnt(fd, now->lft, m);
+               fprintf(fd, ")");
+               break;
+
+       case NAME:
+               if (!nocast && now->sym && Sym_typ(now) < SHORT)
+                       putname(fd, "((int)", now, m, ")");
+               else
+                       putname(fd, "", now, m, "");
+               break;
+
+       case   'p':
+               putremote(fd, now, m);
+               break;
+
+       case   'q':
+               if (terse)
+                       fprintf(fd, "%s", now->sym->name);
+               else
+                       fprintf(fd, "%d", remotelab(now));
+               break;
+
+       case C_EXPR:
+               fprintf(fd, "(");
+               plunk_expr(fd, now->sym->name);
+#if 1
+               fprintf(fd, ")");
+#else
+               fprintf(fd, ") /* %s */ ", now->sym->name);
+#endif
+               break;
+
+       case C_CODE:
+               if (now->sym)
+                       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 */
+               }
+
+               if (now->sym)
+                       plunk_inline(fd, now->sym->name, 1);
+               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");
+                       fprintf(fd, "\t\tc_update((uchar *) &(now.c_state[0]));\n");
+                       fprintf(fd, "#endif\n");
+               }
+               break;
+
+       case ASSERT:
+               if (has_enabled)
+                       fprintf(fd, "if (TstOnly) return 1;\n\t\t");
+
+               cat3("assert(", now->lft, ", ");
+               terse = nocast = 1;
+               cat3("\"", now->lft, "\", II, tt, t)");
+               terse = nocast = 0;
+               break;
+
+       case '.':
+       case BREAK:
+       case GOTO:
+               if (Pid == eventmapnr)
+                       fprintf(fd, "Uerror(\"cannot get here\")");
+               putskip(m);
+               break;
+
+       case '@':
+               if (Pid == eventmapnr)
+               {       fprintf(fd, "return 0");
+                       break;
+               }
+
+               if (has_enabled)
+               {       fprintf(fd, "if (TstOnly)\n\t\t\t");
+                       fprintf(fd, "return (II+1 == now._nr_pr);\n\t\t");
+               }
+               fprintf(fd, "if (!delproc(1, II)) ");
+               Bailout(fd, "");
+               break;
+
+       default:
+               printf("spin: bad node type %d (.m) - line %d\n",
+                       now->ntyp, now->ln);
+               fflush(tm);
+               alldone(1);
+       }
+}
+
+void
+putname(FILE *fd, char *pre, Lextok *n, int m, char *suff) /* varref */
+{      Symbol *s = n->sym;
+       lineno = n->ln; Fname = n->fn;
+
+       if (!s)
+               fatal("no name - putname", (char *) 0);
+
+       if (s->context && context && s->type)
+               s = findloc(s);         /* it's a local var */
+
+       if (!s)
+       {       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);
+               s->type = INT;
+       }
+
+       if (s->type == PROCTYPE)
+               fatal("proctype-name '%s' used as array-name", s->name);
+
+       fprintf(fd, pre);
+       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);
+               } 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 (evalindex != 1)
+               fprintf(fd, "%s", s->name);
+
+       if (s->nel != 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");
+               }
+               /* an xr or xs reference to an array element
+                * becomes an exclusion tag on the array itself -
+                * which could result in invalidly labeling
+                * operations on other elements of this array to
+                * be also safe under the partial order reduction
+                * (see procedure has_global())
+                */
+
+               if (evalindex == 2)
+               {       fprintf(fd, "[%%d]");
+               } else if (evalindex == 1)
+               {       evalindex = 0;          /* no good if index is indexed array */
+                       fprintf(fd, ", ");
+                       putstmnt(fd, n->lft, m);
+                       evalindex = 1;
+               } else
+               {       if (terse
+                       || (n->lft
+                       &&  n->lft->ntyp == CONST
+                       &&  n->lft->val < s->nel)
+                       || (!n->lft && s->nel > 0))
+                       {       cat3("[", n->lft, "]");
+                       } else
+                       {       cat3("[ Index(", n->lft, ", ");
+                               fprintf(fd, "%d) ]", s->nel);
+                       }
+               }
+       }
+       if (s->type == STRUCT && n->rgt && n->rgt->lft)
+       {       putname(fd, ".", n->rgt->lft, m, "");
+       }
+       fprintf(fd, suff);
+}
+
+void
+putremote(FILE *fd, Lextok *n, int m)  /* remote reference */
+{      int promoted = 0;
+       int pt;
+
+       if (terse)
+       {       fprintf(fd, "%s", n->lft->sym->name);   /* proctype name */
+               if (n->lft->lft)
+               {       fprintf(fd, "[");
+                       putstmnt(fd, n->lft->lft, m);   /* pid */
+                       fprintf(fd, "]");
+               }
+               fprintf(fd, ".%s", n->sym->name);
+       } else
+       {       if (Sym_typ(n) < SHORT)
+               {       promoted = 1;
+                       fprintf(fd, "((int)");
+               }
+
+               pt = fproc(n->lft->sym->name);
+               fprintf(fd, "((P%d *)Pptr(", pt);
+               if (n->lft->lft)
+               {       fprintf(fd, "BASE+");
+                       putstmnt(fd, n->lft->lft, m);
+               } else
+                       fprintf(fd, "f_pid(%d)", pt);
+               fprintf(fd, "))->%s", n->sym->name);
+       }
+       if (n->rgt)
+       {       fprintf(fd, "[");
+               putstmnt(fd, n->rgt, m);        /* array var ref */
+               fprintf(fd, "]");
+       }
+       if (promoted) fprintf(fd, ")");
+}
+
+static int
+getweight(Lextok *n)
+{      /* this piece of code is a remnant of early versions
+        * of the verifier -- in the current version of Spin
+        * only non-zero values matter - so this could probably
+        * simply return 1 in all cases.
+        */
+       switch (n->ntyp) {
+       case 'r':     return 4;
+       case 's':     return 2;
+       case TIMEOUT: return 1;
+       case 'c':     if (has_typ(n->lft, TIMEOUT)) return 1;
+       }
+       return 3;
+}
+
+int
+has_typ(Lextok *n, int m)
+{
+       if (!n) return 0;
+       if (n->ntyp == m) return 1;
+       return (has_typ(n->lft, m) || has_typ(n->rgt, m));
+}
+
+static int runcount, opcount;
+
+static void
+do_count(Lextok *n, int checkop)
+{
+       if (!n) return;
+
+       switch (n->ntyp) {
+       case RUN:
+               runcount++;
+               break;
+       default:
+               if (checkop) opcount++;
+               break;
+       }
+       do_count(n->lft, checkop && (n->ntyp != RUN));
+       do_count(n->rgt, checkop);
+}
+
+void
+count_runs(Lextok *n)
+{
+       runcount = opcount = 0;
+       do_count(n, 1);
+       if (runcount > 1)
+               fatal("more than one run operator in expression", "");
+       if (runcount == 1 && opcount > 1)
+               fatal("use of run operator in compound expression", "");
+}
+
+void
+any_runs(Lextok *n)
+{
+       runcount = opcount = 0;
+       do_count(n, 0);
+       if (runcount >= 1)
+               fatal("run operator used in invalid context", "");
+}
diff --git a/trunk/verif/Spin/Src5.1.6/pangen2.h b/trunk/verif/Spin/Src5.1.6/pangen2.h
new file mode 100755 (executable)
index 0000000..58c1b78
--- /dev/null
@@ -0,0 +1,987 @@
+/***** spin: pangen2.h *****/
+
+/* Copyright (c) 1989-2007 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            */
+/* (c) 2007: small additions for V5.0 to support multi-core verifications */
+
+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\");",
+       "}",
+       "#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>",
+       "#include <stdarg.h>",
+       "#include <string.h>",
+       "#include <ctype.h>",
+       "#include <errno.h>",
+       "#if defined(WIN32) || defined(WIN64)",
+               "#include <time.h>",
+       "#else",
+               "#include <unistd.h>",
+               "#include <sys/times.h>",
+       "#endif",
+       "#include <sys/types.h>",       /* defines off_t */
+       "#include <sys/stat.h>",
+       "#include <fcntl.h>",
+
+       "#define Offsetof(X, Y) ((unsigned long)(&(((X *)0)->Y)))",
+       "#ifndef max",
+       "#define max(a,b) (((a)<(b)) ? (b) : (a))",
+       "#endif",
+       "#ifndef PRINTF",
+       "int Printf(const char *fmt, ...); /* prototype only */",
+       "#endif",
+       0,
+};
+
+static char *Preamble[] = {
+
+       "#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]--",
+       "#endif",
+
+       "#if !defined(SAFETY) && !defined(NOCOMP)",
+               /*
+                * V_A identifies states in the current statespace
+                * A_V identifies states in the 'other' statespace
+                * 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;",
+       "#else",
+               "#define V_A    0",
+               "#define A_V    0",
+               "#define S_A    0",
+       "#endif",
+
+"#ifdef MA",
+       "#undef onstack_now",
+       "#undef onstack_put",
+       "#undef onstack_zap",
+       "#define onstack_put()  ;",
+       "#define onstack_zap()  gstore((char *) &now, vsize, 4)",
+"#else",
+       "#if defined(FULLSTACK) && !defined(BITSTATE)",
+       "#define onstack_put()  trpt->ostate = Lstate",
+       "#define onstack_zap()  { \\",
+       "       if (trpt->ostate) \\",
+       "               trpt->ostate->tagged = \\",
+       "               (S_A)? (trpt->ostate->tagged&~V_A) : 0; \\",
+       "       }",
+       "#endif",
+"#endif",
+
+       "#ifndef NO_V_PROVISO",
+       "#define V_PROVISO",
+       "#endif",
+       "#if !defined(NO_RESIZE) && !defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(SPACE) && NCORE==1",
+       "       #define AUTO_RESIZE",
+       "#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",
+       "#if !defined(SAFETY) || defined(REACH)",
+       "       unsigned int D;",
+       "#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",
+       "       unsigned short ln;",    /* length of vector */
+       "       #else",
+       "       unsigned long ln;",     /* length of vector */
+       "       #endif",
+       "#endif",
+       "#if defined(AUTO_RESIZE) && !defined(BITSTATE)",
+       "       unsigned long m_K1;",
+       "#endif",
+       "       unsigned long 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",
+       "#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",
+       "       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) || (NCORE>1)",
+       "       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 SCHED",
+       "       /* based on Qadeer&Rehof, Tacas 2005, LNCS 3440, pp. 93-107 */",
+       "       #if NCORE>1",
+       "       #error \"-DSCHED cannot be combined with -DNCORE (yet)\"",
+       "       #endif",
+       "       int     sched_limit;",
+       "#endif",
+       "#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;",
+       "Trail  *trail, *trpt;",
+
+       "FILE   *efd;",
+       "uchar  *this;",
+       "long   maxdepth=10000;",
+       "long   omaxdepth=10000;",
+       "#ifdef SCHED",
+       "int    sched_max = 10;",
+       "#endif",
+       "#ifdef PERMUTED",
+       "       uchar   permuted = 1;",
+       "#else",
+       "       uchar   permuted = 0;",
+       "#endif",
+       "double quota;  /* time limit */",
+       "#if NCORE>1",
+       "long   z_handoff = -1;",
+       "#endif",
+       "#ifdef SC",    /* stack cycling */
+       "char   *stackfile;",
+       "#endif",
+       "uchar  *SS, *LL;",
+       "uchar  HASH_NR = 0;",
+       "",
+       "double memcnt = (double) 0;",
+       "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;",
+       "",
+       "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",
+       "};",
+       "#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;",
+       "#if defined(ZAPH) && defined(BITSTATE)",
+       "double zstates = 0;",
+       "#endif",
+       "int    c_init_run;",
+       "#ifdef BFS",
+       "double midrv=0, failedrv=0, revrv=0;",
+       "#endif",
+       "unsigned long  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;",
+       "int    whichtrail = 0, onlyproc = -1, silent = 0;",
+       "#endif",
+       "int    state_tables=0, fairness=0, no_rck=0, Nr_Trails=0;",
+       "char   simvals[128];",
+       "#ifndef INLINE",
+       "int    TstOnly=0;",
+       "#endif",
+       "unsigned long mask, nmask;",
+       "#ifdef BITSTATE",
+       "int    ssize=23;       /* 1 Mb */",
+       "#else",
+       "int    ssize=19;       /* 512K slots */",
+       "#endif",
+       "int    hmax=0, svmax=0, smax=0;",
+       "int    Maxbody=0, XX;",
+       "uchar  *noptr; /* used by macro Pptr(x) */",
+       "#ifdef VAR_RANGES",
+       "void logval(char *, int);",
+       "void dumpranges(void);",
+       "#endif",
+
+       "#ifdef MA",
+       "#define INLINE_REV",
+       "extern void dfa_init(unsigned short);",
+       "extern int  dfa_member(unsigned long);",
+       "extern int  dfa_store(uchar *);",
+       "unsigned int   maxgs = 0;",
+       "#endif",
+       "",
+       "#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",
+       "",
+       "State  comp_msk;",
+       "uchar  *Mask = (uchar *) &comp_msk;",
+       "#ifdef COLLAPSE",
+       "State  comp_tmp;",
+       "static char    *scratch = (char *) &comp_tmp;",
+       "#endif",
+
+       "Stack  *stack;         /* for queues, processes */",
+       "Svtack *svtack;        /* for old state vectors */",
+       "#ifdef BITSTATE",
+       "static unsigned int hfns = 3;  /* new default */",
+       "#endif",
+       "static unsigned long j1;",
+       "static unsigned long K1, K2;",
+       "static unsigned long j2, j3, j4;",
+       "#ifdef BITSTATE",
+#ifndef POWOW
+       "static long udmem;",
+#endif
+       "#endif",
+       "static long    A_depth = 0;",
+       "long   depth = 0;",
+       /* depth: not static to support -S2, but possible clash with embedded code */
+       "#if NCORE>1",
+       "long nr_handoffs = 0;",
+       "#endif",
+       "static uchar   warned = 0, iterative = 0, exclusive = 0, like_java = 0, every_error = 0;",
+       "static uchar   noasserts = 0, noends = 0, bounded = 0;",
+       "#if SYNC>0 && ASYNC==0",
+       "void set_recvs(void);",
+       "int  no_recvs(int);",
+       "#endif",
+       "#if SYNC",
+       "#define IfNotBlocked   if (boq != -1) continue;",
+       "#define UnBlock        boq = -1",
+       "#else",
+       "#define IfNotBlocked   /* cannot block */",
+       "#define UnBlock        /* don't bother */",
+       "#endif\n",
+       "#ifdef BITSTATE",
+       "int (*bstore)(char *, int);",
+       "int bstore_reg(char *, int);",
+#ifndef POWOW
+       "int bstore_mod(char *, int);",
+#endif
+       "#endif",
+       "void active_procs(void);",
+       "void cleanup(void);",
+       "void do_the_search(void);",
+       "void find_shorter(int);",
+       "void iniglobals(void);",
+       "void stopped(int);",
+       "void wrapup(void);",
+       "int *grab_ints(int);",
+       "void ungrab_ints(int *, int);",
+       0,
+};
+
+static char *Tail[] = {
+       "Trans *",
+       "settr( int t_id, int a, int b, int c, int d,",
+       "       char *t, int g, int tpe0, int tpe1)",
+       "{      Trans *tmp = (Trans *) emalloc(sizeof(Trans));\n",
+       "       tmp->atom  = a&(6|32);  /* only (2|8|32) have meaning */",
+       "       if (!g) tmp->atom |= 8; /* no global references */",
+       "       tmp->st    = b;",
+       "       tmp->tpe[0] = tpe0;",
+       "       tmp->tpe[1] = tpe1;",
+       "       tmp->tp    = t;",
+       "       tmp->t_id  = t_id;",
+       "       tmp->forw  = c;",
+       "       tmp->back  = d;",
+       "       return tmp;",
+       "}\n",
+       "Trans *",
+       "cpytr(Trans *a)",
+       "{      Trans *tmp = (Trans *) emalloc(sizeof(Trans));\n",
+       "       int i;",
+       "       tmp->atom  = a->atom;",
+       "       tmp->st    = a->st;",
+       "#ifdef HAS_UNLESS",
+       "       tmp->e_trans = a->e_trans;",
+       "       for (i = 0; i < HAS_UNLESS; i++)",
+       "               tmp->escp[i] = a->escp[i];",
+       "#endif",
+       "       tmp->tpe[0] = a->tpe[0];",
+       "       tmp->tpe[1] = a->tpe[1];",
+       "       for (i = 0; i < 6; i++)",
+       "       {       tmp->qu[i] = a->qu[i];",
+       "               tmp->ty[i] = a->ty[i];",
+       "       }",
+       "       tmp->tp    = (char *) emalloc(strlen(a->tp)+1);",
+       "       strcpy(tmp->tp, a->tp);",
+       "       tmp->t_id  = a->t_id;",
+       "       tmp->forw  = a->forw;",
+       "       tmp->back  = a->back;",
+       "       return tmp;",
+       "}\n",
+       "#ifndef NOREDUCE",
+       "int",
+       "srinc_set(int n)",
+       "{      if (n <= 2) return LOCAL;",
+       "       if (n <= 2+  DELTA) return Q_FULL_F; /* 's' or nfull  */",
+       "       if (n <= 2+2*DELTA) return Q_EMPT_F; /* 'r' or nempty */",
+       "       if (n <= 2+3*DELTA) return Q_EMPT_T; /* empty */",
+       "       if (n <= 2+4*DELTA) return Q_FULL_T; /* full  */",
+       "       if (n ==   5*DELTA) return GLOBAL;",
+       "       if (n ==   6*DELTA) return TIMEOUT_F;",
+       "       if (n ==   7*DELTA) return ALPHA_F;",
+       "       Uerror(\"cannot happen srinc_class\");",
+       "       return BAD;",
+       "}",
+       "int",
+       "srunc(int n, int m)",
+       "{      switch(m) {",
+       "       case Q_FULL_F: return n-2;",
+       "       case Q_EMPT_F: return n-2-DELTA;",
+       "       case Q_EMPT_T: return n-2-2*DELTA;",
+       "       case Q_FULL_T: return n-2-3*DELTA;",
+       "       case ALPHA_F:",
+       "       case TIMEOUT_F: return 257; /* non-zero, and > MAXQ */",
+       "       }",
+       "       Uerror(\"cannot happen srunc\");",
+       "       return 0;",
+       "}",
+       "#endif",
+       "int cnt;",
+       "#ifdef HAS_UNLESS",
+       "int",
+       "isthere(Trans *a, int b)", /* is b already in a's list? */
+       "{      Trans *t;",
+       "       for (t = a; t; t = t->nxt)",
+       "               if (t->t_id == b)",
+       "                       return 1;",
+       "       return 0;",
+       "}",
+       "#endif",
+       "#ifndef NOREDUCE",
+       "int",
+       "mark_safety(Trans *t) /* for conditional safety */",
+       "{      int g = 0, i, j, k;",
+       "",
+       "       if (!t) return 0;",
+       "       if (t->qu[0])",
+       "               return (t->qu[1])?2:1;  /* marked */",
+       "",
+       "       for (i = 0; i < 2; i++)",
+       "       {       j = srinc_set(t->tpe[i]);",
+       "               if (j >= GLOBAL && j != ALPHA_F)",
+       "                       return -1;",
+       "               if (j != LOCAL)",
+       "               {       k = srunc(t->tpe[i], j);",
+       "                       if (g == 0",
+       "                       ||  t->qu[0] != k",
+       "                       ||  t->ty[0] != j)",
+       "                       {       t->qu[g] = k;",
+       "                               t->ty[g] = j;",
+       "                               g++;",
+       "       }       }       }",
+       "       return g;",
+       "}",
+       "#endif",
+       "void",
+       "retrans(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])",
+       "       /* process n, with m states, is=initial state */",
+       "{      Trans *T0, *T1, *T2, *T3;",
+       "       int i, k;",
+       "#ifndef NOREDUCE",
+       "       int g, h, j, aa;",
+       "#endif",
+       "#ifdef HAS_UNLESS",
+       "       int p;",
+       "#endif",
+       "       if (state_tables >= 4)",
+       "       {       printf(\"STEP 1 proctype %%s\\n\", ",
+       "                       procname[n]);",
+       "               for (i = 1; i < m; i++)",
+       "               for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
+       "                       crack(n, i, T0, srcln);",
+       "               return;",
+       "       }",
+       "       do {",
+       "               for (i = 1, cnt = 0; i < m; i++)",
+       "               {       T2 = trans[n][i];",
+       "                       T1 = T2?T2->nxt:(Trans *)0;",
+       "/* prescan: */         for (T0 = T1; T0; T0 = T0->nxt)",
+       "/* choice in choice */ {       if (T0->st && trans[n][T0->st]",
+       "                               &&  trans[n][T0->st]->nxt)",
+       "                                       break;",
+       "                       }",
+       "#if 0",
+       "               if (T0)",
+       "               printf(\"\\tstate %%d / %%d: choice in choice\\n\",",
+       "               i, T0->st);",
+       "#endif",
+       "                       if (T0)",
+       "                       for (T0 = T1; T0; T0 = T0->nxt)",
+       "                       {       T3 = trans[n][T0->st];",
+       "                               if (!T3->nxt)",
+       "                               {       T2->nxt = cpytr(T0);",
+       "                                       T2 = T2->nxt;",
+       "                                       imed(T2, T0->st, n, i);",
+       "                                       continue;",
+       "                               }",
+       "                               do {    T3 = T3->nxt;",
+       "                                       T2->nxt = cpytr(T3);",
+       "                                       T2 = T2->nxt;",
+       "                                       imed(T2, T0->st, n, i);",
+       "                               } while (T3->nxt);",
+       "                               cnt++;",
+       "                       }",
+       "               }",
+       "       } while (cnt);",
+
+       "       if (state_tables >= 3)",
+       "       {       printf(\"STEP 2 proctype %%s\\n\", ",
+       "                       procname[n]);",
+       "               for (i = 1; i < m; i++)",
+       "               for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
+       "                       crack(n, i, T0, srcln);",
+       "               return;",
+       "       }",
+       "       for (i = 1; i < m; i++)",
+       "       {       if (trans[n][i] && trans[n][i]->nxt) /* optimize */",
+       "               {       T1 = trans[n][i]->nxt;",
+       "#if 0",
+       "                       printf(\"\\t\\tpull %%d (%%d) to %%d\\n\",",
+       "                       T1->st, T1->forw, i);",
+       "#endif",
+       "                       if (!trans[n][T1->st]) continue;",
+       "                       T0 = cpytr(trans[n][T1->st]);",
+       "                       trans[n][i] = T0;",
+       "                       reach[T1->st] = 1;",
+       "                       imed(T0, T1->st, n, i);",
+       "                       for (T1 = T1->nxt; T1; T1 = T1->nxt)",
+       "                       {",
+       "#if 0",
+       "                       printf(\"\\t\\tpull %%d (%%d) to %%d\\n\",",
+       "                               T1->st, T1->forw, i);",
+       "#endif",
+       "                               if (!trans[n][T1->st]) continue;",
+       "                               T0->nxt = cpytr(trans[n][T1->st]);",
+       "                               T0 = T0->nxt;",
+       "                               reach[T1->st] = 1;",
+       "                               imed(T0, T1->st, n, i);",
+       "       }       }       }",
+       "       if (state_tables >= 2)",
+       "       {       printf(\"STEP 3 proctype %%s\\n\", ",
+       "                       procname[n]);",
+       "               for (i = 1; i < m; i++)",
+       "               for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
+       "                       crack(n, i, T0, srcln);",
+       "               return;",
+       "       }",
+       "#ifdef HAS_UNLESS",
+       "       for (i = 1; i < m; i++)",
+       "       {       if (!trans[n][i]) continue;",
+       "               /* check for each state i if an",
+       "                * escape to some state p is defined",
+       "                * if so, copy and mark p's transitions",
+       "                * and prepend them to the transition-",
+       "                * list of state i",
+       "                */",
+       "        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)",
+       "                       {       if (isthere(trans[n][i], T1->t_id))",
+       "                                       continue;",
+       "                               T2 = cpytr(T1);",
+       "                               T2->e_trans = p;",
+       "                               T2->nxt = trans[n][i];",
+       "                               trans[n][i] = T2;",
+       "               }       }",
+       "        } else /* outermost unless checked first */",
+       "        {      Trans *T4;",
+       "               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])",
+       "                       for (T1 = trans[n][p]; T1; T1 = T1->nxt)",
+       "                       {       if (isthere(trans[n][i], T1->t_id))",
+       "                                       continue;",
+       "                               T2 = cpytr(T1);",
+       "                               T2->nxt = (Trans *) 0;",
+       "                               T2->e_trans = p;",
+       "                               if (T3) T3->nxt = T2;",
+       "                               else    T4 = T2;",
+       "                               T3 = T2;",
+       "               }       }",
+       "               if (T4)",
+       "               {       T3->nxt = trans[n][i];",
+       "                       trans[n][i] = T4;",
+       "               }",
+       "        }",
+       "       }",
+       "#endif",
+
+       "#ifndef NOREDUCE",
+       "       for (i = 1; i < m; i++)",
+       "       {       if (a_cycles)",
+       "               { /* moves through these states are visible */",
+       "       #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",
+       "                       if (accpstate[n][i] || visstate[n][i])",
+       "                               goto degrade;",
+       "                       for (T1 = trans[n][i]; T1; T1 = T1->nxt)",
+       "                               if (accpstate[n][T1->st])",
+       "                                       goto degrade;",
+       "               }",
+       "               T1 = trans[n][i];",
+       "               if (!T1) continue;",
+       "               g = mark_safety(T1);    /* V3.3.1 */",
+       "               if (g < 0) goto degrade; /* global */",
+       "               /* check if mixing of guards preserves reduction */",
+       "               if (T1->nxt)",
+       "               {       k = 0;",
+       "                       for (T0 = T1; T0; T0 = T0->nxt)",
+       "                       {       if (!(T0->atom&8))",
+       "                                       goto degrade;",
+       "                               for (aa = 0; aa < 2; aa++)",
+       "                               {       j = srinc_set(T0->tpe[aa]);",
+       "                                       if (j >= GLOBAL && j != ALPHA_F)",
+       "                                               goto degrade;",
+       "                                       if (T0->tpe[aa]",
+       "                                       &&  T0->tpe[aa]",
+       "                                       !=  T1->tpe[0])",
+       "                                               k = 1;",
+       "                       }       }",
+       "                       /* g = 0;       V3.3.1 */",
+       "                       if (k)  /* non-uniform selection */",
+       "                       for (T0 = T1; T0; T0 = T0->nxt)",
+       "                       for (aa = 0; aa < 2; aa++)",
+       "                       {       j = srinc_set(T0->tpe[aa]);",
+       "                               if (j != LOCAL)",
+       "                               {       k = srunc(T0->tpe[aa], j);",
+       "                                       for (h = 0; h < 6; h++)",
+       "                                               if (T1->qu[h] == k",
+       "                                               &&  T1->ty[h] == j)",
+       "                                                       break;",
+       "                                       if (h >= 6)",
+       "                                       {       T1->qu[g%%6] = k;",
+       "                                               T1->ty[g%%6] = j;",
+       "                                               g++;",
+       "                       }       }       }",
+       "                       if (g > 6)",
+       "                       {       T1->qu[0] = 0;  /* turn it off */",
+       "                               printf(\"pan: warning, line %%d, \",",
+       "                                       srcln[i]);",
+       "                               printf(\"too many stmnt types (%%d)\",",
+       "                                       g);",
+       "                               printf(\" in selection\\n\");",
+       "                         goto degrade;",
+       "                       }",
+       "               }",
+       "               /* mark all options global if >=1 is global */",
+       "               for (T1 = trans[n][i]; T1; T1 = T1->nxt)",
+       "                       if (!(T1->atom&8)) break;",
+       "               if (T1)",
+       "degrade:       for (T1 = trans[n][i]; T1; T1 = T1->nxt)",
+       "                       T1->atom &= ~8; /* mark as unsafe */",
+
+       "               /* can only mix 'r's or 's's if on same chan */",
+       "               /* and not mixed with other local operations */",
+       "               T1 = trans[n][i];",
+
+       "               if (!T1 || T1->qu[0]) continue;",
+
+       "               j = T1->tpe[0];",
+       "               if (T1->nxt && T1->atom&8)",
+       "               { if (j == 5*DELTA)",
+       "                 {     printf(\"warning: line %%d \", srcln[i]);",
+       "                       printf(\"mixed condition \");",
+       "                       printf(\"(defeats reduction)\\n\");",
+       "                       goto degrade;",
+       "                 }",
+       "                 for (T0 = T1; T0; T0 = T0->nxt)",
+       "                 for (aa = 0; aa < 2; aa++)",
+       "                 if  (T0->tpe[aa] && T0->tpe[aa] != j)",
+       "                 {     printf(\"warning: line %%d \", srcln[i]);",
+       "                       printf(\"[%%d-%%d] mixed %%stion \",",
+       "                               T0->tpe[aa], j, ",
+       "                               (j==5*DELTA)?\"condi\":\"selec\");",
+       "                       printf(\"(defeats reduction)\\n\");",
+       "                       printf(\"       '%%s' <-> '%%s'\\n\",",
+       "                               T1->tp, T0->tp);",
+       "                       goto degrade;",
+       "               } }",
+       "       }",
+       "#endif",
+       "       for (i = 1; i < m; i++)",       /* R */
+       "       {       T2 = trans[n][i];",
+       "               if (!T2",
+       "               ||  T2->nxt",
+       "               ||  strncmp(T2->tp, \".(goto)\", 7)",
+       "               ||  !stopstate[n][i])",
+       "                       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]);",
+       "               for (i = 1; i < m; i++)",
+       "                       reach[i] = 1;",
+       "               tagtable(n, m, is, srcln, reach);",
+       "       } else",
+       "       for (i = 1; i < m; i++)",
+       "       {       int nrelse;",
+       "               if (strcmp(procname[n], \":never:\") != 0)",
+       "               {       for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
+       "                       {       if (T0->st == i",
+       "                               && strcmp(T0->tp, \"(1)\") == 0)",
+       "                               {       printf(\"error: proctype '%%s' \",",
+       "                                               procname[n]);",
+       "                                       printf(\"line %%d, state %%d: has un\",",
+       "                                               srcln[i], i);",
+       "                                       printf(\"conditional self-loop\\n\");",
+       "                                       pan_exit(1);",
+       "               }       }       }",
+       "               nrelse = 0;",
+       "               for (T0 = trans[n][i]; T0; T0 = T0->nxt)",
+       "               {       if (strcmp(T0->tp, \"else\") == 0)",
+       "                               nrelse++;",
+       "               }",
+       "               if (nrelse > 1)",
+       "               {       printf(\"error: proctype '%%s' state\",",
+       "                               procname[n]);",
+       "                       printf(\" %%d, inherits %%d\", i, nrelse);",
+       "                       printf(\" 'else' stmnts\\n\");",
+       "                       pan_exit(1);",
+       "       }       }",
+       "       if (!state_tables && strcmp(procname[n], \":never:\") == 0)",
+       "       {       int h = 0;",
+       "               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;",
+       "       }",
+       "#ifndef LOOPSTATE",
+       "       if (state_tables)",
+       "#endif",
+       "       do_dfs(n, m, is, srcln, reach, lstate);",
+       "#ifdef T_REVERSE",
+       "       /* process n, with m states, is=initial state -- reverse list */",
+       "       if (!state_tables && strcmp(procname[n], \":never:\") != 0)",
+       "       {       for (i = 1; i < m; i++)", /* for each state */
+       "               {       Trans *T4 = (Trans *) 0;",
+       "                       T1 = (Trans *) 0;", /* points to reversed list */
+       "                       T2 = (Trans *) 0;", /* points to first entry */
+       "                       T3 = (Trans *) 0;", /* remembers any else */
+       "                       for (T0 = trans[n][i]; T0; T0 = T4)",
+       "                       {       T4 = T0->nxt;",
+       "                               if (strcmp(T0->tp, \"else\") == 0)",
+       "                               {       T3 = T0;",
+       "                                       T0->nxt = (Trans *) 0;",
+       "                               } else",
+       "                               {       T0->nxt = T1;",
+       "                                       if (!T1) { T2 = T0; }",
+       "                                       T1 = T0;",
+       "                       }       }",
+       "                       if (T2 && T3) { T2->nxt = T3; }", /* at the end */
+       "                       trans[n][i] = T1; /* reversed -- else at end */",
+       "       }       }",
+       "#endif",
+       "}",
+       "void",
+       "imed(Trans *T, int v, int n, int j)    /* set intermediate state */",
+       "{      progstate[n][T->st] |= progstate[n][v];",
+       "       accpstate[n][T->st] |= accpstate[n][v];",
+       "       stopstate[n][T->st] |= stopstate[n][v];",
+       "       mapstate[n][j] = T->st;",
+       "}",
+       "void",
+       "tagtable(int n, int m, int is, short srcln[], uchar reach[])",
+       "{      Trans *z;\n",
+       "       if (is >= m || !trans[n][is]",
+       "       ||  is <= 0 || reach[is] == 0)",
+       "               return;",
+       "       reach[is] = 0;",
+       "       if (state_tables)",
+       "       for (z = trans[n][is]; z; z = z->nxt)",
+       "               crack(n, is, z, srcln);",
+       "       for (z = trans[n][is]; z; z = z->nxt)",
+       "       {",
+       "#ifdef HAS_UNLESS",
+       "               int i, j;",
+       "#endif",
+       "               tagtable(n, m, z->st, srcln, reach);",
+       "#ifdef HAS_UNLESS",
+       "               for (i = 0; i < HAS_UNLESS; i++)",
+       "               {       j = trans[n][is]->escp[i];",
+       "                       if (!j) break;",
+       "                       tagtable(n, m, j, srcln, reach);",
+       "               }",
+       "#endif",
+       "       }",
+       "}",
+       "void",
+       "dfs_table(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])",
+       "{      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 */",
+       "               {       lstate[is] = 1;",
+       "                       reach[is] |= 8; /* recorded */",
+       "                       if (state_tables)",
+       "                       {       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)",
+       "       {",
+       "#ifdef HAS_UNLESS",
+       "               int i, j;",
+       "#endif",
+       "               dfs_table(n, m, z->st, srcln, reach, lstate);",
+       "#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, lstate);",
+       "               }",
+       "#endif",
+       "       }",
+       "       reach[is] &= ~16; /* no longer on stack */",
+       "}",
+       "void",
+       "do_dfs(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])",
+       "{      int i;",
+       "       dfs_table(n, m, is, srcln, reach, lstate);",
+       "       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;",
+       "       printf(\"\tstate %%3d -(tr %%3d)-> state %%3d  \",",
+       "               j, z->forw, z->st);",
+       "       printf(\"[id %%3d tp %%3d\", z->t_id, z->tpe[0]);",
+       "       if (z->tpe[1]) printf(\",%%d\", z->tpe[1]);",
+       "#ifdef HAS_UNLESS",
+       "       if (z->e_trans)",
+       "               printf(\" org %%3d\", z->e_trans);",
+       "       else if (state_tables >= 2)",
+       "       for (i = 0; i < HAS_UNLESS; i++)",
+       "       {       if (!z->escp[i]) break;",
+       "               printf(\" esc %%d\", z->escp[i]);",
+       "       }",
+       "#endif",
+       "       printf(\"]\");",
+       "       printf(\" [%%s%%s%%s%%s%%s] line %%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]);",
+       "       for (i = 0; z->tp[i]; i++)",
+       "               if (z->tp[i] == \'\\n\')",
+       "                       printf(\"\\\\n\");",
+       "               else",
+       "                       putchar(z->tp[i]);",
+       "       if (z->qu[0])",
+       "       {       printf(\"\\t[\");",
+       "               for (i = 0; i < 6; i++)",
+       "                       if (z->qu[i])",
+       "                               printf(\"(%%d,%%d)\",",
+       "                               z->qu[i], z->ty[i]);",
+       "               printf(\"]\");",
+       "       }",
+       "       printf(\"\\n\");",
+       "       fflush(stdout);",
+       "}",
+       "",
+       "#ifdef VAR_RANGES",
+       "#define BYTESIZE       32      /* 2^8 : 2^3 = 256:8 = 32 */",
+       "",
+       "typedef struct Vr_Ptr {",
+       "       char    *nm;",
+       "       uchar   vals[BYTESIZE];",
+       "       struct Vr_Ptr *nxt;",
+       "} Vr_Ptr;",
+       "Vr_Ptr *ranges = (Vr_Ptr *) 0;",
+       "",
+       "void",
+       "logval(char *s, int v)",
+       "{      Vr_Ptr *tmp;",
+       "",
+       "       if (v<0 || v > 255) return;",
+       "       for (tmp = ranges; tmp; tmp = tmp->nxt)",
+       "               if (!strcmp(tmp->nm, s))",
+       "                       goto found;",
+       "       tmp = (Vr_Ptr *) emalloc(sizeof(Vr_Ptr));",
+       "       tmp->nxt = ranges;",
+       "       ranges = tmp;",
+       "       tmp->nm = s;",
+       "found:",
+       "       tmp->vals[(v)/8] |= 1<<((v)%%8);",
+       "}",
+       "",
+       "void",
+       "dumpval(uchar X[], int range)",
+       "{      int w, x, i, j = -1;",
+       "",
+       "       for (w = i = 0; w < range; w++)",
+       "       for (x = 0; x < 8; x++, i++)",
+       "       {",
+       "from:          if ((X[w] & (1<<x)))",
+       "               {       printf(\"%%d\", i);",
+       "                       j = i;",
+       "                       goto upto;",
+       "       }       }",
+       "       return;",
+       "       for (w = 0; w < range; w++)",
+       "       for (x = 0; x < 8; x++, i++)",
+       "       {",
+       "upto:          if (!(X[w] & (1<<x)))",
+       "               {       if (i-1 == j)",
+       "                               printf(\", \");",
+       "                       else",
+       "                               printf(\"-%%d, \", i-1);",
+       "                       goto from;",
+       "       }       }",
+       "       if (j >= 0 && j != 255)",
+       "               printf(\"-255\");",
+       "}",
+       "",
+       "void",
+       "dumpranges(void)",
+       "{      Vr_Ptr *tmp;",
+       "       printf(\"\\nValues assigned within \");",
+       "       printf(\"interval [0..255]:\\n\");",
+       "       for (tmp = ranges; tmp; tmp = tmp->nxt)",
+       "       {       printf(\"\\t%%s\\t: \", tmp->nm);",
+       "               dumpval(tmp->vals, BYTESIZE);",
+       "               printf(\"\\n\");",
+       "       }",
+       "}",
+       "#endif",
+       0,
+};
diff --git a/trunk/verif/Spin/Src5.1.6/pangen3.c b/trunk/verif/Spin/Src5.1.6/pangen3.c
new file mode 100755 (executable)
index 0000000..53b7604
--- /dev/null
@@ -0,0 +1,394 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+extern FILE    *th;
+extern int     claimnr, eventmapnr;
+
+typedef struct SRC {
+       short ln, st;   /* linenr, statenr */
+       Symbol *fn;     /* filename */
+       struct SRC *nxt;
+} SRC;
+
+static int     col;
+static Symbol  *lastfnm;
+static Symbol  lastdef;
+static int     lastfrom;
+static SRC     *frst = (SRC *) 0;
+static SRC     *skip = (SRC *) 0;
+
+extern void    sr_mesg(FILE *, int, int);
+
+static void
+putnr(int n)
+{
+       if (col++ == 8)
+       {       fprintf(th, "\n\t");
+               col = 1;
+       }
+       fprintf(th, "%3d, ", n);
+}
+
+static void
+putfnm(int j, Symbol *s)
+{
+       if (lastfnm && lastfnm == s && j != -1)
+               return;
+
+       if (lastfnm)
+               fprintf(th, "{ %s, %d, %d },\n\t",
+                       lastfnm->name,
+                       lastfrom,
+                       j-1);
+       lastfnm = s;
+       lastfrom = j;
+}
+
+static void
+putfnm_flush(int j)
+{
+       if (lastfnm)
+               fprintf(th, "{ %s, %d, %d }\n",
+                       lastfnm->name,
+                       lastfrom, j);
+}
+
+void
+putskip(int m) /* states that need not be reached */
+{      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;
+}
+
+void
+unskip(int m)  /* a state that needs to be reached after all */
+{      SRC *tmp, *lst=(SRC *)0;
+
+       for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
+               if (tmp->st == m)
+               {       if (tmp == skip)
+                               skip = skip->nxt;
+                       else if (lst)   /* always true, but helps coverity */
+                               lst->nxt = tmp->nxt;
+                       break;
+               }
+}
+
+void
+putsrc(Element *e)     /* match states to source lines */
+{      SRC *tmp;
+       int n, m;
+
+       if (!e || !e->n) return;
+
+       n = e->n->ln;
+       m = e->seqno;
+
+       for (tmp = frst; 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,
+                               tmp->ln, tmp->fn->name);
+                       return;
+               }
+       tmp = (SRC *) emalloc(sizeof(SRC));
+       tmp->ln = (short) n;
+       tmp->st = (short) m;
+       tmp->fn = e->n->fn;
+       tmp->nxt = frst;
+       frst = tmp;
+}
+
+static void
+dumpskip(int n, int m)
+{      SRC *tmp, *lst;
+       int j;
+
+       fprintf(th, "uchar reached%d [] = {\n\t", m);
+       for (j = 0, col = 0; j <= n; j++)
+       {       lst = (SRC *) 0;
+               for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
+                       if (tmp->st == j)
+                       {       putnr(1);
+                               if (lst)
+                                       lst->nxt = tmp->nxt;
+                               else
+                                       skip = tmp->nxt;
+                               break;
+                       }
+               if (!tmp)
+                       putnr(0);
+       }
+       fprintf(th, "};\n");
+
+       fprintf(th, "uchar *loopstate%d;\n", m);
+
+       if (m == claimnr)
+               fprintf(th, "#define reached_claim      reached%d\n", m);
+       if (m == eventmapnr)
+               fprintf(th, "#define reached_event      reached%d\n", m);
+
+       skip = (SRC *) 0;
+}
+
+void
+dumpsrc(int n, int m)
+{      SRC *tmp, *lst;
+       int j;
+
+       fprintf(th, "short src_ln%d [] = {\n\t", m);
+       for (j = 0, col = 0; j <= n; j++)
+       {       lst = (SRC *) 0;
+               for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
+                       if (tmp->st == j)
+                       {       putnr(tmp->ln);
+                               break;
+                       }
+               if (!tmp)
+                       putnr(0);
+       }
+       fprintf(th, "};\n");
+
+       lastfnm = (Symbol *) 0;
+       lastdef.name = "\"-\"";
+       fprintf(th, "S_F_MAP src_file%d [] = {\n\t", m);
+       for (j = 0, col = 0; j <= n; j++)
+       {       lst = (SRC *) 0;
+               for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
+                       if (tmp->st == j)
+                       {       putfnm(j, tmp->fn);
+                               if (lst)
+                                       lst->nxt = tmp->nxt;
+                               else
+                                       frst = tmp->nxt;
+                               break;
+                       }
+               if (!tmp)
+                       putfnm(j, &lastdef);
+       }
+       putfnm_flush(j);
+       fprintf(th, "};\n");
+
+       if (m == claimnr)
+               fprintf(th, "#define src_claim  src_ln%d\n", m);
+       if (m == eventmapnr)
+               fprintf(th, "#define src_event  src_ln%d\n", m);
+
+       frst = (SRC *) 0;
+       dumpskip(n, m);
+}
+
+#define Cat0(x)        comwork(fd,now->lft,m); fprintf(fd, x); \
+                       comwork(fd,now->rgt,m)
+#define Cat1(x)                fprintf(fd,"("); Cat0(x); fprintf(fd,")")
+#define Cat2(x,y)      fprintf(fd,x); comwork(fd,y,m)
+#define Cat3(x,y,z)    fprintf(fd,x); comwork(fd,y,m); fprintf(fd,z)
+
+static int
+symbolic(FILE *fd, Lextok *tv)
+{      Lextok *n; extern Lextok *Mtype;
+       int cnt = 1;
+
+       if (tv->ismtyp)
+       for (n = Mtype; n; n = n->rgt, cnt++)
+               if (cnt == tv->val)
+               {       fprintf(fd, "%s", n->lft->sym->name);
+                       return 1;
+               }
+       return 0;
+}
+
+static void
+comwork(FILE *fd, Lextok *now, int m)
+{      Lextok *v;
+       int i, j;
+
+       if (!now) { fprintf(fd, "0"); return; }
+       switch (now->ntyp) {
+       case CONST:     sr_mesg(fd, now->val, now->ismtyp); break;
+       case '!':       Cat3("!(", now->lft, ")"); break;
+       case UMIN:      Cat3("-(", now->lft, ")"); break;
+       case '~':       Cat3("~(", now->lft, ")"); break;
+
+       case '/':       Cat1("/");  break;
+       case '*':       Cat1("*");  break;
+       case '-':       Cat1("-");  break;
+       case '+':       Cat1("+");  break;
+       case '%':       Cat1("%%"); break;
+       case '&':       Cat1("&");  break;
+       case '^':       Cat1("^");  break;
+       case '|':       Cat1("|");  break;
+       case LE:        Cat1("<="); break;
+       case GE:        Cat1(">="); break;
+       case GT:        Cat1(">"); break;
+       case LT:        Cat1("<"); break;
+       case NE:        Cat1("!="); break;
+       case EQ:        Cat1("=="); break;
+       case OR:        Cat1("||"); break;
+       case AND:       Cat1("&&"); break;
+       case LSHIFT:    Cat1("<<"); break;
+       case RSHIFT:    Cat1(">>"); break;
+
+       case RUN:       fprintf(fd, "run %s(", now->sym->name);
+                       for (v = now->lft; v; v = v->rgt)
+                               if (v == now->lft)
+                               {       comwork(fd, v->lft, m);
+                               } else
+                               {       Cat2(",", v->lft);
+                               }
+                       fprintf(fd, ")");
+                       break;
+
+       case LEN:       putname(fd, "len(", now->lft, m, ")");
+                       break;
+       case FULL:      putname(fd, "full(", now->lft, m, ")");
+                       break;
+       case EMPTY:     putname(fd, "empty(", now->lft, m, ")");
+                       break;
+       case NFULL:     putname(fd, "nfull(", now->lft, m, ")");
+                       break;
+       case NEMPTY:    putname(fd, "nempty(", now->lft, m, ")");
+                       break;
+
+       case 's':       putname(fd, "", now->lft, m, now->val?"!!":"!");
+                       for (v = now->rgt, i=0; v; v = v->rgt, i++)
+                       {       if (v != now->rgt) fprintf(fd,",");
+                               if (!symbolic(fd, v->lft))
+                                       comwork(fd,v->lft,m);
+                       }
+                       break;
+       case 'r':       putname(fd, "", now->lft, m, "?");
+                       switch (now->val) {
+                       case 0: break;
+                       case 1: fprintf(fd, "?");  break;
+                       case 2: fprintf(fd, "<");  break;
+                       case 3: fprintf(fd, "?<"); break;
+                       }
+                       for (v = now->rgt, i=0; v; v = v->rgt, i++)
+                       {       if (v != now->rgt) fprintf(fd,",");
+                               if (!symbolic(fd, v->lft))
+                                       comwork(fd,v->lft,m);
+                       }
+                       if (now->val >= 2)
+                               fprintf(fd, ">");
+                       break;
+       case 'R':       putname(fd, "", now->lft, m,  now->val?"??[":"?[");
+                       for (v = now->rgt, i=0; v; v = v->rgt, i++)
+                       {       if (v != now->rgt) fprintf(fd,",");
+                               if (!symbolic(fd, v->lft))
+                                       comwork(fd,v->lft,m);
+                       }
+                       fprintf(fd, "]");
+                       break;
+
+       case ENABLED:   Cat3("enabled(", now->lft, ")");
+                       break;
+
+       case EVAL:      Cat3("eval(", now->lft, ")");
+                       break;
+
+       case NONPROGRESS:
+                       fprintf(fd, "np_");
+                       break;
+
+       case PC_VAL:    Cat3("pc_value(", now->lft, ")");
+                       break;
+
+       case 'c':       Cat3("(", now->lft, ")");
+                       break;
+
+       case '?':       if (now->lft)
+                       {       Cat3("( (", now->lft, ") -> ");
+                       }
+                       if (now->rgt)
+                       {       Cat3("(", now->rgt->lft, ") : ");
+                               Cat3("(", now->rgt->rgt, ") )");
+                       }
+                       break;  
+
+       case ASGN:      comwork(fd,now->lft,m);
+                       fprintf(fd," = ");
+                       comwork(fd,now->rgt,m);
+                       break;
+
+       case PRINT:     {       char c, buf[512];
+                               strncpy(buf, now->sym->name, 510);
+                               for (i = j = 0; i < 510; i++, j++)
+                               {       c = now->sym->name[i];
+                                       buf[j] = c;
+                                       if (c == '\\') buf[++j] = c;
+                                       if (c == '\"') buf[j] = '\'';
+                                       if (c == '\0') break;
+                               }
+                               if (now->ntyp == PRINT)
+                                       fprintf(fd, "printf");
+                               else
+                                       fprintf(fd, "annotate");
+                               fprintf(fd, "(%s", buf);
+                       }
+                       for (v = now->lft; v; v = v->rgt)
+                       {       Cat2(",", v->lft);
+                       }
+                       fprintf(fd, ")");
+                       break;
+       case PRINTM:    fprintf(fd, "printm(");
+                       comwork(fd, now->lft, m);
+                       fprintf(fd, ")");
+                       break;
+       case NAME:      putname(fd, "", now, m, "");
+                       break;
+       case   'p':     putremote(fd, now, m);
+                       break;
+       case   'q':     fprintf(fd, "%s", now->sym->name);
+                       break;
+       case C_EXPR:    
+       case C_CODE:    fprintf(fd, "{%s}", now->sym->name);
+                       break;
+       case ASSERT:    Cat3("assert(", now->lft, ")");
+                       break;
+       case   '.':     fprintf(fd, ".(goto)"); break;
+       case  GOTO:     fprintf(fd, "goto %s", now->sym->name); break;
+       case BREAK:     fprintf(fd, "break"); break;
+       case  ELSE:     fprintf(fd, "else"); break;
+       case   '@':     fprintf(fd, "-end-"); break;
+
+       case D_STEP:    fprintf(fd, "D_STEP"); break;
+       case ATOMIC:    fprintf(fd, "ATOMIC"); break;
+       case NON_ATOMIC: fprintf(fd, "sub-sequence"); break;
+       case IF:        fprintf(fd, "IF"); break;
+       case DO:        fprintf(fd, "DO"); break;
+       case UNLESS:    fprintf(fd, "unless"); break;
+       case TIMEOUT:   fprintf(fd, "timeout"); break;
+       default:        if (isprint(now->ntyp))
+                               fprintf(fd, "'%c'", now->ntyp);
+                       else
+                               fprintf(fd, "%d", now->ntyp);
+                       break;
+       }
+}
+
+void
+comment(FILE *fd, Lextok *now, int m)
+{      extern short terse, nocast;
+
+       terse=nocast=1;
+       comwork(fd, now, m);
+       terse=nocast=0;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/pangen3.h b/trunk/verif/Spin/Src5.1.6/pangen3.h
new file mode 100755 (executable)
index 0000000..c4c17fa
--- /dev/null
@@ -0,0 +1,1023 @@
+/***** 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            */
+/* (c) 2007: small additions for V5.0 to support multi-core verifications */
+
+static char *Head0[] = {
+       "#if defined(BFS) && defined(REACH)",
+       "#undef REACH", /* redundant with bfs */
+       "#endif",
+       "#ifdef VERI",
+               "#define BASE   1",
+       "#else",
+               "#define BASE   0",
+       "#endif",
+       "typedef struct Trans {",
+       "       short atom;     /* if &2 = atomic trans; if &8 local */",
+       "#ifdef HAS_UNLESS",
+       "       short escp[HAS_UNLESS]; /* lists the escape states */",
+       "       short e_trans;  /* if set, this is an escp-trans */",
+       "#endif",
+       "       short tpe[2];   /* class of operation (for reduction) */",
+       "       short qu[6];    /* for conditional selections: qid's  */",
+       "       uchar ty[6];    /* ditto: type's */",
+       "#ifdef NIBIS",
+       "       short om;       /* completion status of preselects */",
+       "#endif",
+       "       char *tp;       /* src txt of statement */",
+       "       int st;         /* the nextstate */",
+       "       int t_id;       /* transition id, unique within proc */",
+       "       int forw;       /* index forward transition */",
+       "       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)",      */
+       "extern uchar *Pptr(int);",
+
+       "#define q_sz(x)        (((Q0 *)qptr(x))->Qlen)\n",
+       "#ifndef VECTORSZ",
+       "#define VECTORSZ       1024           /* sv   size in bytes */",
+       "#endif\n",
+       0,
+};
+
+static char *Header[] = {
+       "#ifdef VERBOSE",
+               "#ifndef CHECK",
+               "#define CHECK",
+               "#endif",
+               "#ifndef DEBUG",
+               "#define DEBUG",
+               "#endif",
+       "#endif",
+       "#ifdef SAFETY",
+               "#ifndef NOFAIR",
+                       "#define NOFAIR",
+               "#endif",
+       "#endif",
+       "#ifdef NOREDUCE",
+               "#ifndef XUSAFE",
+               "#define XUSAFE",
+               "#endif",
+               "#if !defined(SAFETY) && !defined(MA)",
+                       "#define FULLSTACK",
+               "#endif",
+       "#else",
+               "#ifdef BITSTATE",
+                       "#if defined(SAFETY) && !defined(HASH64)",
+                               "#define CNTRSTACK",
+                       "#else",
+                               "#define FULLSTACK",
+                       "#endif",
+               "#else",
+                       "#define FULLSTACK",
+               "#endif",
+       "#endif",
+       "#ifdef BITSTATE",
+               "#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",
+       "#endif",
+       "#ifdef HC",
+       "#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",
+       "#if NCORE>1 && !defined(SEP_STATE)",
+       "unsigned long *ncomps; /* in shared memory */",
+       "#else",
+       "unsigned long ncomps[256+2];",
+       "#endif",
+       "#endif",
+
+       "#define MAXQ           255",
+       "#define MAXPROC        255",
+       "#define WS             sizeof(void *) /* word size in bytes */",
+       "typedef struct Stack  {         /* for queues and processes */",
+       "#if VECTORSZ>32000",
+       "       int o_delta;",
+       "       int o_offset;",
+       "       int o_skip;",
+       "       int o_delqs;",
+       "#else",
+       "       short o_delta;",
+       "       short o_offset;",
+       "       short o_skip;",
+       "       short o_delqs;",
+       "#endif",
+       "       short o_boq;",
+       "#ifndef XUSAFE",
+       "       char *o_name;",
+       "#endif",
+       "       char *body;",
+       "       struct Stack *nxt;",
+       "       struct Stack *lst;",
+       "} Stack;\n",
+       "typedef struct Svtack { /* for complete state vector */",
+       "#if VECTORSZ>32000",
+       "       int o_delta;",
+       "       int m_delta;",
+       "#else",
+       "       short o_delta;   /* current size of frame */",
+       "       short m_delta;   /* maximum size of frame */",
+       "#endif",
+       "#if SYNC",
+       "       short o_boq;",
+       "#endif",
+       0,
+};
+
+static char *Header0[] = {
+       "       char *body;",
+       "       struct Svtack *nxt;",
+       "       struct Svtack *lst;",
+       "} Svtack;\n",
+       "Trans ***trans;        /* 1 ptr per state per proctype */\n",
+       "struct H_el *Lstate;",
+       "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[] = {
+       "typedef struct State {",
+       "       uchar _nr_pr;",
+       "       uchar _nr_qs;",
+       "       uchar   _a_t;   /* cycle detection */",
+#if 0
+       in _a_t: bits 0,4, and 5 =(1|16|32) are set during a 2nd dfs
+       bit 1 is used as the A-bit for fairness
+       bit 7 (128) is the proviso bit, for reduced 2nd dfs (acceptance)
+#endif
+       "#ifndef NOFAIR",
+       "       uchar   _cnt[NFAIR];    /* counters, weak fairness */",
+       "#endif",
+
+       "#ifndef NOVSZ",
+#ifdef SOLARIS
+               "#if 0",
+               /* v3.4
+                * noticed alignment problems with some Solaris
+                * compilers, if widest field isn't wordsized
+                */
+#else
+               "#if VECTORSZ<65536",
+#endif
+               "       unsigned short _vsz;",
+               "#else",
+               "       unsigned long  _vsz;",
+               "#endif",
+       "#endif",
+
+       "#ifdef HAS_LAST",      /* cannot go before _cnt - see hstore() */
+       "       uchar  _last;   /* pid executed in last step */",
+       "#endif",
+       "#ifdef EVENT_TRACE",
+               "#if nstates_event<256",
+       "       uchar _event;",
+               "#else",
+       "       unsigned short _event;",
+               "#endif",
+       "#endif",
+       0,
+};
+
+static char *Addp0[] = {
+       /* addproc(....parlist... */ ")",
+       "{      int j, h = now._nr_pr;",
+       "#ifndef NOCOMP",
+       "       int k;",
+       "#endif",
+       "       uchar *o_this = this;\n",
+       "#ifndef INLINE",
+       "       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)",
+       "#endif",
+       "       if (h >= MAXPROC)",
+       "               Uerror(\"too many processes\");",
+       "       switch (n) {",
+       "       case 0: j = sizeof(P0); break;",
+       0,
+};
+
+static char *Addp1[] = {
+       "       default: Uerror(\"bad proc - addproc\");",
+       "       }",
+       "       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",
+       "       vsize += (int) proc_skip[h];",
+       "       proc_offset[h] = vsize;",
+       "#ifdef SVDUMP",
+       "       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",
+       "               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 */",
+       "       }",
+       "#endif",
+       "       now._nr_pr += 1;",
+       "       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\",",
+       "                       (8*NFAIR)/2 - 2, NFAIR);",
+       "               printf(\"\\trecompile with -DNFAIR=%%d\\n\",",
+       "                       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);",
+       "       if (vsize >= VECTORSZ)",
+       "       {       printf(\"pan: error, VECTORSZ too small, recompile pan.c\");",
+       "               printf(\" with -DVECTORSZ=N with N>%%d\\n\", (int) vsize);",
+       "               Uerror(\"aborting\");",
+       "       }",
+       "       memset((char *)pptr(h), 0, j);",
+       "       this = pptr(h);",
+       "       if (BASE > 0 && h > 0)",
+       "               ((P0 *)this)->_pid = h-BASE;",
+       "       else",
+       "               ((P0 *)this)->_pid = h;",
+       "       switch (n) {",
+       0,
+};
+
+static char *Addq0[] = {
+       "int",
+       "addqueue(int n, int is_rv)",
+       "{      int j=0, i = now._nr_qs;",
+       "#ifndef NOCOMP",
+       "       int k;",
+       "#endif",
+       "       if (i >= MAXQ)",
+       "               Uerror(\"too many queues\");",
+       "       switch (n) {",
+       0,
+};
+
+static char *Addq1[] = {
+       "       default: Uerror(\"bad queue - addqueue\");",
+       "       }",
+       "       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",
+       "       vsize += (int) q_skip[i];",
+       "       q_offset[i] = vsize;",
+       "       now._nr_qs += 1;",
+       "       vsize += j;",
+       "#ifndef NOVSZ",
+       "       now._vsz = vsize;",
+       "#endif",
+       "       hmax = max(hmax, vsize);",
+       "       if (vsize >= VECTORSZ)",
+       "               Uerror(\"VECTORSZ is too small, edit pan.h\");",
+       "       memset((char *)qptr(i), 0, j);",
+       "       ((Q0 *)qptr(i))->_t = n;",
+       "       return i+1;",
+       "}\n",
+       0,
+};
+
+static char *Addq11[] = {
+       "{      int j; uchar *z;\n",
+       "#ifdef HAS_SORTED",
+       "       int k;",
+       "#endif",
+       "       if (!into--)",
+       "       uerror(\"ref to uninitialized chan name (sending)\");",
+       "       if (into >= (int) now._nr_qs || into < 0)",
+       "               Uerror(\"qsend bad queue#\");",
+       "       z = qptr(into);",
+       "       j = ((Q0 *)qptr(into))->Qlen;",
+       "       switch (((Q0 *)qptr(into))->_t) {",
+       0,
+};
+
+static char *Addq2[] = {
+       "       case 0: printf(\"queue %%d was deleted\\n\", into+1);",
+       "       default: Uerror(\"bad queue - qsend\");",
+       "       }",
+       "#ifdef EVENT_TRACE",
+       "       if (in_s_scope(into+1))",
+       "               require('s', into);",
+       "#endif",
+       "}",
+       "#endif\n",
+       "#if SYNC",
+       "int",
+       "q_zero(int from)",
+       "{      if (!from--)",
+       "       {       uerror(\"ref to uninitialized chan name (q_zero)\");",
+       "               return 0;",
+       "       }",
+       "       switch(((Q0 *)qptr(from))->_t) {",
+       0,
+};
+
+static char *Addq3[] = {
+       "       case 0: printf(\"queue %%d was deleted\\n\", from+1);",
+       "       }",
+       "       Uerror(\"bad queue q-zero\");",
+       "       return -1;",
+       "}",
+       "int",
+       "not_RV(int from)",
+       "{      if (q_zero(from))",
+       "       {       printf(\"==>> a test of the contents of a rv \");",
+       "               printf(\"channel always returns FALSE\\n\");",
+       "               uerror(\"error to poll rendezvous channel\");",
+       "       }",
+       "       return 1;",
+       "}",
+       "#endif",
+       "#ifndef XUSAFE",
+       "void",
+       "setq_claim(int x, int m, char *s, int y, char *p)",
+       "{      if (x == 0)",
+       "       uerror(\"x[rs] claim on uninitialized channel\");",
+       "       if (x < 0 || x > MAXQ)",
+       "               Uerror(\"cannot happen setq_claim\");",
+       "       q_claim[x] |= m;",
+       "       p_name[y] = p;",
+       "       q_name[x] = s;",
+       "       if (m&2) q_S_check(x, y);",
+       "       if (m&1) q_R_check(x, y);",
+       "}",
+       "short q_sender[MAXQ+1];",
+       "int",
+       "q_S_check(int x, int who)",
+       "{      if (!q_sender[x])",
+       "       {       q_sender[x] = who+1;",
+       "#if SYNC",
+       "               if (q_zero(x))",
+       "               {       printf(\"chan %%s (%%d), \",",
+       "                               q_name[x], x-1);",
+       "                       printf(\"sndr proc %%s (%%d)\\n\",",
+       "                               p_name[who], who);",
+       "                       uerror(\"xs chans cannot be used for rv\");",
+       "               }",
+       "#endif",
+       "       } else",
+       "       if (q_sender[x] != who+1)",
+       "       {       printf(\"pan: xs assertion violated: \");",
+       "               printf(\"access to chan <%%s> (%%d)\\npan: by \",",
+       "                       q_name[x], x-1);",
+       "               if (q_sender[x] > 0 && p_name[q_sender[x]-1])",
+       "                       printf(\"%%s (proc %%d) and by \",",
+       "                       p_name[q_sender[x]-1], q_sender[x]-1);",
+       "               printf(\"%%s (proc %%d)\\n\",",
+       "                       p_name[who], who);",
+       "               uerror(\"error, partial order reduction invalid\");",
+       "       }",
+       "       return 1;",
+       "}",
+       "short q_recver[MAXQ+1];",
+       "int",
+       "q_R_check(int x, int who)",
+       "{      if (!q_recver[x])",
+       "       {       q_recver[x] = who+1;",
+       "#if SYNC",
+       "               if (q_zero(x))",
+       "               {       printf(\"chan %%s (%%d), \",",
+       "                               q_name[x], x-1);",
+       "                       printf(\"recv proc %%s (%%d)\\n\",",
+       "                               p_name[who], who);",
+       "                       uerror(\"xr chans cannot be used for rv\");",
+       "               }",
+       "#endif",
+       "       } else",
+       "       if (q_recver[x] != who+1)",
+       "       {       printf(\"pan: xr assertion violated: \");",
+       "               printf(\"access to chan %%s (%%d)\\npan: \",",
+       "                       q_name[x], x-1);",
+       "               if (q_recver[x] > 0 && p_name[q_recver[x]-1])",
+       "                       printf(\"by %%s (proc %%d) and \",",
+       "                       p_name[q_recver[x]-1], q_recver[x]-1);",
+       "               printf(\"by %%s (proc %%d)\\n\",",
+       "                       p_name[who], who);",
+       "               uerror(\"error, partial order reduction invalid\");",
+       "       }",
+       "       return 1;",
+       "}",
+       "#endif",
+       "int",
+       "q_len(int x)",
+       "{      if (!x--)",
+       "       uerror(\"ref to uninitialized chan name (len)\");",
+       "       return ((Q0 *)qptr(x))->Qlen;",
+       "}\n",
+       "int",
+       "q_full(int from)",
+       "{      if (!from--)",
+       "       uerror(\"ref to uninitialized chan name (qfull)\");",
+       "       switch(((Q0 *)qptr(from))->_t) {",
+       0,
+};
+
+static char *Addq4[] = {
+       "       case 0: printf(\"queue %%d was deleted\\n\", from+1);",
+       "       }",
+       "       Uerror(\"bad queue - q_full\");",
+       "       return 0;",
+       "}\n",
+       "#ifdef HAS_UNLESS",
+       "int",
+       "q_e_f(int from)",
+       "{      /* empty or full */",
+       "       return !q_len(from) || q_full(from);",
+       "}",
+       "#endif",
+       "#if NQS>0",
+       "int",
+       "qrecv(int from, int slot, int fld, int done)",
+       "{      uchar *z;",
+       "       int j, k, r=0;\n",
+       "       if (!from--)",
+       "       uerror(\"ref to uninitialized chan name (receiving)\");",
+       "       if (from >= (int) now._nr_qs || from < 0)",
+       "               Uerror(\"qrecv bad queue#\");",
+       "       z = qptr(from);",
+       "#ifdef EVENT_TRACE",
+       "       if (done && (in_r_scope(from+1)))",
+       "               require('r', from);",
+       "#endif",
+       "       switch (((Q0 *)qptr(from))->_t) {",
+       0,
+};
+
+static char *Addq5[] = {
+       "       case 0: printf(\"queue %%d was deleted\\n\", from+1);",
+       "       default: Uerror(\"bad queue - qrecv\");",
+       "       }",
+       "       return r;",
+       "}",
+       "#endif\n",
+       "#ifndef BITSTATE",
+       "#ifdef COLLAPSE",
+       "long",
+       "col_q(int i, char *z)",
+       "{      int j=0, k;",
+       "       char *x, *y;",
+       "       Q0 *ptr = (Q0 *) qptr(i);",
+       "       switch (ptr->_t) {",
+       0,
+};
+
+static char *Code0[] = {
+       "void",
+       "run(void)",
+       "{      /* int i; */",
+       "       memset((char *)&now, 0, sizeof(State));",
+       "       vsize = (unsigned long) (sizeof(State) - VECTORSZ);",
+       "#ifndef NOVSZ",
+       "       now._vsz = vsize;",
+       "#endif",
+       "/* optional provisioning statements, e.g. to */",
+       "/* set hidden variables, used as constants */",
+       "#ifdef PROV",
+       "#include PROV",
+       "#endif",
+       "       settable();",
+       0,
+};
+
+static 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);",
+       "       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));",
+       "#ifdef HAS_CODE",
+       "       NrStates[%d] = nstates%d;",
+       "#endif",
+       "       stopstate[%d][endstate%d] = 1;",
+       0,
+};
+
+static char *R0a[] = {
+       "       retrans(%d, nstates%d, start%d, src_ln%d, reached%d, loopstate%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);",
+       "       }",
+       0,
+};
+
+static char *Code1[] = {
+       "#ifdef NP",
+       "       #define ACCEPT_LAB      1 /* at least 1 in np_ */",
+       "#else",
+       "       #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[] = {
+       "#define PROG_LAB       %d /* progress labels */",
+       0,
+};
+
+static 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];",
+       "#endif",
+       0,
+};
+static 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);",
+       0,
+};
+static char *R5[] = {
+       "       case %d: j = sizeof(P%d); break;",
+       0,
+};
+static char *R6[] = {
+       "       }",
+       "       this = o_this;",
+       "       return h-BASE;",
+       "#ifndef NOBOUNDCHECK",
+       "#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; }",
+       "#endif",
+       "#ifndef BITSTATE",
+       "#ifdef COLLAPSE",
+       "long",
+       "col_p(int i, char *z)",
+       "{      int j, k; unsigned long ordinal(char *, long, short);",
+       "       char *x, *y;",
+       "       P0 *ptr = (P0 *) pptr(i);",
+       "       switch (ptr->_t) {",
+       "       case 0: j = sizeof(P0); break;",
+       0,
+};
+static char *R8a[] = {
+       "       default: Uerror(\"bad proctype - collapse\");",
+       "       }",
+       "       if (z) x = z; else x = scratch;",
+       "       y = (char *) ptr; k = proc_offset[i];",
+
+       "       for ( ; j > 0; j--, y++)",
+       "               if (!Mask[k++]) *x++ = *y;",
+
+       "       for (j = 0; j < WS-1; j++)",
+       "               *x++ = 0;",
+       "       x -= j;",
+       "       if (z) return (long) (x - z);",
+       "       return ordinal(scratch, x-scratch, (short) (2+ptr->_t));",
+       "}",
+       "#endif",
+       "#endif",
+       0,
+};
+static char *R8b[] = {
+       "       default: Uerror(\"bad qtype - collapse\");",
+       "       }",
+       "       if (z) x = z; else x = scratch;",
+       "       y = (char *) ptr; k = q_offset[i];",
+
+       "       /* no need to store the empty slots at the end */",
+       "       j -= (q_max[ptr->_t] - ptr->Qlen) * ((j - 2)/q_max[ptr->_t]);",
+
+       "       for ( ; j > 0; j--, y++)",
+       "               if (!Mask[k++]) *x++ = *y;",
+
+       "       for (j = 0; j < WS-1; j++)",
+       "               *x++ = 0;",
+       "       x -= j;",
+       "       if (z) return (long) (x - z);",
+       "       return ordinal(scratch, x-scratch, 1); /* chan */",
+       "}",
+       "#endif",
+       "#endif",
+       0,
+};
+
+static char *R12[] = {
+       "\t\tcase %d: r = ((Q%d *)z)->contents[slot].fld%d; break;",
+       0,
+};
+char *R13[] = {
+       "int ",
+       "unsend(int into)",
+       "{      int _m=0, j; uchar *z;\n",
+       "#ifdef HAS_SORTED",
+       "       int k;",
+       "#endif",
+       "       if (!into--)",
+       "               uerror(\"ref to uninitialized chan (unsend)\");",
+       "       z = qptr(into);",
+       "       j = ((Q0 *)z)->Qlen;",
+       "       ((Q0 *)z)->Qlen = --j;",
+       "       switch (((Q0 *)qptr(into))->_t) {",
+       0,
+};
+char *R14[] = {
+       "       default: Uerror(\"bad queue - unsend\");",
+       "       }",
+       "       return _m;",
+       "}\n",
+       "void",
+       "unrecv(int from, int slot, int fld, int fldvar, int strt)",
+       "{      int j; uchar *z;\n",
+       "       if (!from--)",
+       "               uerror(\"ref to uninitialized chan (unrecv)\");",
+       "       z = qptr(from);",
+       "       j = ((Q0 *)z)->Qlen;",
+       "       if (strt) ((Q0 *)z)->Qlen = j+1;",
+       "       switch (((Q0 *)qptr(from))->_t) {",
+       0,
+};
+char *R15[] = {
+       "       default: Uerror(\"bad queue - qrecv\");",
+       "       }",
+       "}",
+       0,
+};
+static char *Proto[] = {
+       "",
+       "/** function prototypes **/",
+       "char *emalloc(unsigned long);",
+       "char *Malloc(unsigned long);",
+       "int Boundcheck(int, int, int, int, Trans *);",
+       "int addqueue(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);",
+       "#endif",
+#endif
+       "int delproc(int, int);",
+       "int endstate(void);",
+       "int hstore(char *, int);",
+"#ifdef MA",
+       "int gstore(char *, int, uchar);",
+"#endif",
+       "int q_cond(short, Trans *);",
+       "int q_full(int);",
+       "int q_len(int);",
+       "int q_zero(int);",
+       "int qrecv(int, int, int, int);",
+       "int unsend(int);",
+       "/* void *sbrk(int); */",
+       "void Uerror(char *);",
+       "void assert(int, char *, int, int, Trans *);",
+       "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(const char *, int);",
+       "void sfh(const char *, int);",
+       "void d_hash(uchar *, int);",
+       "void s_hash(uchar *, int);",
+       "void r_hash(uchar *, int);",
+       "void delq(int);",
+       "void do_reach(void);",
+       "void pan_exit(int);",
+       "void exit(int);",
+       "void hinit(void);",
+       "void imed(Trans *, int, int, int);",
+       "void new_state(void);",
+       "void p_restor(int);",
+       "void putpeg(int, int);",
+       "void putrail(void);",
+       "void q_restor(void);",
+       "void retrans(int, int, int, short *, uchar *, uchar *);",
+       "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 do_dfs(int, int, int, short *, uchar *, uchar *);",
+       "void uerror(char *);",
+       "void unrecv(int, int, int, int, int);",
+       "void usage(FILE *);",
+       "void wrap_stats(void);",
+       "#if defined(FULLSTACK) && defined(BITSTATE)",
+       "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];",
+       "#endif",
+       0,
+};
+
+static char *SvMap[] = {
+       "void",
+       "to_compile(void)",
+       "{      char ctd[1024], carg[64];",
+       "#ifdef BITSTATE",
+       "       strcpy(ctd, \"-DBITSTATE \");",
+       "#else",
+       "       strcpy(ctd, \"\");",
+       "#endif",
+       "#ifdef NOVSZ",
+       "       strcat(ctd, \"-DNOVSZ \");",
+       "#endif",
+       "#ifdef REVERSE",
+       "       strcat(ctd, \"-DREVERSE \");",
+       "#endif",
+       "#ifdef T_REVERSE",
+       "       strcat(ctd, \"-DT_REVERSE \");",
+       "#endif",
+       "#ifdef RANDOMIZE",
+       "       #if RANDOMIZE>0",
+       "       sprintf(carg, \"-DRANDOMIZE=%%d \", RANDOMIZE);",
+       "       strcat(ctd, carg);",
+       "       #else",
+       "       strcat(ctd, \"-DRANDOMIZE \");",
+       "       #endif",
+       "#endif",
+       "#ifdef SCHED",
+       "       sprintf(carg, \"-DSCHED=%%d \", SCHED);",
+       "       strcat(ctd, carg);",
+       "#endif",
+       "#ifdef BFS",
+       "       strcat(ctd, \"-DBFS \");",
+       "#endif",
+       "#ifdef MEMLIM",
+       "       sprintf(carg, \"-DMEMLIM=%%d \", MEMLIM);",
+       "       strcat(ctd, carg);",
+       "#else",
+       "#ifdef MEMCNT",
+       "       sprintf(carg, \"-DMEMCNT=%%d \", MEMCNT);",
+       "       strcat(ctd, carg);",
+       "#endif",
+       "#endif",
+       "#ifdef NOCLAIM",
+       "       strcat(ctd, \"-DNOCLAIM \");",
+       "#endif",
+       "#ifdef SAFETY",
+       "       strcat(ctd, \"-DSAFETY \");",
+       "#else",
+               "#ifdef NOFAIR",
+               "       strcat(ctd, \"-DNOFAIR \");",
+               "#else",
+                       "#ifdef NFAIR",
+               "       if (NFAIR != 2)",
+               "       {       sprintf(carg, \"-DNFAIR=%%d \", NFAIR);",
+               "               strcat(ctd, carg);",
+               "       }",
+                       "#endif",
+               "#endif",
+       "#endif",
+       "#ifdef NOREDUCE",
+       "       strcat(ctd, \"-DNOREDUCE \");",
+       "#else",
+               "#ifdef XUSAFE",
+               "       strcat(ctd, \"-DXUSAFE \");",
+               "#endif",
+       "#endif",
+       "#ifdef NP",
+       "       strcat(ctd, \"-DNP \");",
+       "#endif",
+       "#ifdef PEG",
+       "       strcat(ctd, \"-DPEG \");",
+       "#endif",
+       "#ifdef VAR_RANGES",
+       "       strcat(ctd, \"-DVAR_RANGES \");",
+       "#endif",
+       "#ifdef HC0",
+       "       strcat(ctd, \"-DHC0 \");",
+       "#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",
+       "#ifdef CTL",
+       "       strcat(ctd, \"-DCTL \");",
+       "#endif",
+       "#ifdef NIBIS",
+       "       strcat(ctd, \"-DNIBIS \");",
+       "#endif",
+       "#ifdef NOBOUNDCHECK",
+       "       strcat(ctd, \"-DNOBOUNDCHECK \");",
+       "#endif",
+       "#ifdef NOSTUTTER",
+       "       strcat(ctd, \"-DNOSTUTTER \");",
+       "#endif",
+       "#ifdef REACH",
+       "       strcat(ctd, \"-DREACH \");",
+       "#endif",
+       "#ifdef PRINTF",
+       "       strcat(ctd, \"-DPRINTF \");",
+       "#endif",
+       "#ifdef OTIM",
+       "       strcat(ctd, \"-DOTIM \");",
+       "#endif",
+       "#ifdef COLLAPSE",
+       "       strcat(ctd, \"-DCOLLAPSE \");",
+       "#endif",
+       "#ifdef MA",
+       "       sprintf(carg, \"-DMA=%%d \", MA);",
+       "       strcat(ctd, carg);",
+       "#endif",
+       "#ifdef SVDUMP",
+       "       strcat(ctd, \"-DSVDUMP \");",
+       "#endif",
+       "#ifdef VECTORSZ",
+       "       if (VECTORSZ != 1024)",
+       "       {       sprintf(carg, \"-DVECTORSZ=%%d \", VECTORSZ);",
+       "               strcat(ctd, carg);",
+       "       }",
+       "#endif",
+       "#ifdef VERBOSE",
+       "       strcat(ctd, \"-DVERBOSE \");",
+       "#endif",
+       "#ifdef CHECK",
+       "       strcat(ctd, \"-DCHECK \");",
+       "#endif",
+       "#ifdef SDUMP",
+       "       strcat(ctd, \"-DSDUMP \");",
+       "#endif",
+       "#if NCORE>1",
+       "       sprintf(carg, \"-DNCORE=%%d \", NCORE);",
+       "       strcat(ctd, carg);",
+       "#endif",
+       "#ifdef SFH",
+       "       sprintf(carg, \"-DSFH \");",
+       "       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);",
+       "}",
+       0,
+};
diff --git a/trunk/verif/Spin/Src5.1.6/pangen4.c b/trunk/verif/Spin/Src5.1.6/pangen4.c
new file mode 100755 (executable)
index 0000000..12477c8
--- /dev/null
@@ -0,0 +1,351 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+extern FILE    *tc, *tb;
+extern Queue   *qtab;
+extern Symbol  *Fname;
+extern int     lineno, m_loss, Pid, eventmapnr, multi_oval;
+extern short   nocast, has_provided, has_sorted;
+extern char    *R13[], *R14[], *R15[];
+
+static void    check_proc(Lextok *, int);
+
+void
+undostmnt(Lextok *now, int m)
+{      Lextok *v;
+       int i, j;
+
+       if (!now)
+       {       fprintf(tb, "0");
+               return;
+       }
+       lineno = now->ln;
+       Fname  = now->fn;
+       switch (now->ntyp) {
+       case CONST:     case '!':       case UMIN:
+       case '~':       case '/':       case '*':
+       case '-':       case '+':       case '%':
+       case LT:        case GT:        case '&':
+       case '|':       case LE:        case GE:
+       case NE:        case EQ:        case OR:
+       case AND:       case LSHIFT:    case RSHIFT:
+       case TIMEOUT:   case LEN:       case NAME:
+       case FULL:      case EMPTY:     case 'R':
+       case NFULL:     case NEMPTY:    case ENABLED:
+       case '?':       case PC_VAL:    case '^':
+       case C_EXPR:
+       case NONPROGRESS:
+               putstmnt(tb, now, m);
+               break;
+
+       case RUN:
+               fprintf(tb, "delproc(0, now._nr_pr-1)");
+               break;
+
+       case 's':
+               if (Pid == eventmapnr) break;
+
+               if (m_loss)
+                       fprintf(tb, "if (_m == 2) ");
+               putname(tb, "_m = unsend(", now->lft, m, ")");
+               break;
+
+       case 'r':
+               if (Pid == eventmapnr) break;
+
+               for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
+                       if (v->lft->ntyp != CONST
+                       &&  v->lft->ntyp != EVAL)
+                               j++;
+               if (j == 0 && now->val >= 2)
+                       break;  /* poll without side-effect */
+
+               {       int ii = 0, jj;
+
+                       for (v = now->rgt; v; v = v->rgt)
+                               if ((v->lft->ntyp != CONST
+                               &&   v->lft->ntyp != EVAL))
+                                       ii++;   /* nr of things bupped */
+                       if (now->val == 1)
+                       {       ii++;
+                               jj = multi_oval - ii - 1;
+                               fprintf(tb, "XX = trpt->bup.oval");
+                               if (multi_oval > 0)
+                               {       fprintf(tb, "s[%d]", jj);
+                                       jj++;
+                               }
+                               fprintf(tb, ";\n\t\t");
+                       } else
+                       {       fprintf(tb, "XX = 1;\n\t\t");
+                               jj = multi_oval - ii - 1;
+                       }
+
+                       if (now->val < 2)       /* not for channel poll */
+                       for (v = now->rgt, i = 0; v; v = v->rgt, i++)
+                       {       switch(v->lft->ntyp) {
+                               case CONST:
+                               case EVAL:
+                                       fprintf(tb, "unrecv");
+                                       putname(tb, "(", now->lft, m, ", XX-1, ");
+                                       fprintf(tb, "%d, ", i);
+                                       if (v->lft->ntyp == EVAL)
+                                               undostmnt(v->lft->lft, m);
+                                       else
+                                               undostmnt(v->lft, m);
+                                       fprintf(tb, ", %d);\n\t\t", (i==0)?1:0);
+                                       break;
+                               default:
+                                       fprintf(tb, "unrecv");
+                                       putname(tb, "(", now->lft, m, ", XX-1, ");
+                                       fprintf(tb, "%d, ", i);
+                                       if (v->lft->sym
+                                       && !strcmp(v->lft->sym->name, "_"))
+                                       {       fprintf(tb, "trpt->bup.oval");
+                                               if (multi_oval > 0)
+                                                       fprintf(tb, "s[%d]", jj);
+                                       } else
+                                               putstmnt(tb, v->lft, m);
+
+                                       fprintf(tb, ", %d);\n\t\t", (i==0)?1:0);
+                                       if (multi_oval > 0)
+                                               jj++;
+                                       break;
+                       }       }
+                       jj = multi_oval - ii - 1;
+
+                       if (now->val == 1 && multi_oval > 0)
+                               jj++;   /* new 3.4.0 */
+
+                       for (v = now->rgt, i = 0; v; v = v->rgt, i++)
+                       {       switch(v->lft->ntyp) {
+                               case CONST:
+                               case EVAL:
+                                       break;
+                               default:
+                                       if (!v->lft->sym
+                                       ||  strcmp(v->lft->sym->name, "_") != 0)
+                                       {       nocast=1; putstmnt(tb,v->lft,m);
+                                               nocast=0; fprintf(tb, " = trpt->bup.oval");
+                                               if (multi_oval > 0)
+                                                       fprintf(tb, "s[%d]", jj);
+                                               fprintf(tb, ";\n\t\t");
+                                       }
+                                       if (multi_oval > 0)
+                                               jj++;
+                                       break;
+                       }       }
+                       multi_oval -= ii;
+               }
+               break;
+
+       case '@':
+               fprintf(tb, "p_restor(II);\n\t\t");
+               break;
+
+       case ASGN:
+               nocast=1; putstmnt(tb,now->lft,m);
+               nocast=0; fprintf(tb, " = trpt->bup.oval");
+               if (multi_oval > 0)
+               {       multi_oval--;
+                       fprintf(tb, "s[%d]", multi_oval-1);
+               }
+               check_proc(now->rgt, m);
+               break;
+
+       case 'c':
+               check_proc(now->lft, m);
+               break;
+
+       case '.':
+       case GOTO:
+       case ELSE:
+       case BREAK:
+               break;
+
+       case C_CODE:
+               fprintf(tb, "sv_restor();\n");
+               break;
+
+       case ASSERT:
+       case PRINT:
+               check_proc(now, m);
+               break;
+       case PRINTM:
+               break;
+
+       default:
+               printf("spin: bad node type %d (.b)\n", now->ntyp);
+               alldone(1);
+       }
+}
+
+int
+any_undo(Lextok *now)
+{      /* is there anything to undo on a return move? */
+       if (!now) return 1;
+       switch (now->ntyp) {
+       case 'c':       return any_oper(now->lft, RUN);
+       case ASSERT:
+       case PRINT:     return any_oper(now, RUN);
+
+       case PRINTM:
+       case   '.':
+       case  GOTO:
+       case  ELSE:
+       case BREAK:     return 0;
+       default:        return 1;
+       }
+}
+
+int
+any_oper(Lextok *now, int oper)
+{      /* check if an expression contains oper operator */
+       if (!now) return 0;
+       if (now->ntyp == oper)
+               return 1;
+       return (any_oper(now->lft, oper) || any_oper(now->rgt, oper));
+}
+
+static void
+check_proc(Lextok *now, int m)
+{
+       if (!now)
+               return;
+       if (now->ntyp == '@' || now->ntyp == RUN)
+       {       fprintf(tb, ";\n\t\t");
+               undostmnt(now, m);
+       }
+       check_proc(now->lft, m);
+       check_proc(now->rgt, m);
+}
+
+void
+genunio(void)
+{      char buf1[256];
+       Queue *q; int i;
+
+       ntimes(tc, 0, 1, R13);
+       for (q = qtab; q; q = q->nxt)
+       {       fprintf(tc, "\tcase %d:\n", q->qid);
+
+               if (has_sorted)
+               {       sprintf(buf1, "((Q%d *)z)->contents", q->qid);
+                       fprintf(tc, "#ifdef HAS_SORTED\n");
+                       fprintf(tc, "\t\tj = trpt->ipt;\n");    /* ipt was bup.oval */
+                       fprintf(tc, "#endif\n");
+                       fprintf(tc, "\t\tfor (k = j; k < ((Q%d *)z)->Qlen; k++)\n",
+                               q->qid);
+                       fprintf(tc, "\t\t{\n");
+                       for (i = 0; i < q->nflds; i++)
+                       fprintf(tc, "\t\t\t%s[k].fld%d = %s[k+1].fld%d;\n",
+                               buf1, i, buf1, i);
+                       fprintf(tc, "\t\t}\n");
+                       fprintf(tc, "\t\tj = ((Q0 *)z)->Qlen;\n");
+               }
+
+               sprintf(buf1, "((Q%d *)z)->contents[j].fld", q->qid);
+               for (i = 0; i < q->nflds; i++)
+                       fprintf(tc, "\t\t%s%d = 0;\n", buf1, i);
+               if (q->nslots==0)
+               {       /* check if rendezvous succeeded, 1 level down */
+                       fprintf(tc, "\t\t_m = (trpt+1)->o_m;\n");
+                       fprintf(tc, "\t\tif (_m) (trpt-1)->o_pm |= 1;\n");
+                       fprintf(tc, "\t\tUnBlock;\n");
+               } else
+                       fprintf(tc, "\t\t_m = trpt->o_m;\n");
+
+               fprintf(tc, "\t\tbreak;\n");
+       }
+       ntimes(tc, 0, 1, R14);
+       for (q = qtab; q; q = q->nxt)
+       {       sprintf(buf1, "((Q%d *)z)->contents", q->qid);
+               fprintf(tc, "   case %d:\n", q->qid);
+               if (q->nslots == 0)
+                       fprintf(tc, "\t\tif (strt) boq = from+1;\n");
+               else if (q->nslots > 1) /* shift */
+               {       fprintf(tc, "\t\tif (strt && slot<%d)\n",
+                                                       q->nslots-1);
+                       fprintf(tc, "\t\t{\tfor (j--; j>=slot; j--)\n");
+                       fprintf(tc, "\t\t\t{");
+                       for (i = 0; i < q->nflds; i++)
+                       {       fprintf(tc, "\t%s[j+1].fld%d =\n\t\t\t",
+                                                       buf1, i);
+                               fprintf(tc, "\t%s[j].fld%d;\n\t\t\t",
+                                                       buf1, i);
+                       }
+                       fprintf(tc, "}\n\t\t}\n");
+               }
+               strcat(buf1, "[slot].fld");
+               fprintf(tc, "\t\tif (strt) {\n");
+               for (i = 0; i < q->nflds; i++)
+                       fprintf(tc, "\t\t\t%s%d = 0;\n", buf1, i);
+               fprintf(tc, "\t\t}\n");
+               if (q->nflds == 1)      /* set */
+                       fprintf(tc, "\t\tif (fld == 0) %s0 = fldvar;\n",
+                                                       buf1);
+               else
+               {       fprintf(tc, "\t\tswitch (fld) {\n");
+                       for (i = 0; i < q->nflds; i++)
+                       {       fprintf(tc, "\t\tcase %d:\t%s", i, buf1);
+                               fprintf(tc, "%d = fldvar; break;\n", i);
+                       }
+                       fprintf(tc, "\t\t}\n");
+               }
+               fprintf(tc, "\t\tbreak;\n");
+       }
+       ntimes(tc, 0, 1, R15);
+}
+
+extern void explain(int);
+
+int
+proper_enabler(Lextok *n)
+{
+       if (!n) return 1;
+       switch (n->ntyp) {
+       case NEMPTY:    case FULL:
+       case NFULL:     case EMPTY:
+       case LEN:       case 'R':
+       case NAME:
+               has_provided = 1;
+               if (strcmp(n->sym->name, "_pid") == 0)
+                       return 1;
+               return (!(n->sym->context));
+
+       case C_EXPR:
+       case CONST:
+       case TIMEOUT:
+               has_provided = 1;
+               return 1;
+
+       case ENABLED:   case PC_VAL:
+               return proper_enabler(n->lft);
+
+       case '!': case UMIN: case '~':
+               return proper_enabler(n->lft);
+
+       case '/': case '*': case '-': case '+':
+       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':
+               return proper_enabler(n->lft) && proper_enabler(n->rgt);
+       default:
+               break;
+       }
+       printf("spin: saw ");
+       explain(n->ntyp);
+       printf("\n");
+       return 0;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/pangen4.h b/trunk/verif/Spin/Src5.1.6/pangen4.h
new file mode 100755 (executable)
index 0000000..d80bdea
--- /dev/null
@@ -0,0 +1,727 @@
+/***** 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            */
+
+/* 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[] = {
+       "#ifdef MA",
+       "/*",
+       "#include <stdio.h>",
+       "#define uchar  unsigned char",
+       "*/",
+       "#define ulong  unsigned long",
+       "#define ushort unsigned short",
+       "",
+       "#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))",
+       "",
+       "extern char    *emalloc(unsigned long);        /* imported routine  */",
+       "extern void    dfa_init(ushort);       /* 4 exported routines */",
+       "extern int     dfa_member(ulong);",
+       "extern int     dfa_store(uchar *);",
+       "extern void    dfa_stats(void);",
+       "",
+       "typedef struct Edge {",
+       "       uchar From, To;         /* max range 0..255 */",
+       "       uchar s, S;             /* if s=1, S is singleton */",
+       "       struct Vertex   *Dst;",
+       "       struct Edge     *Nxt;",
+       "} Edge;",
+       "",
+       "typedef struct Vertex {",
+       "       ulong   key, num;       /* key for splay tree, nr incoming edges */",
+       "       uchar   from[2], to[2]; /* in-node predefined edge info    */",
+       "       struct  Vertex  *dst[2];/* most nodes have 2 or more edges */",
+       "       struct  Edge    *Succ;  /* in case there are more edges */",
+       "       struct  Vertex  *lnk, *left, *right; /* splay tree plumbing */",
+       "} Vertex;",
+       "",
+       "static Edge    *free_edges;",
+       "static Vertex  *free_vertices;",
+       "static Vertex  **layers;       /* one splay tree of nodes per layer */",
+       "static Vertex  **path;         /* run of word in the DFA */",
+       "static Vertex  *R, *F, *NF;    /* Root, Final, Not-Final */",
+       "static uchar   *word, *lastword;/* string, and last string inserted */",
+       "static int     dfa_depth, iv=0, nv=0, pfrst=0, Tally;",
+       "",
+       "static void    insert_it(Vertex *, int);       /* splay-tree code */",
+       "static void    delete_it(Vertex *, int);",
+       "static Vertex  *find_it(Vertex *, Vertex *, uchar, int);",
+       "",
+       "static void",
+       "recyc_edges(Edge *e)",
+       "{",
+       "       if (!e) return;",
+       "       recyc_edges(e->Nxt);",
+       "       e->Nxt = free_edges;",
+       "       free_edges = e;",
+       "}",
+       "",
+       "static Edge *",
+       "new_edge(Vertex *dst)",
+       "{      Edge *e;",
+       "",
+       "       if (free_edges)",
+       "       {       e = free_edges;",
+       "               free_edges = e->Nxt;",
+       "               e->From = e->To = e->s = e->S = 0;",
+       "               e->Nxt = (Edge *) 0;",
+       "       } else",
+       "               e = (Edge *) emalloc(sizeof(Edge));",
+       "       e->Dst = dst;",
+       "",
+       "       return e;",
+       "}",
+       "",
+       "static void",
+       "recyc_vertex(Vertex *v)",
+       "{",
+       "       recyc_edges(v->Succ);",
+       "       v->Succ = (Edge *) free_vertices;",
+       "       free_vertices = v;",
+       "       nr_states--;",
+       "}",
+       "",
+       "static Vertex *",
+       "new_vertex(void)",
+       "{      Vertex *v;",
+       "",
+       "       if (free_vertices)",
+       "       {       v = free_vertices;",
+       "               free_vertices = (Vertex *) v->Succ;",
+       "               v->Succ = (Edge *) 0;",
+       "               v->num  = 0;",
+       "       } else",
+       "               v = (Vertex *) emalloc(sizeof(Vertex));",
+       "",
+       "       nr_states++;",
+       "       return v; ",
+       "}",
+       "",
+       "static Vertex *",
+       "allDelta(Vertex *v, int n)",
+       "{      Vertex *dst = new_vertex();",
+       "",
+       "       v->from[0] = 0;",
+       "       v->to[0] = 255;",
+       "       v->dst[0] = dst;",
+       "       dst->num = 256;",
+       "       insert_it(v, n);",
+       "       return dst;",
+       "}",
+       "",
+       "static void",
+       "insert_edge(Vertex *v, Edge *e)",
+       "{      /* put new edge first */",
+       "       if (!v->dst[0])",
+       "       {       v->dst[0] = e->Dst;",
+       "               v->from[0] = e->From;",
+       "               v->to[0] = e->To;",
+       "               recyc_edges(e);",
+       "               return;",
+       "       }",
+       "       if (!v->dst[1])",
+       "       {       v->from[1] = v->from[0]; v->from[0] = e->From;",
+       "               v->to[1]   = v->to[0];   v->to[0]   = e->To;",
+       "               v->dst[1]  = v->dst[0];  v->dst[0]  = e->Dst;",
+       "               recyc_edges(e);",
+       "               return;",
+       "       } /* shift */",
+       "       {       int f      = v->from[1];",
+       "               int t      = v->to[1];",
+       "               Vertex *d  = v->dst[1];",
+       "               v->from[1] = v->from[0]; v->from[0] = e->From;",
+       "               v->to[1]   = v->to[0];   v->to[0]   = e->To;",
+       "               v->dst[1]  = v->dst[0];  v->dst[0]  = e->Dst;",
+       "               e->From = f;",
+       "               e->To   = t;",
+       "               e->Dst  = d;",
+       "       }",
+       "       e->Nxt = v->Succ;",
+       "       v->Succ = e;",
+       "}",
+       "",
+       "static void",
+       "copyRecursive(Vertex *v, Edge *e)",
+       "{      Edge *f;",
+       "       if (e->Nxt) copyRecursive(v, e->Nxt);",
+       "       f = new_edge(e->Dst);",
+       "       f->From = e->From;",
+       "       f->To   = e->To;",
+       "       f->s    = e->s;",
+       "       f->S    = e->S;",
+       "       f->Nxt  = v->Succ;",
+       "       v->Succ = f;",
+       "}",
+       "",
+       "static void",
+       "copyEdges(Vertex *to, Vertex *from)",
+       "{      int i;",
+       "       for (i = 0; i < 2; i++)",
+       "       {       to->from[i] = from->from[i];",
+       "               to->to[i]   = from->to[i];",
+       "               to->dst[i]  = from->dst[i];",
+       "       }",
+       "       if (from->Succ) copyRecursive(to, from->Succ);",
+       "}",
+       "",
+       "static Edge *",
+       "cacheDelta(Vertex *v, int h, int first)",
+       "{      static Edge *ov, tmp;  int i;",
+       "",
+       "       if (!first && INRANGE(ov,h))",
+       "               return ov; /* intercepts about 10%% */",
+       "       for (i = 0; i < 2; i++)",
+       "               if (v->dst[i] && h >= v->from[i] && h <= v->to[i])",
+       "               {       tmp.From = v->from[i];",
+       "                       tmp.To   = v->to[i];",
+       "                       tmp.Dst  = v->dst[i];",
+       "                       tmp.s    =  tmp.S = 0;",
+       "                       ov = &tmp;",
+       "                       return ov;",
+       "               }",
+       "       for (ov = v->Succ; ov; ov = ov->Nxt)",
+       "               if (INRANGE(ov,h)) return ov;",
+       "",
+       "       Uerror(\"cannot get here, cacheDelta\");",
+       "       return (Edge *) 0;",
+       "}",
+       "",
+       "static Vertex *",
+       "Delta(Vertex *v, int h)        /* v->delta[h] */",
+       "{      Edge *e;",
+       "",
+       "       if (v->dst[0] && h >= v->from[0] && h <= v->to[0])",
+       "               return v->dst[0];       /* oldest edge */",
+       "       if (v->dst[1] && h >= v->from[1] && h <= v->to[1])",
+       "               return v->dst[1];",
+       "       for (e = v->Succ; e; e = e->Nxt)",
+       "               if (INRANGE(e,h))",
+       "                       return e->Dst;",
+       "       Uerror(\"cannot happen Delta\");",
+       "       return (Vertex *) 0;",
+       "}",
+       "",
+       "static void",
+       "numDelta(Vertex *v, int d)",
+       "{      Edge *e;",
+       "       ulong cnt;",
+       "       int i;",
+       "",
+       "       for (i = 0; i < 2; i++)",
+       "       if (v->dst[i])",
+       "       {       cnt = v->dst[i]->num + d*(1 + v->to[i] - v->from[i]);",
+       "               if (d == 1 && cnt < v->dst[i]->num) goto bad;",
+       "               v->dst[i]->num = cnt;",
+       "       }",
+       "       for (e = v->Succ; e; e = e->Nxt)",
+       "       {       cnt = e->Dst->num + d*(1 + e->To - e->From + e->s);",
+       "               if (d == 1 && cnt < e->Dst->num)",
+       "bad:                   Uerror(\"too many incoming edges\");",
+       "               e->Dst->num = cnt;",
+       "       }",
+       "}",
+       "",
+       "static void",
+       "setDelta(Vertex *v, int h, Vertex *newdst)     /* v->delta[h] = newdst; */",
+       "{      Edge *e, *f = (Edge *) 0, *g;",
+       "       int i;",
+       "",
+       "       /* remove the old entry, if there */",
+       "       for (i = 0; i < 2; i++)",
+       "               if (v->dst[i] && h >= v->from[i] && h <= v->to[i])",
+       "               {       if (h == v->from[i])",
+       "                       {       if (h == v->to[i])",
+       "                               {       v->dst[i] = (Vertex *) 0;",
+       "                                       v->from[i] = v->to[i] = 0;",
+       "                               } else",
+       "                                       v->from[i]++;",
+       "                       } else if (h == v->to[i])",
+       "                       {       v->to[i]--;",
+       "                       } else",
+       "                       {       g = new_edge(v->dst[i]);/* same dst */",
+       "                               g->From    = v->from[i];",
+       "                               g->To      = h-1;       /* left half */",
+       "                               v->from[i] = h+1;       /* right half */",
+       "                               insert_edge(v, g);",
+       "                       }",
+       "                       goto part2;",
+       "               }",
+       "       for (e = v->Succ; e; f = e, e = e->Nxt)",
+       "       {       if (e->s == 1 && e->S == h)",
+       "               {       e->s = e->S = 0;",
+       "                       goto rem_tst;",
+       "               }",
+       "               if (h >= e->From && h <= e->To)",
+       "               {       if (h == e->From)",
+       "                       {       if (h == e->To)",
+       "                               {       if (e->s)",
+       "                                       {       e->From = e->To = e->S;",
+       "                                               e->s = 0;",
+       "                                               break;",
+       "                                       } else",
+       "                                               goto rem_do;",
+       "                               } else",
+       "                                       e->From++;",
+       "                       } else if (h == e->To)",
+       "                       {       e->To--;",
+       "                       } else                          /* split */",
+       "                       {       g = new_edge(e->Dst);   /* same dst */",
+       "                               g->From = e->From;",
+       "                               g->To   = h-1;          /* g=left half */",
+       "                               e->From = h+1;          /* e=right half */",
+       "                               g->Nxt  = e->Nxt;       /* insert g */",
+       "                               e->Nxt  = g;            /* behind e */",
+       "                               break;                  /* done */",
+       "                       }",
+       "",
+       "rem_tst:               if (e->From > e->To)",
+       "                       {       if (e->s == 0) {",
+       "rem_do:                                if (f)",
+       "                                               f->Nxt = e->Nxt;",
+       "                                       else",
+       "                                               v->Succ = e->Nxt;",
+       "                                       e->Nxt = (Edge *) 0;",
+       "                                       recyc_edges(e);",
+       "                               } else",
+       "                               {       e->From = e->To = e->S;",
+       "                                       e->s = 0;",
+       "                       }       }",
+       "                       break;",
+       "       }       }",
+       "part2:",
+       "       /* check if newdst is already there */",
+       "       for (i = 0; i < 2; i++)",
+       "               if (v->dst[i] == newdst)",
+       "               {       if (h+1 == (int) v->from[i])",
+       "                       {       v->from[i] = h;",
+       "                               return;",
+       "                       }",
+       "                       if (h == (int) v->to[i]+1)",
+       "                       {       v->to[i] = h;",
+       "                               return;",
+       "               }       }",
+       "       for (e = v->Succ; e; e = e->Nxt)",
+       "       {       if (e->Dst == newdst)",
+       "               {       if (h+1 == (int) e->From)",
+       "                       {       e->From = h;",
+       "                               if (e->s == 1 && e->S+1 == e->From)",
+       "                               {       e->From = e->S;",
+       "                                       e->s = e->S = 0;",
+       "                               }",
+       "                               return;",
+       "                       }",
+       "                       if (h == (int) e->To+1)",
+       "                       {       e->To = h;",
+       "                               if (e->s == 1 && e->S == e->To+1)",
+       "                               {       e->To = e->S;",
+       "                                       e->s = e->S = 0;",
+       "                               }",
+       "                               return;",
+       "                       }",
+       "                       if (e->s == 0)",
+       "                       {       e->s = 1;",
+       "                               e->S = h;",
+       "                               return;",
+       "       }       }       }",
+       "       /* add as a new edge */",
+       "       e = new_edge(newdst);",
+       "       e->From = e->To = h;",
+       "       insert_edge(v, e);",
+       "}",
+       "",
+       "static ulong",
+       "cheap_key(Vertex *v)",
+       "{      ulong vk2 = 0;",
+       "",
+       "       if (v->dst[0])",
+       "       {       vk2 = (ulong) v->dst[0];",
+       "               if ((ulong) v->dst[1] > vk2)",
+       "                       vk2 = (ulong) v->dst[1];",
+       "       } else if (v->dst[1])",
+       "               vk2 = (ulong) v->dst[1]; ",
+       "       if (v->Succ)",
+       "       {       Edge *e;",
+       "               for (e = v->Succ; e; e = e->Nxt)",
+       "                       if ((ulong) e->Dst > vk2)",
+       "                               vk2 = (ulong) e->Dst;",
+       "       }",
+       "       Tally = (vk2>>2)&(TWIDTH-1);",
+       "       return v->key;",
+       "}",
+       "",
+       "static ulong",
+       "mk_key(Vertex *v)      /* not sensitive to order */",
+       "{      ulong m = 0, vk2 = 0;",
+       "       Edge *e;",
+       "",
+       "       if (v->dst[0])",
+       "       {       m += HASH(v->dst[0], v->to[0] - v->from[0] + 1);",
+       "               vk2 = (ulong) v->dst[0]; ",
+       "       }",
+       "       if (v->dst[1])",
+       "       {       m += HASH(v->dst[1], v->to[1] - v->from[1] + 1);",
+       "               if ((ulong) v->dst[1] > vk2) vk2 = (ulong) v->dst[1]; ",
+       "       }",
+       "       for (e = v->Succ; e; e = e->Nxt)",
+       "       {       m += HASH(e->Dst, e->To - e->From + 1 + e->s);",
+       "               if ((ulong) e->Dst > vk2) vk2 = (ulong) e->Dst; ",
+       "       }",
+       "       Tally = (vk2>>2)&(TWIDTH-1);",
+       "       return m;",
+       "}",
+       "",
+       "static ulong",
+       "mk_special(int sigma, Vertex *n, Vertex *v)",
+       "{      ulong m = 0, vk2 = 0;",
+       "       Edge *f;",
+       "       int i;",
+       "",
+       "       for (i = 0; i < 2; i++)",
+       "               if (v->dst[i])",
+       "               {       if (sigma >= v->from[i] && sigma <= v->to[i])",
+       "                       {       m += HASH(v->dst[i], v->to[i]-v->from[i]);",
+       "                               if ((ulong) v->dst[i] > vk2",
+       "                               &&   v->to[i] > v->from[i])",
+       "                                       vk2 = (ulong) v->dst[i]; ",
+       "                       } else",
+       "                       {       m += HASH(v->dst[i], v->to[i]-v->from[i]+1);",
+       "                               if ((ulong) v->dst[i] > vk2)",
+       "                                       vk2 = (ulong) v->dst[i]; ",
+       "               }       }",
+       "       for (f = v->Succ; f; f = f->Nxt)",
+       "       {       if (sigma >= f->From && sigma <= f->To)",
+       "               {       m += HASH(f->Dst, f->To - f->From + f->s);",
+       "                       if ((ulong) f->Dst > vk2",
+       "                       &&   f->To - f->From + f->s > 0)",
+       "                               vk2 = (ulong) f->Dst; ",
+       "               } else if (f->s == 1 && sigma == f->S)",
+       "               {       m += HASH(f->Dst, f->To - f->From + 1);",
+       "                       if ((ulong) f->Dst > vk2) vk2 = (ulong) f->Dst; ",
+       "               } else",
+       "               {       m += HASH(f->Dst, f->To - f->From + 1 + f->s);",
+       "                       if ((ulong) f->Dst > vk2) vk2 = (ulong) f->Dst; ",
+       "       }       }",
+       "",
+       "       if ((ulong) n > vk2) vk2 = (ulong) n; ",
+       "       Tally = (vk2>>2)&(TWIDTH-1);",
+       "       m += HASH(n, 1);",
+       "       return m;",
+       "}",
+       "",
+       "void ",
+       "dfa_init(ushort nr_layers)",
+       "{      int i; Vertex *r, *t;",
+       "",
+       "       dfa_depth = nr_layers;  /* one byte per layer */",
+       "       path   = (Vertex **) emalloc((dfa_depth+1)*sizeof(Vertex *));",
+       "       layers = (Vertex **) emalloc(TWIDTH*(dfa_depth+1)*sizeof(Vertex *));",
+       "       lastword = (uchar *) emalloc((dfa_depth+1)*sizeof(uchar));",
+       "       lastword[dfa_depth] = lastword[0] = 255;",
+       "       path[0] = R = new_vertex(); F = new_vertex();",
+       "",
+       "       for (i = 1, r = R; i < dfa_depth; i++, r = t)",
+       "               t = allDelta(r, i-1);",
+       "       NF = allDelta(r, i-1);",
+       "}",
+       "",
+       "#if 0",
+       "static void complement_dfa(void) { Vertex *tmp = F; F = NF; NF = tmp; }",
+       "#endif",
+       "",
+       "double",
+       "tree_stats(Vertex *t)",
+       "{      Edge *e; double cnt=0.0;",
+       "       if (!t) return 0;",
+       "       if (!t->key) return 0;",
+       "       t->key = 0; /* precaution */",
+       "       if (t->dst[0]) cnt++;",
+       "       if (t->dst[1]) cnt++;",
+       "       for (e = t->Succ; e; e = e->Nxt)",
+       "               cnt++;",
+       "       cnt += tree_stats(t->lnk);",
+       "       cnt += tree_stats(t->left);",
+       "       cnt += tree_stats(t->right);",
+       "       return cnt;",
+       "}",
+       "",
+       "void",
+       "dfa_stats(void)",
+       "{      int i, j; double cnt = 0.0;",
+       "       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\",",
+       "               nr_states, cnt);",
+       "}",
+       "",
+       "int",
+       "dfa_member(ulong n)",
+       "{      Vertex **p, **q;",
+       "       uchar *w = &word[n];",
+       "       int i;",
+       "",
+       "       p = &path[n]; q = (p+1);",
+       "       for (i = n; i < dfa_depth; i++)",
+       "               *q++ = Delta(*p++, *w++);",
+       "       return (*p == F);",
+       "}",
+       "",
+       "int",
+       "dfa_store(uchar *sv)",
+       "{      Vertex **p, **q, *s, *y, *old, *new = F;",
+       "       uchar *w, *u = lastword;",
+       "       int i, j, k;",
+       "",
+       "       w = word = sv;",
+       "       while (*w++ == *u++)    /* find first byte that differs */",
+       "               ;",
+       "       pfrst = (int) (u - lastword) - 1;",
+       "       memcpy(&lastword[pfrst], &sv[pfrst], dfa_depth-pfrst);",
+       "       if (pfrst > iv) pfrst = iv;",
+       "       if (pfrst > nv) pfrst = nv;",
+       "/* phase1: */",
+       "       p = &path[pfrst]; q = (p+1); w = &word[pfrst];",
+       "       for (i = pfrst; i < dfa_depth; i++)",
+       "               *q++ = Delta(*p++, *w++);       /* (*p)->delta[*w++]; */",
+       "",
+       "       if (*p == F) return 1;  /* it's already there */",
+       "/* phase2: */",
+       "       iv = dfa_depth;",
+       "       do {    iv--;",
+       "               old = new;",
+       "               new = find_it(path[iv], old, word[iv], iv);",
+       "       } while (new && iv > 0);",
+       "",
+       "/* phase3: */",
+       "       nv = k = 0; s = path[0];",
+       "       for (j = 1; j <= iv; ++j) ",
+       "               if (path[j]->num > 1)",
+       "               {       y = new_vertex();",
+       "                       copyEdges(y, path[j]);",
+       "                       insert_it(y, j);",
+       "                       numDelta(y, 1);",
+       "                       delete_it(s, j-1);",
+       "                       setDelta(s, word[j-1], y);",
+       "                       insert_it(s, j-1);",
+       "                       y->num = 1;     /* initial value 1 */",
+       "                       s = y;",
+       "                       path[j]->num--; /* only 1 moved from j to y */",
+       "                       k = 1;",
+       "               } else",
+       "               {       s = path[j];",
+       "                       if (!k) nv = j;",
+       "               }",
+       "       y = Delta(s, word[iv]);",
+       "       y->num--;",
+       "       delete_it(s, iv); ",
+       "       setDelta(s, word[iv], old);",
+       "       insert_it(s, iv); ",
+       "       old->num++;",
+       "",
+       "       for (j = iv+1; j < dfa_depth; j++)",
+       "               if (path[j]->num == 0)",
+       "               {       numDelta(path[j], -1);",
+       "                       delete_it(path[j], j);",
+       "                       recyc_vertex(path[j]);",
+       "               } else",
+       "                       break;",
+       "       return 0;",
+       "}",
+       "",
+       "static Vertex *",
+       "splay(ulong i, Vertex *t)",
+       "{      Vertex N, *l, *r, *y;",
+       "",
+       "       if (!t) return t;",
+       "       N.left = N.right = (Vertex *) 0;",
+       "       l = r = &N;",
+       "       for (;;)",
+       "       {       if (i < t->key)",
+       "               {       if (!t->left) break;",
+       "                       if (i < t->left->key)",
+       "                       {       y = t->left;",
+       "                               t->left = y->right;",
+       "                               y->right = t;",
+       "                               t = y;",
+       "                               if (!t->left) break;",
+       "                       }",
+       "                       r->left = t;",
+       "                       r = t;",
+       "                       t = t->left;",
+       "               } else if (i > t->key)",
+       "               {       if (!t->right) break;",
+       "                       if (i > t->right->key)",
+       "                       {       y = t->right;",
+       "                               t->right = y->left;",
+       "                               y->left = t;",
+       "                               t = y;",
+       "                               if (!t->right) break;",
+       "                       }",
+       "                       l->right = t;",
+       "                       l = t;",
+       "                       t = t->right;",
+       "               } else",
+       "                       break;",
+       "       }",
+       "       l->right = t->left;",
+       "       r->left = t->right;",
+       "       t->left = N.right;",
+       "       t->right = N.left;",
+       "       return t;",
+       "}",
+       "",
+       "static void",
+       "insert_it(Vertex *v, int L)",
+       "{      Vertex *new, *t;",
+       "       ulong i; int nr;",
+       "",
+       "       i = mk_key(v);",
+       "       nr = ((L*TWIDTH)+Tally);",
+       "       t = layers[nr];",
+       "",
+       "       v->key = i; ",
+       "       if (!t)",
+       "       {       layers[nr] = v;",
+       "               return;",
+       "       }",
+       "       t = splay(i, t);",
+       "       if (i < t->key)",
+       "       {       new = v;",
+       "               new->left = t->left;",
+       "               new->right = t;",
+       "               t->left = (Vertex *) 0;",
+       "       } else if (i > t->key)",
+       "       {       new = v;",
+       "               new->right = t->right;",
+       "               new->left = t;",
+       "               t->right = (Vertex *) 0;",
+       "       } else   /* it's already there */",
+       "       {       v->lnk = t->lnk; /* put in linked list off v */",
+       "               t->lnk = v;",
+       "               new = t;",
+       "       }",
+       "       layers[nr] = new;",
+       "}",
+       "",
+       "static int",
+       "checkit(Vertex *h, Vertex *v, Vertex *n, uchar sigma)",
+       "{      Edge *g, *f;",
+       "       int i, k, j = 1;",
+       "",
+       "       for (k = 0; k < 2; k++)",
+       "               if (h->dst[k])",
+       "               {       if (sigma >= h->from[k] && sigma <= h->to[k])",
+       "                       {       if (h->dst[k] != n) goto no_match;",
+       "                       }",
+       "                       for (i = h->from[k]; i <= h->to[k]; i++)",
+       "                       {       if (i == sigma) continue;",
+       "                               g = cacheDelta(v, i, j); j = 0;",
+       "                               if (h->dst[k] != g->Dst)",
+       "                                       goto no_match;",
+       "                               if (g->s == 0 || g->S != i)",
+       "                                       i = g->To;",
+       "               }       }",
+       "       for (f = h->Succ; f; f = f->Nxt)",
+       "       {       if (INRANGE(f,sigma))",
+       "               {       if (f->Dst != n) goto no_match;",
+       "               }",
+       "               for (i = f->From; i <= f->To; i++)",
+       "               {       if (i == sigma) continue;",
+       "                       g = cacheDelta(v, i, j); j = 0;",
+       "                       if (f->Dst != g->Dst)",
+       "                               goto no_match;",
+       "                       if (g->s == 1 && i == g->S)",
+       "                               continue;",
+       "                       i = g->To;",
+       "               }",
+       "               if (f->s && f->S != sigma)",
+       "               {       g = cacheDelta(v, f->S, 1);",
+       "                       if (f->Dst != g->Dst)",
+       "                               goto no_match;",
+       "               }",
+       "       }",
+       "       if (h->Succ || h->dst[0] || h->dst[1]) return 1;",
+       "no_match:",
+       "       return 0;",
+       "}",
+       "",
+       "static Vertex *",
+       "find_it(Vertex *v, Vertex *n, uchar sigma, int L)",
+       "{      Vertex *z, *t;",
+       "       ulong i; int nr;",
+       "",
+       "       i = mk_special(sigma,n,v);",
+       "       nr = ((L*TWIDTH)+Tally);",
+       "       t = layers[nr];",
+       "",
+       "       if (!t) return (Vertex *) 0;",
+       "       layers[nr] = t = splay(i, t);",
+       "       if (i == t->key)",
+       "       for (z = t; z; z = z->lnk)",
+       "               if (checkit(z, v, n, sigma))",
+       "                       return z;",
+       "",
+       "       return (Vertex *) 0;",
+       "}",
+       "",
+       "static void",
+       "delete_it(Vertex *v, int L)",
+       "{      Vertex *x, *t;",
+       "       ulong i; int nr;",
+       "",
+       "       i = cheap_key(v);",
+       "       nr = ((L*TWIDTH)+Tally);",
+       "       t = layers[nr];",
+       "       if (!t) return;",
+       "",
+       "       t = splay(i, t);",
+       "       if (i == t->key)",
+       "       {       Vertex *z, *y = (Vertex *) 0;",
+       "               for (z = t; z && z != v; y = z, z = z->lnk)",
+       "                       ;",
+       "               if (z != v) goto bad;",
+       "               if (y)",
+       "               {       y->lnk = z->lnk;",
+       "                       z->lnk = (Vertex *) 0;",
+       "                       layers[nr] = t;",
+       "                       return;",
+       "               } else if (z->lnk)      /* z == t == v */",
+       "               {       y = z->lnk;",
+       "                       y->left = t->left;",
+       "                       y->right = t->right;",
+       "                       t->left = t->right = t->lnk = (Vertex *) 0;",
+       "                       layers[nr] = y;",
+       "                       return;",
+       "               }",
+       "               /* delete the node itself */",
+       "               if (!t->left)",
+       "               {       x = t->right;",
+       "               } else",
+       "               {       x = splay(i, t->left);",
+       "                       x->right = t->right;",
+       "               }",
+       "               t->left = t->right = t->lnk = (Vertex *) 0;",
+       "               layers[nr] = x;",
+       "               return;",
+       "       }",
+       "bad:   Uerror(\"cannot happen delete\");",
+       "}",
+       "#endif", /* MA */
+       0,
+};
diff --git a/trunk/verif/Spin/Src5.1.6/pangen5.c b/trunk/verif/Spin/Src5.1.6/pangen5.c
new file mode 100755 (executable)
index 0000000..68f62a3
--- /dev/null
@@ -0,0 +1,862 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+typedef struct BuildStack {
+       FSM_trans *t;
+       struct BuildStack *nxt;
+} BuildStack;
+
+extern ProcList        *rdy;
+extern int verbose, eventmapnr, claimnr, rvopt, export_ast, u_sync;
+extern Element *Al_El;
+
+static FSM_state *fsm_free;
+static FSM_trans *trans_free;
+static BuildStack *bs, *bf;
+static int max_st_id;
+static int cur_st_id;
+int o_max;
+FSM_state *fsm;
+FSM_state **fsm_tbl;
+FSM_use   *use_free;
+
+static void ana_seq(Sequence *);
+static void ana_stmnt(FSM_trans *, Lextok *, int);
+
+extern void AST_slice(void);
+extern void AST_store(ProcList *, int);
+extern int  has_global(Lextok *);
+extern void exit(int);
+
+static void
+fsm_table(void)
+{      FSM_state *f;
+       max_st_id += 2;
+       /* fprintf(stderr, "omax %d, max=%d\n", o_max, max_st_id); */
+       if (o_max < max_st_id)
+       {       o_max = max_st_id;
+               fsm_tbl = (FSM_state **) emalloc(max_st_id * sizeof(FSM_state *));
+       } else
+               memset((char *)fsm_tbl, 0, max_st_id * sizeof(FSM_state *));
+       cur_st_id = max_st_id;
+       max_st_id = 0;
+
+       for (f = fsm; f; f = f->nxt)
+               fsm_tbl[f->from] = f;
+}
+
+static int
+FSM_DFS(int from, FSM_use *u)
+{      FSM_state *f;
+       FSM_trans *t;
+       FSM_use *v;
+       int n;
+
+       if (from == 0)
+               return 1;
+
+       f = fsm_tbl[from];
+
+       if (!f)
+       {       printf("cannot find state %d\n", from);
+               fatal("fsm_dfs: cannot happen\n", (char *) 0);
+       }
+
+       if (f->seen)
+               return 1;
+       f->seen = 1;
+
+       for (t = f->t; t; t = t->nxt)
+       {
+               for (n = 0; n < 2; n++)
+               for (v = t->Val[n]; v; v = v->nxt)
+                       if (u->var == v->var)
+                               return n;       /* a read or write */
+
+               if (!FSM_DFS(t->to, u))
+                       return 0;
+       }
+       return 1;
+}
+
+static void
+new_dfs(void)
+{      int i;
+
+       for (i = 0; i < cur_st_id; i++)
+               if (fsm_tbl[i])
+                       fsm_tbl[i]->seen = 0;
+}
+
+static int
+good_dead(Element *e, FSM_use *u)
+{
+       switch (u->special) {
+       case 2: /* ok if it's a receive */
+               if (e->n->ntyp == ASGN
+               &&  e->n->rgt->ntyp == CONST
+               &&  e->n->rgt->val == 0)
+                       return 0;
+               break;
+       case 1: /* must be able to use oval */
+               if (e->n->ntyp != 'c'
+               &&  e->n->ntyp != 'r')
+                       return 0;       /* can't really happen */
+               break;
+       }
+       return 1;
+}
+
+#if 0
+static int howdeep = 0;
+#endif
+
+static int
+eligible(FSM_trans *v)
+{      Element *el = ZE;
+       Lextok  *lt = ZN;
+
+       if (v) el = v->step;
+       if (el) lt = v->step->n;
+
+       if (!lt                         /* dead end */
+       ||  v->nxt                      /* has alternatives */
+       ||  el->esc                     /* has an escape */
+       ||  (el->status&CHECK2)         /* remotely referenced */
+       ||  lt->ntyp == ATOMIC
+       ||  lt->ntyp == NON_ATOMIC      /* used for inlines -- should be able to handle this */
+       ||  lt->ntyp == IF
+       ||  lt->ntyp == C_CODE
+       ||  lt->ntyp == C_EXPR
+       ||  has_lab(el, 0)              /* any label at all */
+
+       ||  lt->ntyp == DO
+       ||  lt->ntyp == UNLESS
+       ||  lt->ntyp == D_STEP
+       ||  lt->ntyp == ELSE
+       ||  lt->ntyp == '@'
+       ||  lt->ntyp == 'c'
+       ||  lt->ntyp == 'r'
+       ||  lt->ntyp == 's')
+               return 0;
+
+       if (!(el->status&(2|4)))        /* not atomic */
+       {       int unsafe = (el->status&I_GLOB)?1:has_global(el->n);
+               if (unsafe)
+                       return 0;
+       }
+
+       return 1;
+}
+
+static int
+canfill_in(FSM_trans *v)
+{      Element *el = v->step;
+       Lextok  *lt = v->step->n;
+
+       if (!lt                         /* dead end */
+       ||  v->nxt                      /* has alternatives */
+       ||  el->esc                     /* has an escape */
+       ||  (el->status&CHECK2))        /* remotely referenced */
+               return 0;
+
+       if (!(el->status&(2|4))         /* not atomic */
+       &&  ((el->status&I_GLOB)
+       ||   has_global(el->n)))        /* and not safe */
+               return 0;
+
+       return 1;
+}
+
+static int
+pushbuild(FSM_trans *v)
+{      BuildStack *b;
+
+       for (b = bs; b; b = b->nxt)
+               if (b->t == v)
+                       return 0;
+       if (bf)
+       {       b = bf;
+               bf = bf->nxt;
+       } else
+               b = (BuildStack *) emalloc(sizeof(BuildStack));
+       b->t = v;
+       b->nxt = bs;
+       bs = b;
+       return 1;
+}
+
+static void
+popbuild(void)
+{      BuildStack *f;
+       if (!bs)
+               fatal("cannot happen, popbuild", (char *) 0);
+       f = bs;
+       bs = bs->nxt;
+       f->nxt = bf;
+       bf = f;                         /* freelist */
+}
+
+static int
+build_step(FSM_trans *v)
+{      FSM_state *f;
+       Element *el;
+#if 0
+       Lextok  *lt = ZN;
+#endif
+       int     st;
+       int     r;
+
+       if (!v) return -1;
+
+       el = v->step;
+       st = v->to;
+
+       if (!el) return -1;
+
+       if (v->step->merge)
+               return v->step->merge;  /* already done */
+
+       if (!eligible(v))               /* non-blocking */
+               return -1;
+
+       if (!pushbuild(v))              /* cycle detected */
+               return -1;              /* break cycle */
+
+       f = fsm_tbl[st];
+#if 0
+       lt = v->step->n;
+       if (verbose&32)
+       {       if (++howdeep == 1)
+                       printf("spin: %s, line %3d, merge:\n",
+                               lt->fn->name,
+                               lt->ln);
+               printf("\t[%d] <seqno %d>\t", howdeep, el->seqno);
+               comment(stdout, lt, 0);
+               printf(";\n");
+       }
+#endif
+       r = build_step(f->t);
+       v->step->merge = (r == -1) ? st : r;
+#if 0
+       if (verbose&32)
+       {       printf("        merge value: %d (st=%d,r=%d, line %d)\n",
+                       v->step->merge, st, r, el->n->ln);
+               howdeep--;
+       }
+#endif
+       popbuild();
+
+       return v->step->merge;
+}
+
+static void
+FSM_MERGER(/* char *pname */ void)     /* find candidates for safely merging steps */
+{      FSM_state *f, *g;
+       FSM_trans *t;
+       Lextok  *lt;
+
+       for (f = fsm; f; f = f->nxt)            /* all states */
+       for (t = f->t; t; t = t->nxt)           /* all edges */
+       {       if (!t->step) continue;         /* happens with 'unless' */
+
+               t->step->merge_in = f->in;      /* ?? */
+
+               if (t->step->merge)
+                       continue;
+               lt = t->step->n;
+
+               if (lt->ntyp == 'c'
+               ||  lt->ntyp == 'r'
+               ||  lt->ntyp == 's')    /* blocking stmnts */
+                       continue;       /* handled in 2nd scan */
+
+               if (!eligible(t))
+                       continue;
+
+               g = fsm_tbl[t->to];
+               if (!g || !eligible(g->t))
+               {
+#define SINGLES
+#ifdef SINGLES
+                       t->step->merge_single = t->to;
+#if 0
+                       if ((verbose&32))
+                       {       printf("spin: %s, line %3d, merge_single:\n\t<seqno %d>\t",
+                                       t->step->n->fn->name,
+                                       t->step->n->ln,
+                                       t->step->seqno);
+                               comment(stdout, t->step->n, 0);
+                               printf(";\n");
+                       }
+#endif
+#endif
+                       /* t is an isolated eligible step:
+                        *
+                        * a merge_start can connect to a proper
+                        * merge chain or to a merge_single
+                        * a merge chain can be preceded by
+                        * a merge_start, but not by a merge_single
+                        */
+
+                       continue;
+               }
+
+               (void) build_step(t);
+       }
+
+       /* 2nd scan -- find possible merge_starts */
+
+       for (f = fsm; f; f = f->nxt)            /* all states */
+       for (t = f->t; t; t = t->nxt)           /* all edges */
+       {       if (!t->step || t->step->merge)
+                       continue;
+
+               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
+       statement within the atomic sequence
+       the same is not true for non-rv send operations
+#endif
+
+               if (lt->ntyp == 'c'     /* potentially blocking stmnts */
+               ||  lt->ntyp == 'r'
+               ||  (lt->ntyp == 's' && u_sync == 0))   /* added !u_sync in 4.1.3 */
+               {       if (!canfill_in(t))             /* atomic, non-global, etc. */
+                               continue;
+
+                       g = fsm_tbl[t->to];
+                       if (!g || !g->t || !g->t->step)
+                               continue;
+                       if (g->t->step->merge)
+                               t->step->merge_start = g->t->step->merge;
+#ifdef SINGLES
+                       else if (g->t->step->merge_single)
+                               t->step->merge_start = g->t->step->merge_single;
+#endif
+#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,
+                                               t->step->seqno);
+                               comment(stdout, lt, 0);
+                               printf(";\n");
+                       }
+#endif
+               }
+       }
+}
+
+static void
+FSM_ANA(void)
+{      FSM_state *f;
+       FSM_trans *t;
+       FSM_use *u, *v, *w;
+       int n;
+
+       for (f = fsm; f; f = f->nxt)            /* all states */
+       for (t = f->t; t; t = t->nxt)           /* all edges */
+       for (n = 0; n < 2; n++)                 /* reads and writes */
+       for (u = t->Val[n]; u; u = u->nxt)
+       {       if (!u->var->context    /* global */
+               ||   u->var->type == CHAN
+               ||   u->var->type == STRUCT)
+                       continue;
+               new_dfs();
+               if (FSM_DFS(t->to, u))  /* cannot hit read before hitting write */
+                       u->special = n+1;       /* means, reset to 0 after use */
+       }
+
+       if (!export_ast)
+       for (f = fsm; f; f = f->nxt)
+       for (t = f->t; t; t = t->nxt)
+       for (n = 0; n < 2; n++)
+       for (u = t->Val[n], w = (FSM_use *) 0; u; )
+       {       if (u->special)
+               {       v = u->nxt;
+                       if (!w)                 /* remove from list */
+                               t->Val[n] = v;
+                       else
+                               w->nxt = v;
+#if q
+                       if (verbose&32)
+                       {       printf("%s : %3d:  %d -> %d \t",
+                                       t->step->n->fn->name,
+                                       t->step->n->ln,
+                                       f->from,
+                                       t->to);
+                               comment(stdout, t->step->n, 0);
+                               printf("\t%c%d: %s\n", n==0?'R':'L',
+                                       u->special, u->var->name);
+                       }
+#endif
+                       if (good_dead(t->step, u))
+                       {       u->nxt = t->step->dead; /* insert into dead */
+                               t->step->dead = u;
+                       }
+                       u = v;
+               } else
+               {       w = u;
+                       u = u->nxt;
+       }       }
+}
+
+void
+rel_use(FSM_use *u)
+{
+       if (!u) return;
+       rel_use(u->nxt);
+       u->var = (Symbol *) 0;
+       u->special = 0;
+       u->nxt = use_free;
+       use_free = u;
+}
+
+static void
+rel_trans(FSM_trans *t)
+{
+       if (!t) return;
+       rel_trans(t->nxt);
+       rel_use(t->Val[0]);
+       rel_use(t->Val[1]);
+       t->Val[0] = t->Val[1] = (FSM_use *) 0;
+       t->nxt = trans_free;
+       trans_free = t;
+}
+
+static void
+rel_state(FSM_state *f)
+{
+       if (!f) return;
+       rel_state(f->nxt);
+       rel_trans(f->t);
+       f->t = (FSM_trans *) 0;
+       f->nxt = fsm_free;
+       fsm_free = f;
+}
+
+static void
+FSM_DEL(void)
+{
+       rel_state(fsm);
+       fsm = (FSM_state *) 0;
+}
+
+static FSM_state *
+mkstate(int s)
+{      FSM_state *f;
+
+       /* fsm_tbl isn't allocated yet */
+       for (f = fsm; f; f = f->nxt)
+               if (f->from == s)
+                       break;
+       if (!f)
+       {       if (fsm_free)
+               {       f = fsm_free;
+                       memset(f, 0, sizeof(FSM_state));
+                       fsm_free = fsm_free->nxt;
+               } else
+                       f = (FSM_state *) emalloc(sizeof(FSM_state));
+               f->from = s;
+               f->t = (FSM_trans *) 0;
+               f->nxt = fsm;
+               fsm = f;
+               if (s > max_st_id)
+                       max_st_id = s;
+       }
+       return f;
+}
+
+static FSM_trans *
+get_trans(int to)
+{      FSM_trans *t;
+
+       if (trans_free)
+       {       t = trans_free;
+               memset(t, 0, sizeof(FSM_trans));
+               trans_free = trans_free->nxt;
+       } else
+               t = (FSM_trans *) emalloc(sizeof(FSM_trans));
+
+       t->to = to;
+       return t;
+}
+
+static void
+FSM_EDGE(int from, int to, Element *e)
+{      FSM_state *f;
+       FSM_trans *t;
+
+       f = mkstate(from);      /* find it or else make it */
+       t = get_trans(to);
+
+       t->step = e;
+       t->nxt = f->t;
+       f->t = t;
+
+       f = mkstate(to);
+       f->in++;
+
+       if (export_ast)
+       {       t = get_trans(from);
+               t->step = e;
+               t->nxt = f->p;  /* from is a predecessor of to */
+               f->p = t;
+       }
+
+       if (t->step)
+               ana_stmnt(t, t->step->n, 0);
+}
+
+#define LVAL   1
+#define RVAL   0
+
+static void
+ana_var(FSM_trans *t, Lextok *now, int usage)
+{      FSM_use *u, *v;
+
+       if (!t || !now || !now->sym)
+               return;
+
+       if (now->sym->name[0] == '_'
+       &&  (strcmp(now->sym->name, "_") == 0
+       ||   strcmp(now->sym->name, "_pid") == 0
+       ||   strcmp(now->sym->name, "_last") == 0))
+               return;
+
+       v = t->Val[usage];
+       for (u = v; u; u = u->nxt)
+               if (u->var == now->sym)
+                       return; /* it's already there */
+
+       if (!now->lft)
+       {       /* not for array vars -- it's hard to tell statically
+                  if the index would, at runtime, evaluate to the
+                  same values at lval and rval references
+               */
+               if (use_free)
+               {       u = use_free;
+                       use_free = use_free->nxt;
+               } else
+                       u = (FSM_use *) emalloc(sizeof(FSM_use));
+       
+               u->var = now->sym;
+               u->nxt = t->Val[usage];
+               t->Val[usage] = u;
+       } else
+                ana_stmnt(t, now->lft, RVAL);  /* index */
+
+       if (now->sym->type == STRUCT
+       &&  now->rgt
+       &&  now->rgt->lft)
+               ana_var(t, now->rgt->lft, usage);
+}
+
+static void
+ana_stmnt(FSM_trans *t, Lextok *now, int usage)
+{      Lextok *v;
+
+       if (!t || !now) return;
+
+       switch (now->ntyp) {
+       case '.':
+       case BREAK:
+       case GOTO:
+       case CONST:
+       case TIMEOUT:
+       case NONPROGRESS:
+       case  ELSE:
+       case '@':
+       case 'q':
+       case IF:
+       case DO:
+       case ATOMIC:
+       case NON_ATOMIC:
+       case D_STEP:
+       case C_CODE:
+       case C_EXPR:
+               break;
+
+       case '!':       
+       case UMIN:
+       case '~':
+       case ENABLED:
+       case PC_VAL:
+       case LEN:
+       case FULL:
+       case EMPTY:
+       case NFULL:
+       case NEMPTY:
+       case ASSERT:
+       case 'c':
+               ana_stmnt(t, now->lft, RVAL);
+               break;
+
+       case '/':
+       case '*':
+       case '-':
+       case '+':
+       case '%':
+       case '&':
+       case '^':
+       case '|':
+       case LT:
+       case GT:
+       case LE:
+       case GE:
+       case NE:
+       case EQ:
+       case OR:
+       case AND:
+       case LSHIFT:
+       case RSHIFT:
+               ana_stmnt(t, now->lft, RVAL);
+               ana_stmnt(t, now->rgt, RVAL);
+               break;
+
+       case ASGN:
+               ana_stmnt(t, now->lft, LVAL);
+               ana_stmnt(t, now->rgt, RVAL);
+               break;
+
+       case PRINT:
+       case RUN:
+               for (v = now->lft; v; v = v->rgt)
+                       ana_stmnt(t, v->lft, RVAL);
+               break;
+
+       case PRINTM:
+               if (now->lft && !now->lft->ismtyp)
+                       ana_stmnt(t, now->lft, RVAL);
+               break;
+
+       case 's':
+               ana_stmnt(t, now->lft, RVAL);
+               for (v = now->rgt; v; v = v->rgt)
+                       ana_stmnt(t, v->lft, RVAL);
+               break;
+
+       case 'R':
+       case 'r':
+               ana_stmnt(t, now->lft, RVAL);
+               for (v = now->rgt; v; v = v->rgt)
+               {       if (v->lft->ntyp == EVAL)
+                               ana_stmnt(t, v->lft->lft, RVAL);
+                       else
+                       if (v->lft->ntyp != CONST
+                       &&  now->ntyp != 'R')           /* was v->lft->ntyp */
+                               ana_stmnt(t, v->lft, LVAL);
+               }
+               break;
+
+       case '?':
+               ana_stmnt(t, now->lft, RVAL);
+               if (now->rgt)
+               {       ana_stmnt(t, now->rgt->lft, RVAL);
+                       ana_stmnt(t, now->rgt->rgt, RVAL);
+               }
+               break;
+
+       case NAME:
+               ana_var(t, now, usage);
+               break;
+
+       case   'p':     /* remote ref */
+               ana_stmnt(t, now->lft->lft, RVAL);      /* process id */
+               ana_var(t, now, RVAL);
+               ana_var(t, now->rgt, RVAL);
+               break;
+
+       default:
+               printf("spin: bad node type %d line %d (ana_stmnt)\n", now->ntyp, now->ln);
+               fatal("aborting", (char *) 0);
+       }
+}
+
+void
+ana_src(int dataflow, int merger)      /* called from main.c and guided.c */
+{      ProcList *p;
+       Element *e;
+#if 0
+       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();
+
+               e = p->s->frst;
+#if 0
+               if (dataflow || merger)
+               {       printf("spin: %d, optimizing '%s'",
+                               counter++, p->n->name);
+                       fflush(stdout);
+               }
+#endif
+               if (dataflow)
+               {       FSM_ANA();
+               }
+               if (merger)
+               {       FSM_MERGER(/* p->n->name */);
+                       huntele(e, e->status, -1)->merge_in = 1; /* start-state */
+#if 0
+                       printf("\n");
+#endif
+               }
+               if (export_ast)
+                       AST_store(p, huntele(e, e->status, -1)->seqno);
+
+               FSM_DEL();
+       }
+       for (e = Al_El; e; e = e->Nxt)
+       {
+               if (!(e->status&DONE) && (verbose&32))
+               {       printf("unreachable code: ");
+                       printf("%s, line %3d:  ",
+                               e->n->fn->name, e->n->ln);
+                       comment(stdout, e->n, 0);
+                       printf("\n");
+               }
+               e->status &= ~DONE;
+       }
+       if (export_ast)
+       {       AST_slice();
+               exit(0);
+       }
+}
+
+void
+spit_recvs(FILE *f1, FILE *f2) /* called from pangen2.c */
+{      Element *e;
+       Sequence *s;
+       extern int Unique;
+
+       fprintf(f1, "unsigned char Is_Recv[%d];\n", Unique);
+
+       fprintf(f2, "void\nset_recvs(void)\n{\n");
+       for (e = Al_El; e; e = e->Nxt)
+       {       if (!e->n) continue;
+
+               switch (e->n->ntyp) {
+               case 'r':
+markit:                        fprintf(f2, "\tIs_Recv[%d] = 1;\n", e->Seqno);
+                       break;
+               case D_STEP:
+                       s = e->n->sl->this;
+                       switch (s->frst->n->ntyp) {
+                       case DO:
+                               fatal("unexpected: do at start of d_step", (char *) 0);
+                       case IF: /* conservative: fall through */
+                       case 'r': goto markit;
+                       }
+                       break;
+               }
+       }
+       fprintf(f2, "}\n");
+
+       if (rvopt)
+       {
+       fprintf(f2, "int\nno_recvs(int me)\n{\n");
+       fprintf(f2, "   int h; uchar ot; short tt;\n");
+       fprintf(f2, "   Trans *t;\n");
+       fprintf(f2, "   for (h = BASE; h < (int) now._nr_pr; h++)\n");
+       fprintf(f2, "   {       if (h == me) continue;\n");
+       fprintf(f2, "           tt = (short) ((P0 *)pptr(h))->_p;\n");
+       fprintf(f2, "           ot = (uchar) ((P0 *)pptr(h))->_t;\n");
+       fprintf(f2, "           for (t = trans[ot][tt]; t; t = t->nxt)\n");
+       fprintf(f2, "                   if (Is_Recv[t->t_id]) return 0;\n");
+       fprintf(f2, "   }\n");
+       fprintf(f2, "   return 1;\n");
+       fprintf(f2, "}\n");
+       }
+}
+
+static void
+ana_seq(Sequence *s)
+{      SeqList *h;
+       Sequence *t;
+       Element *e, *g;
+       int From, To;
+
+       for (e = s->frst; e; e = e->nxt)
+       {       if (e->status & DONE)
+                       goto checklast;
+
+               e->status |= DONE;
+
+               From = e->seqno;
+
+               if (e->n->ntyp == UNLESS)
+                       ana_seq(e->sub->this);
+               else if (e->sub)
+               {       for (h = e->sub; h; h = h->nxt)
+                       {       g = huntstart(h->this->frst);
+                               To = g->seqno;
+
+                               if (g->n->ntyp != 'c'
+                               ||  g->n->lft->ntyp != CONST
+                               ||  g->n->lft->val != 0
+                               ||  g->esc)
+                                       FSM_EDGE(From, To, e);
+                               /* else it's a dead link */
+                       }
+                       for (h = e->sub; h; h = h->nxt)
+                               ana_seq(h->this);
+               } else if (e->n->ntyp == ATOMIC
+                       ||  e->n->ntyp == D_STEP
+                       ||  e->n->ntyp == NON_ATOMIC)
+               {
+                       t = e->n->sl->this;
+                       g = huntstart(t->frst);
+                       t->last->nxt = e->nxt;
+                       To = g->seqno;
+                       FSM_EDGE(From, To, e);
+
+                       ana_seq(t);
+               } else 
+               {       if (e->n->ntyp == GOTO)
+                       {       g = get_lab(e->n, 1);
+                               g = huntele(g, e->status, -1);
+                               To = g->seqno;
+                       } else if (e->nxt)
+                       {       g = huntele(e->nxt, e->status, -1);
+                               To = g->seqno;
+                       } else
+                               To = 0;
+
+                       FSM_EDGE(From, To, e);
+
+                       if (e->esc
+                       &&  e->n->ntyp != GOTO
+                       &&  e->n->ntyp != '.')
+                       for (h = e->esc; h; h = h->nxt)
+                       {       g = huntstart(h->this->frst);
+                               To = g->seqno;
+                               FSM_EDGE(From, To, ZE);
+                               ana_seq(h->this);
+                       }
+               }
+
+checklast:     if (e == s->last)
+                       break;
+       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/pangen5.h b/trunk/verif/Spin/Src5.1.6/pangen5.h
new file mode 100755 (executable)
index 0000000..8a876ef
--- /dev/null
@@ -0,0 +1,424 @@
+/***** 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            */
+
+static char *Xpt[] = {
+       "#if defined(MA) && (defined(W_XPT) || defined(R_XPT))",
+       "static Vertex  **temptree;",
+       "static char    wbuf[4096];",
+       "static int     WCNT = 4096, wcnt=0;",
+       "static uchar   stacker[MA+1];",
+       "static ulong   stackcnt = 0;",
+       "extern double  nstates, nlinks, truncs, truncs2;",
+       "",
+       "static void",
+       "xwrite(int fd, char *b, int n)",
+       "{",
+       "       if (wcnt+n >= 4096)",
+       "       {       write(fd, wbuf, wcnt);",
+       "               wcnt = 0;",
+       "       }",
+       "       memcpy(&wbuf[wcnt], b, n);",
+       "       wcnt += n;",
+       "}",
+       "",
+       "static void",
+       "wclose(fd)",
+       "{",
+       "       if (wcnt > 0)",
+       "               write(fd, wbuf, wcnt);",
+       "       wcnt = 0;",
+       "       close(fd);",
+       "}",
+       "",
+       "static void",
+       "w_vertex(int fd, Vertex *v)",
+       "{      char t[3]; int i; Edge *e;",
+       "",
+       "       xwrite(fd, (char *) &v,  sizeof(Vertex *));",
+       "       t[0] = 0;",
+       "       for (i = 0; i < 2; i++)",
+       "               if (v->dst[i])",
+       "               {       t[1] = v->from[i], t[2] = v->to[i];",
+       "                       xwrite(fd, t, 3);",
+       "                       xwrite(fd, (char *) &(v->dst[i]), sizeof(Vertex *));",
+       "               }",
+       "       for (e = v->Succ; e; e = e->Nxt)",
+       "       {       t[1] = e->From, t[2] = e->To;",
+       "               xwrite(fd, t, 3);",
+       "               xwrite(fd, (char *) &(e->Dst), sizeof(Vertex *));",
+       "",
+       "               if (e->s)",
+       "               {       t[1] = t[2] = e->S;",
+       "                       xwrite(fd, t, 3);",
+       "                       xwrite(fd, (char *) &(e->Dst), sizeof(Vertex *));",
+       "       }       }",
+       "}",
+       "",
+       "static void",
+       "w_layer(int fd, Vertex *v)",
+       "{      uchar c=1;",
+       "",
+       "       if (!v) return;",
+       "       xwrite(fd, (char *) &c, 1);",
+       "       w_vertex(fd, v);",
+       "       w_layer(fd, v->lnk);",
+       "       w_layer(fd, v->left);",
+       "       w_layer(fd, v->right);",
+       "}",
+       "",
+       "void",
+       "w_xpoint(void)",
+       "{      int fd; char nm[64];",
+       "       int i, j;  uchar c;",
+       "       static uchar xwarned = 0;",
+       "",
+       "       sprintf(nm, \"%%s.xpt\", PanSource);",
+       "       if ((fd = creat(nm, 0666)) <= 0)",
+       "       if (!xwarned)",
+       "       {       xwarned = 1;",
+       "               printf(\"cannot creat checkpoint file\\n\");",
+       "               return;",
+       "       }",
+       "       xwrite(fd, (char *) &nstates, sizeof(double));",
+       "       xwrite(fd, (char *) &truncs, sizeof(double));",
+       "       xwrite(fd, (char *) &truncs2, sizeof(double));",
+       "       xwrite(fd, (char *) &nlinks, sizeof(double));",
+       "       xwrite(fd, (char *) &dfa_depth, sizeof(int));",
+       "       xwrite(fd, (char *) &R,  sizeof(Vertex *));",
+       "       xwrite(fd, (char *) &F,  sizeof(Vertex *));",
+       "       xwrite(fd, (char *) &NF, sizeof(Vertex *));",
+       "",
+       "       for (j = 0; j < TWIDTH; j++)",
+       "       for (i = 0; i < dfa_depth+1; i++)",
+       "       {       w_layer(fd, layers[i*TWIDTH+j]);",
+       "               c = 2; xwrite(fd, (char *) &c, 1);",
+       "       }",
+       "       wclose(fd);",
+       "}",
+       "",
+       "static void",
+       "xread(int fd, char *b, int n)",
+       "{      int m = wcnt; int delta = 0;",
+       "       if (m < n)",
+       "       {       if (m > 0) memcpy(b, &wbuf[WCNT-m], m);",
+       "               delta = m;",
+       "               WCNT = wcnt = read(fd, wbuf, 4096);",
+       "               if (wcnt < n-m)",
+       "                       Uerror(\"xread failed -- insufficient data\");",
+       "               n -= m;",
+       "       }",
+       "       memcpy(&b[delta], &wbuf[WCNT-wcnt], n);",
+       "       wcnt -= n;",
+       "}",
+       "",
+       "static void",
+       "x_cleanup(Vertex *c)",
+       "{      Edge *e;        /* remove the tree and edges from c */",
+       "       if (!c) return;",
+       "       for (e = c->Succ; e; e = e->Nxt)",
+       "               x_cleanup(e->Dst);",
+       "       recyc_vertex(c);",
+       "}",
+       "",
+       "static void",
+       "x_remove(void)",
+       "{      Vertex *tmp; int i, s;",
+       "       int r, j;",
+       "       /* double-check: */",
+       "       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);",
+       "               for (i = 0; i < dfa_depth; i++)",
+       "                       printf(\"%%d,\", stacker[i]);",
+       "               printf(\" -- not a stackstate <o:%%d,4:%%d>\\n\", r, j);",
+       "               return;",
+       "       }",
+       "       stacker[dfa_depth-1] = 1;",
+       "       s = dfa_member(dfa_depth-1);",
+       "",
+       "       { tmp = F; F = NF; NF = tmp; }  /* complement */",
+       "               if (s) dfa_store(stacker);",
+       "               stacker[dfa_depth-1] = 0;",
+       "               dfa_store(stacker);",
+       "               stackcnt++;",
+       "       { tmp = F; F = NF; NF = tmp; }",
+       "}",
+       "",
+       "static void",
+       "x_rm_stack(Vertex *t, int k)",
+       "{      int j; Edge *e;",
+       "",
+       "       if (k == 0)",
+       "       {       x_remove();",
+       "               return;",
+       "       }",
+       "       if (t)",
+       "       for (e = t->Succ; e; e = e->Nxt)",
+       "       {       for (j = e->From; j <= (int) e->To; j++)",
+       "               {       stacker[k] = (uchar) j;",
+       "                       x_rm_stack(e->Dst, k-1);",
+       "               }",
+       "               if (e->s)",
+       "               {       stacker[k] = e->S;",
+       "                       x_rm_stack(e->Dst, k-1);",
+       "       }       }",
+       "}",
+       "",
+       "static Vertex *",
+       "insert_withkey(Vertex *v, int L)",
+       "{      Vertex *new, *t = temptree[L];",
+       "",
+       "       if (!t) { temptree[L] = v; return v; }",
+       "       t = splay(v->key, t);",
+       "       if (v->key < t->key)",
+       "       {       new = v;",
+       "               new->left = t->left;",
+       "               new->right = t;",
+       "               t->left = (Vertex *) 0;",
+       "       } else if (v->key > t->key)",
+       "       {       new = v;",
+       "               new->right = t->right;",
+       "               new->left = t;",
+       "               t->right = (Vertex *) 0;",
+       "       } else",
+       "       {       if (t != R && t != F && t != NF)",
+       "                       Uerror(\"double insert, bad checkpoint data\");",
+       "               else",
+       "               {       recyc_vertex(v);",
+       "                       new = t;",
+       "       }       }",
+       "       temptree[L] = new;",
+       "",
+       "       return new;",
+       "}",
+       "",
+       "static Vertex *",
+       "find_withkey(Vertex *v, int L)",
+       "{      Vertex *t = temptree[L];",
+       "       if (t)",
+       "       {       temptree[L] = t = splay((ulong) v, t);",
+       "               if (t->key == (ulong) v)",
+       "                       return t;",
+       "       }",
+       "       Uerror(\"not found error, bad checkpoint data\");",
+       "       return (Vertex *) 0;",
+       "}",
+       "",
+       "void",
+       "r_layer(int fd, int n)",
+       "{      Vertex *v;",
+       "       Edge *e;",
+       "       char c, t[2];",
+       "",
+       "       for (;;)",
+       "       {       xread(fd, &c, 1);",
+       "               if (c == 2) break;",
+       "               if (c == 1)",
+       "               {       v = new_vertex();",
+       "                       xread(fd, (char *) &(v->key), sizeof(Vertex *));",
+       "                       v = insert_withkey(v, n);",
+       "               } else  /* c == 0 */",
+       "               {       e = new_edge((Vertex *) 0);",
+       "                       xread(fd, t, 2);",
+       "                       e->From = t[0];",
+       "                       e->To = t[1];",
+       "                       xread(fd, (char *) &(e->Dst), sizeof(Vertex *));",
+       "                       insert_edge(v, e);",
+       "       }       }",
+       "}",
+       "",
+       "static void",
+       "v_fix(Vertex *t, int nr)",
+       "{      int i; Edge *e;",
+       "",
+       "       if (!t) return;",
+       "",
+       "       for (i = 0; i < 2; i++)",
+       "       if (t->dst[i])",
+       "               t->dst[i] = find_withkey(t->dst[i], nr);",
+       "",
+       "       for (e = t->Succ; e; e = e->Nxt)",
+       "               e->Dst = find_withkey(e->Dst, nr);",
+       "               ",
+       "       v_fix(t->left, nr);",
+       "       v_fix(t->right, nr);",
+       "}",
+       "",
+       "static void",
+       "v_insert(Vertex *t, int nr)",
+       "{      Edge *e; int i;",
+       "",
+       "       if (!t) return;",
+       "       v_insert(t->left, nr);",
+       "       v_insert(t->right, nr);",
+       "",
+       "       /* remove only leafs from temptree */",
+       "       t->left = t->right = t->lnk = (Vertex *) 0;",
+       "       insert_it(t, nr);       /* into layers */",
+       "       for (i = 0; i < 2; i++)",
+       "               if (t->dst[i])",
+       "                       t->dst[i]->num += (t->to[i] - t->from[i] + 1);",
+       "       for (e = t->Succ; e; e = e->Nxt)",
+       "               e->Dst->num += (e->To - e->From + 1 + e->s);",
+       "}",
+       "",
+       "static void",
+       "x_fixup(void)",
+       "{      int i;",
+       "",
+       "       for (i = 0; i < dfa_depth; i++)",
+       "               v_fix(temptree[i], (i+1));",
+       "",
+       "       for (i = dfa_depth; i >= 0; i--)",
+       "               v_insert(temptree[i], i);",
+       "}",
+       "",
+       "static Vertex *",
+       "x_tail(Vertex *t, ulong want)",
+       "{      int i, yes, no; Edge *e; Vertex *v = (Vertex *) 0;",
+       "",
+       "       if (!t) return v;",
+       "",
+       "       yes = no = 0;",
+       "       for (i = 0; i < 2; i++)",
+       "               if ((ulong) t->dst[i] == want)",
+       "               {       /* was t->from[i] <= 0 && t->to[i] >= 0 */",
+       "                       /* but from and to are uchar */",
+       "                       if (t->from[i] == 0)",
+       "                               yes = 1;",
+       "                       else",
+       "                       if (t->from[i] <= 4 && t->to[i] >= 4)",
+       "                               no = 1;",
+       "               }",
+       "",
+       "       for (e = t->Succ; e; e = e->Nxt)",
+       "               if ((ulong) e->Dst == want)",
+       "               {       /* was INRANGE(e,0) but From and To are uchar */",
+       "                       if ((e->From == 0) || (e->s==1 && e->S==0))",
+       "                               yes = 1;",
+       "                       else if (INRANGE(e, 4))",
+       "                               no = 1;",
+       "               }",
+       "       if (yes && !no) return t;",
+       "       v = x_tail(t->left, want);  if (v) return v;",
+       "       v = x_tail(t->right, want); if (v) return v;",
+       "       return (Vertex *) 0;",
+       "}",
+       "",
+       "static void",
+       "x_anytail(Vertex *t, Vertex *c, int nr)",
+       "{      int i; Edge *e, *f; Vertex *v;",
+       "",
+       "       if (!t) return;",
+       "",
+       "       for (i = 0; i < 2; i++)",
+       "               if ((ulong) t->dst[i] == c->key)",
+       "               {       v = new_vertex(); v->key = t->key;",
+       "                       f = new_edge(v);",
+       "                       f->From = t->from[i];",
+       "                       f->To = t->to[i];",
+       "                       f->Nxt = c->Succ;",
+       "                       c->Succ = f;",
+       "                       if (nr > 0)",
+       "                       x_anytail(temptree[nr-1], v, nr-1);",
+       "               }",
+       "",
+       "       for (e = t->Succ; e; e = e->Nxt)",
+       "               if ((ulong) e->Dst == c->key)",
+       "               {       v = new_vertex(); v->key = t->key;",
+       "                       f = new_edge(v);",
+       "                       f->From = e->From;",
+       "                       f->To = e->To;",
+       "                       f->s = e->s;",
+       "                       f->S = e->S;",
+       "                       f->Nxt = c->Succ;",
+       "                       c->Succ = f;",
+       "                       x_anytail(temptree[nr-1], v, nr-1);",
+       "               }",
+       "",
+       "       x_anytail(t->left, c, nr);",
+       "       x_anytail(t->right, c, nr);",
+       "}",
+       "",
+       "static Vertex *",
+       "x_cpy_rev(void)",
+       "{      Vertex *c, *v;  /* find 0 and !4 predecessor of F */",
+       "",
+       "       v = x_tail(temptree[dfa_depth-1], F->key);",
+       "       if (!v) return (Vertex *) 0;",
+       "",
+       "       c = new_vertex(); c->key = v->key;",
+       "",
+       "       /* every node on dfa_depth-2 that has v->key as succ */",
+       "       /* make copy and let c point to these (reversing ptrs) */",
+       "",
+       "       x_anytail(temptree[dfa_depth-2], c, dfa_depth-2);",
+       " ",
+       "       return c;",
+       "}",
+       "",
+       "void",
+       "r_xpoint(void)",
+       "{      int fd; char nm[64]; Vertex *d;",
+       "       int i, j;",
+       "",
+       "       wcnt = 0;",
+       "       sprintf(nm, \"%%s.xpt\", PanSource);",
+       "       if ((fd = open(nm, 0)) < 0)     /* O_RDONLY */",
+       "               Uerror(\"cannot open checkpoint file\");",
+       "",
+       "       xread(fd, (char *) &nstates,   sizeof(double));",
+       "       xread(fd, (char *) &truncs,    sizeof(double));",
+       "       xread(fd, (char *) &truncs2,   sizeof(double));",
+       "       xread(fd, (char *) &nlinks,    sizeof(double));",
+       "       xread(fd, (char *) &dfa_depth, sizeof(int));",
+       "",
+       "       if (dfa_depth != MA+a_cycles)",
+       "               Uerror(\"bad dfa_depth in checkpoint file\");",
+       "",
+       "       path      = (Vertex **) emalloc((dfa_depth+1)*sizeof(Vertex *));",
+       "       layers    = (Vertex **) emalloc(TWIDTH*(dfa_depth+1)*sizeof(Vertex *));",
+       "       temptree  = (Vertex **) emalloc((dfa_depth+2)*sizeof(Vertex *));",
+       "       lastword  = (uchar *)   emalloc((dfa_depth+1)*sizeof(uchar));",
+       "       lastword[dfa_depth] = lastword[0] = 255; ",
+       "",
+       "       path[0] = R = new_vertex();",
+       "       xread(fd, (char *) &R->key, sizeof(Vertex *));",
+       "       R = insert_withkey(R, 0);",
+       "",
+       "       F = new_vertex();",
+       "       xread(fd, (char *) &F->key, sizeof(Vertex *));",
+       "       F = insert_withkey(F, dfa_depth);",
+       "",
+       "       NF = new_vertex();",
+       "       xread(fd, (char *) &NF->key, sizeof(Vertex *));",
+       "       NF = insert_withkey(NF, dfa_depth);",
+       "",
+       "       for (j = 0; j < TWIDTH; j++)",
+       "       for (i = 0; i < dfa_depth+1; i++)",
+       "               r_layer(fd, i);",
+       "",
+       "       if (wcnt != 0) Uerror(\"bad count in checkpoint file\");",
+       "",
+       "       d = x_cpy_rev();",
+       "       x_fixup();",
+       "       stacker[dfa_depth-1] = 0;",
+       "       x_rm_stack(d, dfa_depth-2);",
+       "       x_cleanup(d);",
+       "       close(fd);",
+       "",
+       "       printf(\"pan: removed %%d stackstates\\n\", stackcnt);",
+       "       nstates -= (double) stackcnt;",
+       "}",
+       "#endif",
+       0,
+};
diff --git a/trunk/verif/Spin/Src5.1.6/pangen6.c b/trunk/verif/Spin/Src5.1.6/pangen6.c
new file mode 100755 (executable)
index 0000000..ec2658e
--- /dev/null
@@ -0,0 +1,2354 @@
+/***** 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            */
+
+/* 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"
+
+extern Ordered  *all_names;
+extern FSM_use   *use_free;
+extern FSM_state **fsm_tbl;
+extern FSM_state *fsm;
+extern int      verbose, o_max;
+
+static FSM_trans *cur_t;
+static FSM_trans *expl_par;
+static FSM_trans *expl_var;
+static FSM_trans *explicit;
+
+extern void rel_use(FSM_use *);
+
+#define ulong  unsigned long
+
+typedef struct Pair {
+       FSM_state       *h;
+       int             b;
+       struct Pair     *nxt;
+} Pair;
+
+typedef struct AST {
+       ProcList *p;            /* proctype decl */
+       int     i_st;           /* start state */
+       int     nstates, nwords;
+       int     relevant;
+       Pair    *pairs;         /* entry and exit nodes of proper subgraphs */
+       FSM_state *fsm;         /* proctype body */
+       struct AST *nxt;        /* linked list */
+} AST;
+
+typedef struct RPN {           /* relevant proctype names */
+       Symbol  *rn;
+       struct RPN *nxt;
+} RPN;
+
+typedef struct ALIAS {         /* channel aliasing info */
+       Lextok  *cnm;           /* this chan */
+       int     origin;         /* debugging - origin of the alias */
+       struct ALIAS    *alias; /* can be an alias for these other chans */
+       struct ALIAS    *nxt;   /* linked list */
+} ALIAS;
+
+typedef struct ChanList {
+       Lextok *s;              /* containing stmnt */
+       Lextok *n;              /* point of reference - could be struct */
+       struct ChanList *nxt;   /* linked list */
+} ChanList;
+
+/* a chan alias can be created in one of three ways:
+       assignement to chan name
+               a = b -- a is now an alias for b
+       passing chan name as parameter in run
+               run x(b) -- proctype x(chan a)
+       passing chan name through channel
+               x!b -- x?a
+ */
+
+#define USE            1
+#define DEF            2
+#define DEREF_DEF      4
+#define DEREF_USE      8
+
+static AST     *ast;
+static ALIAS   *chalcur;
+static ALIAS   *chalias;
+static ChanList        *chanlist;
+static Slicer  *slicer;
+static Slicer  *rel_vars;      /* all relevant variables */
+static int     AST_Changes;
+static int     AST_Round;
+static RPN     *rpn;
+static int     in_recv = 0;
+
+static int     AST_mutual(Lextok *, Lextok *, int);
+static void    AST_dominant(void);
+static void    AST_hidden(void);
+static void    AST_setcur(Lextok *);
+static void    check_slice(Lextok *, int);
+static void    curtail(AST *);
+static void    def_use(Lextok *, int);
+static void    name_AST_track(Lextok *, int);
+static void    show_expl(void);
+
+static int
+AST_isini(Lextok *n)   /* is this an initialized channel */
+{      Symbol *s;
+
+       if (!n || !n->sym) return 0;
+
+       s = n->sym;
+
+       if (s->type == CHAN)
+               return (s->ini->ntyp == CHAN); /* freshly instantiated */
+
+       if (s->type == STRUCT && n->rgt)
+               return AST_isini(n->rgt->lft);
+
+       return 0;
+}
+
+static void
+AST_var(Lextok *n, Symbol *s, int toplevel)
+{
+       if (!s) return;
+
+       if (toplevel)
+       {       if (s->context && s->type)
+                       printf(":%s:L:", s->context->name);
+               else
+                       printf("G:");
+       }
+       printf("%s", s->name); /* array indices ignored */
+
+       if (s->type == STRUCT && n && n->rgt && n->rgt->lft)
+       {       printf(":");
+               AST_var(n->rgt->lft, n->rgt->lft->sym, 0);
+       }
+}
+
+static void
+name_def_indices(Lextok *n, int code)
+{
+       if (!n || !n->sym) return;
+
+       if (n->sym->nel != 1)
+               def_use(n->lft, code);          /* process the index */
+
+       if (n->sym->type == STRUCT              /* and possible deeper ones */
+       &&  n->rgt)
+               name_def_indices(n->rgt->lft, code);
+}
+
+static void
+name_def_use(Lextok *n, int code)
+{      FSM_use *u;
+
+       if (!n) return;
+
+       if ((code&USE)
+       &&  cur_t->step
+       &&  cur_t->step->n)
+       {       switch (cur_t->step->n->ntyp) {
+               case 'c': /* possible predicate abstraction? */
+                       n->sym->colnr |= 2; /* yes */
+                       break;
+               default:
+                       n->sym->colnr |= 1; /* no  */
+                       break;
+               }
+       }
+
+       for (u = cur_t->Val[0]; u; u = u->nxt)
+               if (AST_mutual(n, u->n, 1)
+               &&  u->special == code)
+                       return;
+
+       if (use_free)
+       {       u = use_free;
+               use_free = use_free->nxt;
+       } else
+               u = (FSM_use *) emalloc(sizeof(FSM_use));
+       
+       u->n = n;
+       u->special = code;
+       u->nxt = cur_t->Val[0];
+       cur_t->Val[0] = u;
+
+       name_def_indices(n, USE|(code&(~DEF))); /* not def, but perhaps deref */
+}
+
+static void
+def_use(Lextok *now, int code)
+{      Lextok *v;
+
+       if (now)
+       switch (now->ntyp) {
+       case '!':       
+       case UMIN:      
+       case '~':
+       case 'c':
+       case ENABLED:
+       case ASSERT:
+       case EVAL:
+               def_use(now->lft, USE|code);
+               break;
+
+       case LEN:
+       case FULL:
+       case EMPTY:
+       case NFULL:
+       case NEMPTY:
+               def_use(now->lft, DEREF_USE|USE|code);
+               break;
+
+       case '/':
+       case '*':
+       case '-':
+       case '+':
+       case '%':
+       case '&':
+       case '^':
+       case '|':
+       case LE:
+       case GE:
+       case GT:
+       case LT:
+       case NE:
+       case EQ:
+       case OR:
+       case AND:
+       case LSHIFT:
+       case RSHIFT:
+               def_use(now->lft, USE|code);
+               def_use(now->rgt, USE|code); 
+               break;
+
+       case ASGN:
+               def_use(now->lft, DEF|code);
+               def_use(now->rgt, USE|code);
+               break;
+
+       case TYPE:      /* name in parameter list */
+               name_def_use(now, code);
+               break;
+
+       case NAME:
+               name_def_use(now, code);
+               break;
+
+       case RUN:
+               name_def_use(now, USE);                 /* procname - not really needed */
+               for (v = now->lft; v; v = v->rgt)
+                       def_use(v->lft, USE);           /* params */
+               break;
+
+       case 's':
+               def_use(now->lft, DEREF_DEF|DEREF_USE|USE|code);
+               for (v = now->rgt; v; v = v->rgt)
+                       def_use(v->lft, USE|code);
+               break;
+
+       case 'r':
+               def_use(now->lft, DEREF_DEF|DEREF_USE|USE|code);
+               for (v = now->rgt; v; v = v->rgt)
+               {       if (v->lft->ntyp == EVAL)
+                               def_use(v->lft, code);  /* will add USE */
+                       else if (v->lft->ntyp != CONST)
+                               def_use(v->lft, DEF|code);
+               }
+               break;
+
+       case 'R':
+               def_use(now->lft, DEREF_USE|USE|code);
+               for (v = now->rgt; v; v = v->rgt)
+               {       if (v->lft->ntyp == EVAL)
+                               def_use(v->lft, code); /* will add USE */
+               }
+               break;
+
+       case '?':
+               def_use(now->lft, USE|code);
+               if (now->rgt)
+               {       def_use(now->rgt->lft, code);
+                       def_use(now->rgt->rgt, code);
+               }
+               break;  
+
+       case PRINT:
+               for (v = now->lft; v; v = v->rgt)
+                       def_use(v->lft, USE|code);
+               break;
+
+       case PRINTM:
+               def_use(now->lft, USE);
+               break;
+
+       case CONST:
+       case ELSE:      /* ? */
+       case NONPROGRESS:
+       case PC_VAL:
+       case   'p':
+       case   'q':
+               break;
+
+       case   '.':
+       case  GOTO:
+       case BREAK:
+       case   '@':
+       case D_STEP:
+       case ATOMIC:
+       case NON_ATOMIC:
+       case IF:
+       case DO:
+       case UNLESS:
+       case TIMEOUT:
+       case C_CODE:
+       case C_EXPR:
+       default:
+               break;
+       }
+}
+
+static int
+AST_add_alias(Lextok *n, int nr)
+{      ALIAS *ca;
+       int res;
+
+       for (ca = chalcur->alias; ca; ca = ca->nxt)
+               if (AST_mutual(ca->cnm, n, 1))
+               {       res = (ca->origin&nr);
+                       ca->origin |= nr;       /* 1, 2, or 4 - run, asgn, or rcv */
+                       return (res == 0);      /* 0 if already there with same origin */
+               }
+
+       ca = (ALIAS *) emalloc(sizeof(ALIAS));
+       ca->cnm = n;
+       ca->origin = nr;
+       ca->nxt = chalcur->alias;
+       chalcur->alias = ca;
+       return 1;
+}
+
+static void
+AST_run_alias(char *pn, char *s, Lextok *t, int parno)
+{      Lextok *v;
+       int cnt;
+
+       if (!t) return;
+
+       if (t->ntyp == RUN)
+       {       if (strcmp(t->sym->name, s) == 0)
+               for (v = t->lft, cnt = 1; v; v = v->rgt, cnt++)
+                       if (cnt == parno)
+                       {       AST_add_alias(v->lft, 1); /* RUN */
+                               break;
+                       }
+       } else
+       {       AST_run_alias(pn, s, t->lft, parno);
+               AST_run_alias(pn, s, t->rgt, parno);
+       }
+}
+
+static void
+AST_findrun(char *s, int parno)
+{      FSM_state *f;
+       FSM_trans *t;
+       AST *a;
+
+       for (a = ast; a; a = a->nxt)            /* automata       */
+       for (f = a->fsm; f; f = f->nxt)         /* control states */
+       for (t = f->t; t; t = t->nxt)           /* transitions    */
+       {       if (t->step)
+               AST_run_alias(a->p->n->name, s, t->step->n, parno);
+       }
+}
+
+static void
+AST_par_chans(ProcList *p)     /* find local chan's init'd to chan passed as param */
+{      Ordered *walk;
+       Symbol  *sp;
+
+       for (walk = all_names; walk; walk = walk->next)
+       {       sp = walk->entry;
+               if (sp
+               &&  sp->context
+               &&  strcmp(sp->context->name, p->n->name) == 0
+               &&  sp->Nid >= 0        /* not itself a param */
+               &&  sp->type == CHAN
+               &&  sp->ini->ntyp == NAME)      /* != CONST and != CHAN */
+               {       Lextok *x = nn(ZN, 0, ZN, ZN);
+                       x->sym = sp;
+                       AST_setcur(x);
+                       AST_add_alias(sp->ini, 2);      /* ASGN */
+       }       }
+}
+
+static void
+AST_para(ProcList *p)
+{      Lextok *f, *t, *c;
+       int cnt = 0;
+
+       AST_par_chans(p);
+
+       for (f = p->p; f; f = f->rgt)           /* list of types */
+       for (t = f->lft; t; t = t->rgt)
+       {       if (t->ntyp != ',')
+                       c = t;
+               else
+                       c = t->lft;     /* expanded struct */
+
+               cnt++;
+               if (Sym_typ(c) == CHAN)
+               {       ALIAS *na = (ALIAS *) emalloc(sizeof(ALIAS));
+
+                       na->cnm = c;
+                       na->nxt = chalias;
+                       chalcur = chalias = na;
+#if 0
+                       printf("%s -- (par) -- ", p->n->name);
+                       AST_var(c, c->sym, 1);
+                       printf(" => <<");
+#endif
+                       AST_findrun(p->n->name, cnt);
+#if 0
+                       printf(">>\n");
+#endif
+               }
+       }
+}
+
+static void
+AST_haschan(Lextok *c)
+{
+       if (!c) return;
+       if (Sym_typ(c) == CHAN)
+       {       AST_add_alias(c, 2);    /* ASGN */
+#if 0
+               printf("<<");
+               AST_var(c, c->sym, 1);
+               printf(">>\n");
+#endif
+       } else
+       {       AST_haschan(c->rgt);
+               AST_haschan(c->lft);
+       }
+}
+
+static int
+AST_nrpar(Lextok *n) /* 's' or 'r' */
+{      Lextok *m;
+       int j = 0;
+
+       for (m = n->rgt; m; m = m->rgt)
+               j++;
+       return j;
+}
+
+static int
+AST_ord(Lextok *n, Lextok *s)
+{      Lextok *m;
+       int j = 0;
+
+       for (m = n->rgt; m; m = m->rgt)
+       {       j++;
+               if (s->sym == m->lft->sym)
+                       return j;
+       }
+       return 0;
+}
+
+#if 0
+static void
+AST_ownership(Symbol *s)
+{
+       if (!s) return;
+       printf("%s:", s->name);
+       AST_ownership(s->owner);
+}
+#endif
+
+static int
+AST_mutual(Lextok *a, Lextok *b, int toplevel)
+{      Symbol *as, *bs;
+
+       if (!a && !b) return 1;
+
+       if (!a || !b) return 0;
+
+       as = a->sym;
+       bs = b->sym;
+
+       if (!as || !bs) return 0;
+
+       if (toplevel && as->context != bs->context)
+               return 0;
+
+       if (as->type != bs->type)
+               return 0;
+
+       if (strcmp(as->name, bs->name) != 0)
+               return 0;
+
+       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;
+}
+
+static void
+AST_setcur(Lextok *n)  /* set chalcur */
+{      ALIAS *ca;
+
+       for (ca = chalias; ca; ca = ca->nxt)
+               if (AST_mutual(ca->cnm, n, 1))  /* if same chan */
+               {       chalcur = ca;
+                       return;
+               }
+
+       ca = (ALIAS *) emalloc(sizeof(ALIAS));
+       ca->cnm = n;
+       ca->nxt = chalias;
+       chalcur = chalias = ca;
+}
+
+static void
+AST_other(AST *a)      /* check chan params in asgns and recvs */
+{      FSM_state *f;
+       FSM_trans *t;
+       FSM_use *u;
+       ChanList *cl;
+
+       for (f = a->fsm; f; f = f->nxt)         /* control states */
+       for (t = f->t; t; t = t->nxt)           /* transitions    */
+       for (u = t->Val[0]; u; u = u->nxt)      /* def/use info   */
+               if (Sym_typ(u->n) == CHAN
+               &&  (u->special&DEF))           /* def of chan-name  */
+               {       AST_setcur(u->n);
+                       switch (t->step->n->ntyp) {
+                       case ASGN:
+                               AST_haschan(t->step->n->rgt);
+                               break;
+                       case 'r':
+                               /* guess sends where name may originate */
+                               for (cl = chanlist; cl; cl = cl->nxt)   /* all sends */
+                               {       int aa = AST_nrpar(cl->s);
+                                       int bb = AST_nrpar(t->step->n);
+                                       if (aa != bb)   /* matching nrs of params */
+                                               continue;
+
+                                       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 */
+                               }
+                               break;
+                       default:
+                               printf("type = %d\n", t->step->n->ntyp);
+                               non_fatal("unexpected chan def type", (char *) 0);
+                               break;
+               }       }
+}
+
+static void
+AST_aliases(void)
+{      ALIAS *na, *ca;
+
+       for (na = chalias; na; na = na->nxt)
+       {       printf("\npossible aliases of ");
+               AST_var(na->cnm, na->cnm->sym, 1);
+               printf("\n\t");
+               for (ca = na->alias; ca; ca = ca->nxt)
+               {       if (!ca->cnm->sym)
+                               printf("no valid name ");
+                       else
+                               AST_var(ca->cnm, ca->cnm->sym, 1);
+                       printf("<");
+                       if (ca->origin & 1) printf("RUN ");
+                       if (ca->origin & 2) printf("ASGN ");
+                       if (ca->origin & 4) printf("RCV ");
+                       printf("[%s]", AST_isini(ca->cnm)?"Initzd":"Name");
+                       printf(">");
+                       if (ca->nxt) printf(", ");
+               }
+               printf("\n");
+       }
+       printf("\n");
+}
+
+static void
+AST_indirect(FSM_use *uin, FSM_trans *t, char *cause, char *pn)
+{      FSM_use *u;
+
+       /* this is a newly discovered relevant statement */
+       /* all vars it uses to contribute to its DEF are new criteria */
+
+       if (!(t->relevant&1)) AST_Changes++;
+
+       t->round = AST_Round;
+       t->relevant = 1;
+
+       if ((verbose&32) && t->step)
+       {       printf("\tDR %s [[ ", pn);
+               comment(stdout, t->step->n, 0);
+               printf("]]\n\t\tfully relevant %s", cause);
+               if (uin) { printf(" due to "); AST_var(uin->n, uin->n->sym, 1); }
+               printf("\n");
+       }
+       for (u = t->Val[0]; u; u = u->nxt)
+               if (u != uin
+               && (u->special&(USE|DEREF_USE)))
+               {       if (verbose&32)
+                       {       printf("\t\t\tuses(%d): ", u->special);
+                               AST_var(u->n, u->n->sym, 1);
+                               printf("\n");
+                       }
+                       name_AST_track(u->n, u->special);       /* add to slice criteria */
+               }
+}
+
+static void
+def_relevant(char *pn, FSM_trans *t, Lextok *n, int ischan)
+{      FSM_use *u;
+       ALIAS *na, *ca;
+       int chanref;
+
+       /* look for all DEF's of n
+        *      mark those stmnts relevant
+        *      mark all var USEs in those stmnts as criteria
+        */
+
+       if (n->ntyp != ELSE)
+       for (u = t->Val[0]; u; u = u->nxt)
+       {       chanref = (Sym_typ(u->n) == CHAN);
+
+               if (ischan != chanref                   /* no possible match  */
+               || !(u->special&(DEF|DEREF_DEF)))       /* not a def */
+                       continue;
+
+               if (AST_mutual(u->n, n, 1))
+               {       AST_indirect(u, t, "(exact match)", pn);
+                       continue;
+               }
+
+               if (chanref)
+               for (na = chalias; na; na = na->nxt)
+               {       if (!AST_mutual(u->n, na->cnm, 1))
+                               continue;
+                       for (ca = na->alias; ca; ca = ca->nxt)
+                               if (AST_mutual(ca->cnm, n, 1)
+                               &&  AST_isini(ca->cnm)) 
+                               {       AST_indirect(u, t, "(alias match)", pn);
+                                       break;
+                               }
+                       if (ca) break;
+       }       }       
+}
+
+static void
+AST_relevant(Lextok *n)
+{      AST *a;
+       FSM_state *f;
+       FSM_trans *t;
+       int ischan;
+
+       /* look for all DEF's of n
+        *      mark those stmnts relevant
+        *      mark all var USEs in those stmnts as criteria
+        */
+
+       if (!n) return;
+       ischan = (Sym_typ(n) == CHAN);
+
+       if (verbose&32)
+       {       printf("<<ast_relevant (ntyp=%d) ", n->ntyp);
+               AST_var(n, n->sym, 1);
+               printf(">>\n");
+       }
+
+       for (t = expl_par; t; t = t->nxt)       /* param assignments */
+       {       if (!(t->relevant&1))
+               def_relevant(":params:", t, n, ischan);
+       }
+
+       for (t = expl_var; t; t = t->nxt)
+       {       if (!(t->relevant&1))           /* var inits */
+               def_relevant(":vars:", t, n, ischan);
+       }
+
+       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)
+               for (f = a->fsm; f; f = f->nxt)
+               for (t = f->t; t; t = t->nxt)
+               {       if (!(t->relevant&1))
+                       def_relevant(a->p->n->name, t, n, ischan);
+       }       }
+}
+
+static int
+AST_relpar(char *s)
+{      FSM_trans *t, *T;
+       FSM_use *u;
+
+       for (T = expl_par; T; T = (T == expl_par)?expl_var: (FSM_trans *) 0)
+       for (t = T; t; t = t->nxt)
+       {       if (t->relevant&1)
+               for (u = t->Val[0]; u; u = u->nxt)
+               {       if (u->n->sym->type
+                       &&  u->n->sym->context
+                       &&  strcmp(u->n->sym->context->name, s) == 0)
+                       {
+                               if (verbose&32)
+                               {       printf("proctype %s relevant, due to symbol ", s);
+                                       AST_var(u->n, u->n->sym, 1);
+                                       printf("\n");
+                               }
+                               return 1;
+       }       }       }
+       return 0;
+}
+
+static void
+AST_dorelevant(void)
+{      AST *a;
+       RPN *r;
+
+       for (r = rpn; r; r = r->nxt)
+       {       for (a = ast; a; a = a->nxt)
+                       if (strcmp(a->p->n->name, r->rn->name) == 0)
+                       {       a->relevant |= 1;
+                               break;
+                       }
+               if (!a)
+               fatal("cannot find proctype %s", r->rn->name);
+       }               
+}
+
+static void
+AST_procisrelevant(Symbol *s)
+{      RPN *r;
+       for (r = rpn; r; r = r->nxt)
+               if (strcmp(r->rn->name, s->name) == 0)
+                       return;
+       r = (RPN *) emalloc(sizeof(RPN));
+       r->rn = s;
+       r->nxt = rpn;
+       rpn = r;
+}
+
+static int
+AST_proc_isrel(char *s)
+{      AST *a;
+
+       for (a = ast; a; a = a->nxt)
+               if (strcmp(a->p->n->name, s) == 0)
+                       return (a->relevant&1);
+       non_fatal("cannot happen, missing proc in ast", (char *) 0);
+       return 0;
+}
+
+static int
+AST_scoutrun(Lextok *t)
+{
+       if (!t) return 0;
+
+       if (t->ntyp == RUN)
+               return AST_proc_isrel(t->sym->name);
+       return (AST_scoutrun(t->lft) || AST_scoutrun(t->rgt));
+}
+
+static void
+AST_tagruns(void)
+{      AST *a;
+       FSM_state *f;
+       FSM_trans *t;
+
+       /* if any stmnt inside a proctype is relevant
+        * or any parameter passed in a run
+        * then so are all the run statements on that proctype
+        */
+
+       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)
+               {       a->relevant |= 1;       /* the proctype is relevant */
+                       continue;
+               }
+               if (AST_relpar(a->p->n->name))
+                       a->relevant |= 1;
+               else
+               {       for (f = a->fsm; f; f = f->nxt)
+                       for (t = f->t; t; t = t->nxt)
+                               if (t->relevant)
+                                       goto yes;
+yes:                   if (f)
+                               a->relevant |= 1;
+               }
+       }
+
+       for (a = ast; a; a = a->nxt)
+       for (f = a->fsm; f; f = f->nxt)
+       for (t = f->t; t; t = t->nxt)
+               if (t->step
+               &&  AST_scoutrun(t->step->n))
+               {       AST_indirect((FSM_use *)0, t, ":run:", a->p->n->name);
+                       /* BUT, not all actual params are relevant */
+               }
+}
+
+static void
+AST_report(AST *a, Element *e) /* ALSO deduce irrelevant vars */
+{
+       if (!(a->relevant&2))
+       {       a->relevant |= 2;
+               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,
+               e->n?e->n->fn->name:"-",
+               e->seqno);
+       printf("        [");
+       comment(stdout, e->n, 0);
+       printf("]\n");
+}
+
+static int
+AST_always(Lextok *n)
+{
+       if (!n) return 0;
+
+       if (n->ntyp == '@'      /* -end */
+       ||  n->ntyp == 'p')     /* remote reference */
+               return 1;
+       return AST_always(n->lft) || AST_always(n->rgt);
+}
+
+static void
+AST_edge_dump(AST *a, FSM_state *f)
+{      FSM_trans *t;
+       FSM_use *u;
+
+       for (t = f->t; t; t = t->nxt)   /* edges */
+       {
+               if (t->step && AST_always(t->step->n))
+                       t->relevant |= 1;       /* always relevant */
+
+               if (verbose&32)
+               {       switch (t->relevant) {
+                       case  0: printf("     "); break;
+                       case  1: printf("*%3d ", t->round); break;
+                       case  2: printf("+%3d ", t->round); break;
+                       case  3: printf("#%3d ", t->round); break;
+                       default: printf("? "); break;
+                       }
+       
+                       printf("%d\t->\t%d\t", f->from, t->to);
+                       if (t->step)
+                               comment(stdout, t->step->n, 0);
+                       else
+                               printf("Unless");
+       
+                       for (u = t->Val[0]; u; u = u->nxt)
+                       {       printf(" <");
+                               AST_var(u->n, u->n->sym, 1);
+                               printf(":%d>", u->special);
+                       }
+                       printf("\n");
+               } else
+               {       if (t->relevant)
+                               continue;
+
+                       if (t->step)
+                       switch(t->step->n->ntyp) {
+                       case ASGN:
+                       case 's':
+                       case 'r':
+                       case 'c':
+                               if (t->step->n->lft->ntyp != CONST)
+                                       AST_report(a, t->step);
+                               break;
+
+                       case PRINT:     /* don't report */
+                       case PRINTM:
+                       case ASSERT:
+                       case C_CODE:
+                       case C_EXPR:
+                       default:
+                               break;
+       }       }       }
+}
+
+static void
+AST_dfs(AST *a, int s, int vis)
+{      FSM_state *f;
+       FSM_trans *t;
+
+       f = fsm_tbl[s];
+       if (f->seen) return;
+
+       f->seen = 1;
+       if (vis) AST_edge_dump(a, f);
+
+       for (t = f->t; t; t = t->nxt)
+               AST_dfs(a, t->to, vis);
+}
+
+static void
+AST_dump(AST *a)
+{      FSM_state *f;
+
+       for (f = a->fsm; f; f = f->nxt)
+       {       f->seen = 0;
+               fsm_tbl[f->from] = f;
+       }
+
+       if (verbose&32)
+               printf("AST_START %s from %d\n", a->p->n->name, a->i_st);
+
+       AST_dfs(a, a->i_st, 1);
+}
+
+static void
+AST_sends(AST *a)
+{      FSM_state *f;
+       FSM_trans *t;
+       FSM_use *u;
+       ChanList *cl;
+
+       for (f = a->fsm; f; f = f->nxt)         /* control states */
+       for (t = f->t; t; t = t->nxt)           /* transitions    */
+       {       if (t->step
+               &&  t->step->n
+               &&  t->step->n->ntyp == 's')
+               for (u = t->Val[0]; u; u = u->nxt)
+               {       if (Sym_typ(u->n) == CHAN
+                       &&  ((u->special&USE) && !(u->special&DEREF_USE)))
+                       {
+#if 0
+                               printf("%s -- (%d->%d) -- ",
+                                       a->p->n->name, f->from, t->to);
+                               AST_var(u->n, u->n->sym, 1);
+                               printf(" -> chanlist\n");
+#endif
+                               cl = (ChanList *) emalloc(sizeof(ChanList));
+                               cl->s = t->step->n;
+                               cl->n = u->n;
+                               cl->nxt = chanlist;
+                               chanlist = cl;
+}      }       }       }
+
+static ALIAS *
+AST_alfind(Lextok *n)
+{      ALIAS *na;
+
+       for (na = chalias; na; na = na->nxt)
+               if (AST_mutual(na->cnm, n, 1))
+                       return na;
+       return (ALIAS *) 0;
+}
+
+static void
+AST_trans(void)
+{      ALIAS *na, *ca, *da, *ea;
+       int nchanges;
+
+       do {
+               nchanges = 0;
+               for (na = chalias; na; na = na->nxt)
+               {       chalcur = na;
+                       for (ca = na->alias; ca; ca = ca->nxt)
+                       {       da = AST_alfind(ca->cnm);
+                               if (da)
+                               for (ea = da->alias; ea; ea = ea->nxt)
+                               {       nchanges += AST_add_alias(ea->cnm,
+                                                       ea->origin|ca->origin);
+               }       }       }
+       } while (nchanges > 0);
+
+       chalcur = (ALIAS *) 0;
+}
+
+static void
+AST_def_use(AST *a)
+{      FSM_state *f;
+       FSM_trans *t;
+
+       for (f = a->fsm; f; f = f->nxt)         /* control states */
+       for (t = f->t; t; t = t->nxt)           /* all edges */
+       {       cur_t = t;
+               rel_use(t->Val[0]);             /* redo Val; doesn't cover structs */
+               rel_use(t->Val[1]);
+               t->Val[0] = t->Val[1] = (FSM_use *) 0;
+
+               if (!t->step) continue;
+
+               def_use(t->step->n, 0);         /* def/use info, including structs */
+       }
+       cur_t = (FSM_trans *) 0;
+}
+
+static void
+name_AST_track(Lextok *n, int code)
+{      extern int nr_errs;
+#if 0
+       printf("AST_name: ");
+       AST_var(n, n->sym, 1);
+       printf(" -- %d\n", code);
+#endif
+       if (in_recv && (code&DEF) && (code&USE))
+       {       printf("spin: error: DEF and USE of same var in rcv stmnt: ");
+               AST_var(n, n->sym, 1);
+               printf(" -- %d\n", code);
+               nr_errs++;
+       }
+       check_slice(n, code);
+}
+
+void
+AST_track(Lextok *now, int code)       /* called from main.c */
+{      Lextok *v; extern int export_ast;
+
+       if (!export_ast) return;
+
+       if (now)
+       switch (now->ntyp) {
+       case LEN:
+       case FULL:
+       case EMPTY:
+       case NFULL:
+       case NEMPTY:
+               AST_track(now->lft, DEREF_USE|USE|code);
+               break;
+
+       case '/':
+       case '*':
+       case '-':
+       case '+':
+       case '%':
+       case '&':
+       case '^':
+       case '|':
+       case LE:
+       case GE:
+       case GT:
+       case LT:
+       case NE:
+       case EQ:
+       case OR:
+       case AND:
+       case LSHIFT:
+       case RSHIFT:
+               AST_track(now->rgt, USE|code);
+               /* fall through */
+       case '!':       
+       case UMIN:      
+       case '~':
+       case 'c':
+       case ENABLED:
+       case ASSERT:
+               AST_track(now->lft, USE|code);
+               break;
+
+       case EVAL:
+               AST_track(now->lft, USE|(code&(~DEF)));
+               break;
+
+       case NAME:
+               name_AST_track(now, code);
+               if (now->sym->nel != 1)
+                       AST_track(now->lft, USE|code);  /* index */
+               break;
+
+       case 'R':
+               AST_track(now->lft, DEREF_USE|USE|code);
+               for (v = now->rgt; v; v = v->rgt)
+                       AST_track(v->lft, code); /* a deeper eval can add USE */
+               break;
+
+       case '?':
+               AST_track(now->lft, USE|code);
+               if (now->rgt)
+               {       AST_track(now->rgt->lft, code);
+                       AST_track(now->rgt->rgt, code);
+               }
+               break;
+
+/* added for control deps: */
+       case TYPE:      
+               name_AST_track(now, code);
+               break;
+       case ASGN:
+               AST_track(now->lft, DEF|code);
+               AST_track(now->rgt, USE|code);
+               break;
+       case RUN:
+               name_AST_track(now, USE);
+               for (v = now->lft; v; v = v->rgt)
+                       AST_track(v->lft, USE|code);
+               break;
+       case 's':
+               AST_track(now->lft, DEREF_DEF|DEREF_USE|USE|code);
+               for (v = now->rgt; v; v = v->rgt)
+                       AST_track(v->lft, USE|code);
+               break;
+       case 'r':
+               AST_track(now->lft, DEREF_DEF|DEREF_USE|USE|code);
+               for (v = now->rgt; v; v = v->rgt)
+               {       in_recv++;
+                       AST_track(v->lft, DEF|code);
+                       in_recv--;
+               }
+               break;
+       case PRINT:
+               for (v = now->lft; v; v = v->rgt)
+                       AST_track(v->lft, USE|code);
+               break;
+       case PRINTM:
+               AST_track(now->lft, USE);
+               break;
+/* end add */
+       case   'p':
+#if 0
+                          'p' -sym-> _p
+                          /
+                        '?' -sym-> a (proctype)
+                        /
+                       b (pid expr)
+#endif
+               AST_track(now->lft->lft, USE|code);
+               AST_procisrelevant(now->lft->sym);
+               break;
+
+       case CONST:
+       case ELSE:
+       case NONPROGRESS:
+       case PC_VAL:
+       case   'q':
+               break;
+
+       case   '.':
+       case  GOTO:
+       case BREAK:
+       case   '@':
+       case D_STEP:
+       case ATOMIC:
+       case NON_ATOMIC:
+       case IF:
+       case DO:
+       case UNLESS:
+       case TIMEOUT:
+       case C_CODE:
+       case C_EXPR:
+               break;
+
+       default:
+               printf("AST_track, NOT EXPECTED ntyp: %d\n", now->ntyp);
+               break;
+       }
+}
+
+static int
+AST_dump_rel(void)
+{      Slicer *rv;
+       Ordered *walk;
+       char buf[64];
+       int banner=0;
+
+       if (verbose&32)
+       {       printf("Relevant variables:\n");
+               for (rv = rel_vars; rv; rv = rv->nxt)
+               {       printf("\t");
+                       AST_var(rv->n, rv->n->sym, 1);
+                       printf("\n");
+               }
+               return 1;
+       }
+       for (rv = rel_vars; rv; rv = rv->nxt)
+               rv->n->sym->setat = 1;  /* mark it */
+
+       for (walk = all_names; walk; walk = walk->next)
+       {       Symbol *s;
+               s = walk->entry;
+               if (!s->setat
+               &&  (s->type != MTYPE || s->ini->ntyp != CONST)
+               &&  s->type != STRUCT   /* report only fields */
+               &&  s->type != PROCTYPE
+               &&  !s->owner
+               &&  sputtype(buf, s->type))
+               {       if (!banner)
+                       {       banner = 1;
+                               printf("spin: redundant vars (for given property):\n");
+                       }
+                       printf("\t");
+                       symvar(s);
+       }       }
+       return banner;
+}
+
+static void
+AST_suggestions(void)
+{      Symbol *s;
+       Ordered *walk;
+       FSM_state *f;
+       FSM_trans *t;
+       AST *a;
+       int banner=0;
+       int talked=0;
+
+       for (walk = all_names; walk; walk = walk->next)
+       {       s = walk->entry;
+               if (s->colnr == 2       /* only used in conditionals */
+               &&  (s->type == BYTE
+               ||   s->type == SHORT
+               ||   s->type == INT
+               ||   s->type == MTYPE))
+               {       if (!banner)
+                       {       banner = 1;
+                               printf("spin: consider using predicate");
+                               printf(" abstraction to replace:\n");
+                       }
+                       printf("\t");
+                       symvar(s);
+       }       }
+
+       /* look for source and sink processes */
+
+       for (a = ast; a; a = a->nxt)            /* automata       */
+       {       banner = 0;
+               for (f = a->fsm; f; f = f->nxt) /* control states */
+               for (t = f->t; t; t = t->nxt)   /* transitions    */
+               {       if (t->step)
+                       switch (t->step->n->ntyp) {
+                       case 's':
+                               banner |= 1;
+                               break;
+                       case 'r':
+                               banner |= 2;
+                               break;
+                       case '.':
+                       case D_STEP:
+                       case ATOMIC:
+                       case NON_ATOMIC:
+                       case IF:
+                       case DO:
+                       case UNLESS:
+                       case '@':
+                       case GOTO:
+                       case BREAK:
+                       case PRINT:
+                       case PRINTM:
+                       case ASSERT:
+                       case C_CODE:
+                       case C_EXPR:
+                               break;
+                       default:
+                               banner |= 4;
+                               goto no_good;
+                       }
+               }
+no_good:       if (banner == 1 || banner == 2)
+               {       printf("spin: proctype %s defines a %s process\n",
+                               a->p->n->name,
+                               banner==1?"source":"sink");
+                       talked |= banner;
+               } else if (banner == 3)
+               {       printf("spin: proctype %s mimics a buffer\n",
+                               a->p->n->name);
+                       talked |= 4;
+               }
+       }
+       if (talked&1)
+       {       printf("\tto reduce complexity, consider merging the code of\n");
+               printf("\teach source process into the code of its target\n");
+       }
+       if (talked&2)
+       {       printf("\tto reduce complexity, consider merging the code of\n");
+               printf("\teach sink process into the code of its source\n");
+       }
+       if (talked&4)
+               printf("\tto reduce complexity, avoid buffer processes\n");
+}
+
+static void
+AST_preserve(void)
+{      Slicer *sc, *nx, *rv;
+
+       for (sc = slicer; sc; sc = nx)
+       {       if (!sc->used)
+                       break;  /* done */
+
+               nx = sc->nxt;
+
+               for (rv = rel_vars; rv; rv = rv->nxt)
+                       if (AST_mutual(sc->n, rv->n, 1))
+                               break;
+
+               if (!rv) /* not already there */
+               {       sc->nxt = rel_vars;
+                       rel_vars = sc;
+       }       }
+       slicer = sc;
+}
+
+static void
+check_slice(Lextok *n, int code)
+{      Slicer *sc;
+
+       for (sc = slicer; sc; sc = sc->nxt)
+               if (AST_mutual(sc->n, n, 1)
+               &&  sc->code == code)
+                       return; /* already there */
+
+       sc = (Slicer *) emalloc(sizeof(Slicer));
+       sc->n = n;
+
+       sc->code = code;
+       sc->used = 0;
+       sc->nxt = slicer;
+       slicer = sc;
+}
+
+static void
+AST_data_dep(void)
+{      Slicer *sc;
+
+       /* mark all def-relevant transitions */
+       for (sc = slicer; sc; sc = sc->nxt)
+       {       sc->used = 1;
+               if (verbose&32)
+               {       printf("spin: slice criterion ");
+                       AST_var(sc->n, sc->n->sym, 1);
+                       printf(" type=%d\n", Sym_typ(sc->n));
+               }
+               AST_relevant(sc->n);
+       }
+       AST_tagruns();  /* mark 'run's relevant if target proctype is relevant */
+}
+
+static int
+AST_blockable(AST *a, int s)
+{      FSM_state *f;
+       FSM_trans *t;
+
+       f = fsm_tbl[s];
+
+       for (t = f->t; t; t = t->nxt)
+       {       if (t->relevant&2)
+                       return 1;
+
+               if (t->step && t->step->n)
+               switch (t->step->n->ntyp) {
+               case IF:
+               case DO:
+               case ATOMIC:
+               case NON_ATOMIC:
+               case D_STEP:
+                       if (AST_blockable(a, t->to))
+                       {       t->round = AST_Round;
+                               t->relevant |= 2;
+                               return 1;
+                       }
+                       /* else fall through */
+               default:
+                       break;
+               }
+               else if (AST_blockable(a, t->to))       /* Unless */
+               {       t->round = AST_Round;
+                       t->relevant |= 2;
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+static void
+AST_spread(AST *a, int s)
+{      FSM_state *f;
+       FSM_trans *t;
+
+       f = fsm_tbl[s];
+
+       for (t = f->t; t; t = t->nxt)
+       {       if (t->relevant&2)
+                       continue;
+
+               if (t->step && t->step->n)
+                       switch (t->step->n->ntyp) {
+                       case IF:
+                       case DO:
+                       case ATOMIC:
+                       case NON_ATOMIC:
+                       case D_STEP:
+                               AST_spread(a, t->to);
+                               /* fall thru */
+                       default:
+                               t->round = AST_Round;
+                               t->relevant |= 2;
+                               break;
+                       }
+               else    /* Unless */
+               {       AST_spread(a, t->to);
+                       t->round = AST_Round;
+                       t->relevant |= 2;
+               }
+       }
+}
+
+static int
+AST_notrelevant(Lextok *n)
+{      Slicer *s;
+
+       for (s = rel_vars; s; s = s->nxt)
+               if (AST_mutual(s->n, n, 1))
+                       return 0;
+       for (s = slicer; s; s = s->nxt)
+               if (AST_mutual(s->n, n, 1))
+                       return 0;
+       return 1;
+}
+
+static int
+AST_withchan(Lextok *n)
+{
+       if (!n) return 0;
+       if (Sym_typ(n) == CHAN)
+               return 1;
+       return AST_withchan(n->lft) || AST_withchan(n->rgt);
+}
+
+static int
+AST_suspect(FSM_trans *t)
+{      FSM_use *u;
+       /* check for possible overkill */
+       if (!t || !t->step || !AST_withchan(t->step->n))
+               return 0;
+       for (u = t->Val[0]; u; u = u->nxt)
+               if (AST_notrelevant(u->n))
+                       return 1;
+       return 0;
+}
+
+static void
+AST_shouldconsider(AST *a, int s)
+{      FSM_state *f;
+       FSM_trans *t;
+
+       f = fsm_tbl[s];
+       for (t = f->t; t; t = t->nxt)
+       {       if (t->step && t->step->n)
+                       switch (t->step->n->ntyp) {
+                       case IF:
+                       case DO:
+                       case ATOMIC:
+                       case NON_ATOMIC:
+                       case D_STEP:
+                               AST_shouldconsider(a, t->to);
+                               break;
+                       default:
+                               AST_track(t->step->n, 0);
+/*
+       AST_track is called here for a blockable stmnt from which
+       a relevant stmnmt was shown to be reachable
+       for a condition this makes all USEs relevant
+       but for a channel operation it only makes the executability
+       relevant -- in those cases, parameters that aren't already
+       relevant may be replaceable with arbitrary tokens
+ */
+                               if (AST_suspect(t))
+                               {       printf("spin: possibly redundant parameters in: ");
+                                       comment(stdout, t->step->n, 0);
+                                       printf("\n");
+                               }
+                               break;
+                       }
+               else    /* an Unless */
+                       AST_shouldconsider(a, t->to);
+       }
+}
+
+static int
+FSM_critical(AST *a, int s)
+{      FSM_state *f;
+       FSM_trans *t;
+
+       /* is a 1-relevant stmnt reachable from this state? */
+
+       f = fsm_tbl[s];
+       if (f->seen)
+               goto done;
+       f->seen = 1;
+       f->cr   = 0;
+       for (t = f->t; t; t = t->nxt)
+               if ((t->relevant&1)
+               ||  FSM_critical(a, t->to))
+               {       f->cr = 1;
+
+                       if (verbose&32)
+                       {       printf("\t\t\t\tcritical(%d) ", t->relevant);
+                               comment(stdout, t->step->n, 0);
+                               printf("\n");
+                       }
+                       break;
+               }
+#if 0
+       else {
+               if (verbose&32)
+               { printf("\t\t\t\tnot-crit ");
+                 comment(stdout, t->step->n, 0);
+                 printf("\n");
+               }
+       }
+#endif
+done:
+       return f->cr;
+}
+
+static void
+AST_ctrl(AST *a)
+{      FSM_state *f;
+       FSM_trans *t;
+       int hit;
+
+       /* add all blockable transitions
+        * from which relevant transitions can be reached
+        */
+       if (verbose&32)
+               printf("CTL -- %s\n", a->p->n->name);
+
+       /* 1 : mark all blockable edges */
+       for (f = a->fsm; f; f = f->nxt)
+       {       if (!(f->scratch&2))            /* not part of irrelevant subgraph */
+               for (t = f->t; t; t = t->nxt)
+               {       if (t->step && t->step->n)
+                       switch (t->step->n->ntyp) {
+                       case 'r':
+                       case 's':
+                       case 'c':
+                       case ELSE:
+                               t->round = AST_Round;
+                               t->relevant |= 2;       /* mark for next phases */
+                               if (verbose&32)
+                               {       printf("\tpremark ");
+                                       comment(stdout, t->step->n, 0);
+                                       printf("\n");
+                               }
+                               break;
+                       default:
+                               break;
+       }       }       }
+
+       /* 2: keep only 2-marked stmnts from which 1-marked stmnts can be reached */
+       for (f = a->fsm; f; f = f->nxt)
+       {       fsm_tbl[f->from] = f;
+               f->seen = 0;    /* used in dfs from FSM_critical */
+       }
+       for (f = a->fsm; f; f = f->nxt)
+       {       if (!FSM_critical(a, f->from))
+               for (t = f->t; t; t = t->nxt)
+                       if (t->relevant&2)
+                       {       t->relevant &= ~2;      /* clear mark */
+                               if (verbose&32)
+                               {       printf("\t\tnomark ");
+                                       if (t->step && t->step->n)
+                                               comment(stdout, t->step->n, 0);
+                                       printf("\n");
+       }               }       }
+
+       /* 3 : lift marks across IF/DO etc. */
+       for (f = a->fsm; f; f = f->nxt)
+       {       hit = 0;
+               for (t = f->t; t; t = t->nxt)
+               {       if (t->step && t->step->n)
+                       switch (t->step->n->ntyp) {
+                       case IF:
+                       case DO:
+                       case ATOMIC:
+                       case NON_ATOMIC:
+                       case D_STEP:
+                               if (AST_blockable(a, t->to))
+                                       hit = 1;
+                               break;
+                       default:
+                               break;
+                       }
+                       else if (AST_blockable(a, t->to))       /* Unless */
+                               hit = 1;
+
+                       if (hit) break;
+               }
+               if (hit)        /* at least one outgoing trans can block */
+               for (t = f->t; t; t = t->nxt)
+               {       t->round = AST_Round;
+                       t->relevant |= 2;       /* lift */
+                       if (verbose&32)
+                       {       printf("\t\t\tliftmark ");
+                               if (t->step && t->step->n)
+                                       comment(stdout, t->step->n, 0);
+                               printf("\n");
+                       }
+                       AST_spread(a, t->to);   /* and spread to all guards */
+       }       }
+
+       /* 4: nodes with 2-marked out-edges contribute new slice criteria */
+       for (f = a->fsm; f; f = f->nxt)
+       for (t = f->t; t; t = t->nxt)
+               if (t->relevant&2)
+               {       AST_shouldconsider(a, f->from);
+                       break;  /* inner loop */
+               }
+}
+
+static void
+AST_control_dep(void)
+{      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);
+}
+
+static void
+AST_prelabel(void)
+{      AST *a;
+       FSM_state *f;
+       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)
+               for (f = a->fsm; f; f = f->nxt)
+               for (t = f->t; t; t = t->nxt)
+               {       if (t->step
+                       &&  t->step->n
+                       &&  t->step->n->ntyp == ASSERT
+                       )
+                       {       t->relevant |= 1;
+       }       }       }
+}
+
+static void
+AST_criteria(void)
+{      /*
+        * remote labels are handled separately -- by making
+        * sure they are not pruned away during optimization
+        */
+       AST_Changes = 1;        /* to get started */
+       for (AST_Round = 1; slicer && AST_Changes; AST_Round++)
+       {       AST_Changes = 0;
+               AST_data_dep();
+               AST_preserve();         /* moves processed vars from slicer to rel_vars */
+               AST_dominant();         /* mark data-irrelevant subgraphs */
+               AST_control_dep();      /* can add data deps, which add control deps */
+
+               if (verbose&32)
+                       printf("\n\nROUND %d -- changes %d\n",
+                               AST_Round, AST_Changes);
+       }
+}
+
+static void
+AST_alias_analysis(void)               /* aliasing of promela channels */
+{      AST *a;
+
+       for (a = ast; a; a = a->nxt)
+               AST_sends(a);           /* collect chan-names that are send across chans */
+
+       for (a = ast; a; a = a->nxt)
+               AST_para(a->p);         /* aliasing of chans thru proctype parameters */
+
+       for (a = ast; a; a = a->nxt)
+               AST_other(a);           /* chan params in asgns and recvs */
+
+       AST_trans();                    /* transitive closure of alias table */
+
+       if (verbose&32)
+               AST_aliases();          /* show channel aliasing info */
+}
+
+void
+AST_slice(void)
+{      AST *a;
+       int spurious = 0;
+
+       if (!slicer)
+       {       non_fatal("no slice criteria (or no claim) specified",
+               (char *) 0);
+               spurious = 1;
+       }
+       AST_dorelevant();               /* mark procs refered to in remote refs */
+
+       for (a = ast; a; a = a->nxt)
+               AST_def_use(a);         /* compute standard def/use information */
+
+       AST_hidden();                   /* parameter passing and local var inits */
+
+       AST_alias_analysis();           /* channel alias analysis */
+
+       AST_prelabel();                 /* mark all 'assert(...)' stmnts as relevant */
+       AST_criteria();                 /* process the slice criteria from
+                                        * asserts and from the never claim
+                                        */
+       if (!spurious || (verbose&32))
+       {       spurious = 1;
+               for (a = ast; a; a = a->nxt)
+               {       AST_dump(a);            /* marked up result */
+                       if (a->relevant&2)      /* it printed something */
+                               spurious = 0;
+               }
+               if (!AST_dump_rel()             /* relevant variables */
+               &&  spurious)
+                       printf("spin: no redundancies found (for given property)\n");
+       }
+       AST_suggestions();
+
+       if (verbose&32)
+               show_expl();
+}
+
+void
+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)
+       {       n_ast = (AST *) emalloc(sizeof(AST));
+               n_ast->p = p;
+               n_ast->i_st = start_state;
+               n_ast->relevant = 0;
+               n_ast->fsm = fsm;
+               n_ast->nxt = ast;
+               ast = n_ast;
+       }
+       fsm = (FSM_state *) 0;  /* hide it from FSM_DEL */
+}
+
+static void
+AST_add_explicit(Lextok *d, Lextok *u)
+{      FSM_trans *e = (FSM_trans *) emalloc(sizeof(FSM_trans));
+
+       e->to = 0;                      /* or start_state ? */
+       e->relevant = 0;                /* to be determined */
+       e->step = (Element *) 0;        /* left blank */
+       e->Val[0] = e->Val[1] = (FSM_use *) 0;
+
+       cur_t = e;
+
+       def_use(u, USE);
+       def_use(d, DEF);
+
+       cur_t = (FSM_trans *) 0;
+
+       e->nxt = explicit;
+       explicit = e;
+}
+
+static void
+AST_fp1(char *s, Lextok *t, Lextok *f, int parno)
+{      Lextok *v;
+       int cnt;
+
+       if (!t) return;
+
+       if (t->ntyp == RUN)
+       {       if (strcmp(t->sym->name, s) == 0)
+               for (v = t->lft, cnt = 1; v; v = v->rgt, cnt++)
+                       if (cnt == parno)
+                       {       AST_add_explicit(f, v->lft);
+                               break;
+                       }
+       } else
+       {       AST_fp1(s, t->lft, f, parno);
+               AST_fp1(s, t->rgt, f, parno);
+       }
+}
+
+static void
+AST_mk1(char *s, Lextok *c, int parno)
+{      AST *a;
+       FSM_state *f;
+       FSM_trans *t;
+
+       /* concoct an extra FSM_trans *t with the asgn of
+        * formal par c to matching actual pars made explicit
+        */
+
+       for (a = ast; a; a = a->nxt)            /* automata       */
+       for (f = a->fsm; f; f = f->nxt)         /* control states */
+       for (t = f->t; t; t = t->nxt)           /* transitions    */
+       {       if (t->step)
+               AST_fp1(s, t->step->n, c, parno);
+       }
+}
+
+static void
+AST_par_init(void)     /* parameter passing -- hidden assignments */
+{      AST *a;
+       Lextok *f, *t, *c;
+       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 */
+
+               cnt = 0;
+               for (f = a->p->p; f; f = f->rgt)        /* types */
+               for (t = f->lft; t; t = t->rgt)         /* formals */
+               {       cnt++;                          /* formal par count */
+                       c = (t->ntyp != ',')? t : t->lft;       /* the formal parameter */
+                       AST_mk1(a->p->n->name, c, cnt);         /* all matching run statements */
+       }       }
+}
+
+static void
+AST_var_init(void)             /* initialized vars (not chans) - hidden assignments */
+{      Ordered *walk;
+       Lextok *x;
+       Symbol  *sp;
+       AST *a;
+
+       for (walk = all_names; walk; walk = walk->next) 
+       {       sp = walk->entry;
+               if (sp
+               &&  !sp->context                /* globals */
+               &&  sp->type != PROCTYPE
+               &&  sp->ini
+               && (sp->type != MTYPE || sp->ini->ntyp != CONST) /* not mtype defs */
+               &&  sp->ini->ntyp != CHAN)
+               {       x = nn(ZN, TYPE, ZN, ZN);
+                       x->sym = sp;
+                       AST_add_explicit(x, sp->ini);
+       }       }
+
+       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 */
+               for (walk = all_names; walk; walk = walk->next) 
+               {       sp = walk->entry;
+                       if (sp
+                       &&  sp->context
+                       &&  strcmp(sp->context->name, a->p->n->name) == 0
+                       &&  sp->Nid >= 0        /* not a param */
+                       &&  sp->type != LABEL
+                       &&  sp->ini
+                       &&  sp->ini->ntyp != CHAN)
+                       {       x = nn(ZN, TYPE, ZN, ZN);
+                               x->sym = sp;
+                               AST_add_explicit(x, sp->ini);
+       }       }       }
+}
+
+static void
+show_expl(void)
+{      FSM_trans *t, *T;
+       FSM_use *u;
+
+       printf("\nExplicit List:\n");
+       for (T = expl_par; T; T = (T == expl_par)?expl_var: (FSM_trans *) 0)
+       {       for (t = T; t; t = t->nxt)
+               {       if (!t->Val[0]) continue;
+                       printf("%s", t->relevant?"*":" ");
+                       printf("%3d", t->round);
+                       for (u = t->Val[0]; u; u = u->nxt)
+                       {       printf("\t<");
+                               AST_var(u->n, u->n->sym, 1);
+                               printf(":%d>, ", u->special);
+                       }
+                       printf("\n");
+               }
+               printf("==\n");
+       }
+       printf("End\n");
+}
+
+static void
+AST_hidden(void)                       /* reveal all hidden assignments */
+{
+       AST_par_init();
+       expl_par = explicit;
+       explicit = (FSM_trans *) 0;
+
+       AST_var_init();
+       expl_var = explicit;
+       explicit = (FSM_trans *) 0;
+}
+
+#define BPW    (8*sizeof(ulong))                       /* bits per word */
+
+static int
+bad_scratch(FSM_state *f, int upto)
+{      FSM_trans *t;
+#if 0
+       1. all internal branch-points have else-s
+       2. all non-branchpoints have non-blocking out-edge
+       3. all internal edges are non-relevant
+       subgraphs like this need NOT contribute control-dependencies
+#endif
+
+       if (!f->seen
+       ||  (f->scratch&4))
+               return 0;
+
+       if (f->scratch&8)
+               return 1;
+
+       f->scratch |= 4;
+
+       if (verbose&32) printf("X[%d:%d:%d] ", f->from, upto, f->scratch);
+
+       if (f->scratch&1)
+       {       if (verbose&32)
+                       printf("\tbad scratch: %d\n", f->from);
+bad:           f->scratch &= ~4;
+       /*      f->scratch |=  8;        wrong */
+               return 1;
+       }
+
+       if (f->from != upto)
+       for (t = f->t; t; t = t->nxt)
+               if (bad_scratch(fsm_tbl[t->to], upto))
+                       goto bad;
+
+       return 0;
+}
+
+static void
+mark_subgraph(FSM_state *f, int upto)
+{      FSM_trans *t;
+
+       if (f->from == upto
+       ||  !f->seen
+       ||  (f->scratch&2))
+               return;
+
+       f->scratch |= 2;
+
+       for (t = f->t; t; t = t->nxt)
+               mark_subgraph(fsm_tbl[t->to], upto);
+}
+
+static void
+AST_pair(AST *a, FSM_state *h, int y)
+{      Pair *p;
+
+       for (p = a->pairs; p; p = p->nxt)
+               if (p->h == h
+               &&  p->b == y)
+                       return;
+
+       p = (Pair *) emalloc(sizeof(Pair));
+       p->h = h;
+       p->b = y;
+       p->nxt = a->pairs;
+       a->pairs = p;
+}
+
+static void
+AST_checkpairs(AST *a)
+{      Pair *p;
+
+       for (p = a->pairs; p; p = p->nxt)
+       {       if (verbose&32)
+                       printf("        inspect pair %d %d\n", p->b, p->h->from);
+               if (!bad_scratch(p->h, p->b))   /* subgraph is clean */
+               {       if (verbose&32)
+                               printf("subgraph: %d .. %d\n", p->b, p->h->from);
+                       mark_subgraph(p->h, p->b);
+               }
+       }
+}
+
+static void
+subgraph(AST *a, FSM_state *f, int out)
+{      FSM_state *h;
+       int i, j;
+       ulong *g;
+#if 0
+       reverse dominance suggests that this is a possible
+       entry and exit node for a proper subgraph
+#endif
+       h = fsm_tbl[out];
+
+       i = f->from / BPW;
+       j = f->from % BPW;
+       g = h->mod;
+
+       if (verbose&32)
+               printf("possible pair %d %d -- %d\n",
+                       f->from, h->from, (g[i]&(1<<j))?1:0);
+       
+       if (g[i]&(1<<j))                /* also a forward dominance pair */
+               AST_pair(a, h, f->from);        /* record this pair */
+}
+
+static void
+act_dom(AST *a)
+{      FSM_state *f;
+       FSM_trans *t;
+       int i, j, cnt;
+
+       for (f = a->fsm; f; f = f->nxt)
+       {       if (!f->seen) continue;
+#if 0
+               f->from is the exit-node of a proper subgraph, with
+               the dominator its entry-node, if:
+               a. this node has more than 1 reachable predecessor
+               b. the dominator has more than 1 reachable successor
+                  (need reachability - in case of reverse dominance)
+               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. */
+
+               for (cnt = 1; cnt < a->nstates; cnt++)  /* 0 is endstate */
+               {       if (cnt == f->from
+                       ||  !fsm_tbl[cnt]->seen)
+                               continue;                               /* c. */
+
+                       i = cnt / BPW;
+                       j = cnt % BPW;
+                       if (!(f->dom[i]&(1<<j)))
+                               continue;
+
+                       for (t = fsm_tbl[cnt]->t, i = 0; t; t = t->nxt)
+                               i += fsm_tbl[t->to]->seen;
+                       if (i <= 1)
+                               continue;                               /* b. */
+
+                       if (f->mod)                     /* final check in 2nd phase */
+                               subgraph(a, f, cnt);    /* possible entry-exit pair */
+               }
+       }
+}
+
+static void
+reachability(AST *a)
+{      FSM_state *f;
+
+       for (f = a->fsm; f; f = f->nxt)
+               f->seen = 0;            /* clear */
+       AST_dfs(a, a->i_st, 0);         /* mark 'seen' */
+}
+
+static int
+see_else(FSM_state *f)
+{      FSM_trans *t;
+
+       for (t = f->t; t; t = t->nxt)
+       {       if (t->step
+               &&  t->step->n)
+               switch (t->step->n->ntyp) {
+               case ELSE:
+                       return 1;
+               case IF:
+               case DO:
+               case ATOMIC:
+               case NON_ATOMIC:
+               case D_STEP:
+                       if (see_else(fsm_tbl[t->to]))
+                               return 1;
+               default:
+                       break;
+               }
+       }
+       return 0;
+}
+
+static int
+is_guard(FSM_state *f)
+{      FSM_state *g;
+       FSM_trans *t;
+
+       for (t = f->p; t; t = t->nxt)
+       {       g = fsm_tbl[t->to];
+               if (!g->seen)
+                       continue;
+
+               if (t->step
+               &&  t->step->n)
+               switch(t->step->n->ntyp) {
+               case IF:
+               case DO:
+                       return 1;
+               case ATOMIC:
+               case NON_ATOMIC:
+               case D_STEP:
+                       if (is_guard(g))
+                               return 1;
+               default:
+                       break;
+               }
+       }
+       return 0;
+}
+
+static void
+curtail(AST *a)
+{      FSM_state *f, *g;
+       FSM_trans *t;
+       int i, haselse, isrel, blocking;
+#if 0
+       mark nodes that do not satisfy these requirements:
+       1. all internal branch-points have else-s
+       2. all non-branchpoints have non-blocking out-edge
+       3. all internal edges are non-data-relevant
+#endif
+       if (verbose&32)
+               printf("Curtail %s:\n", a->p->n->name);
+
+       for (f = a->fsm; f; f = f->nxt)
+       {       if (!f->seen
+               ||  (f->scratch&(1|2)))
+                       continue;
+
+               isrel = haselse = i = blocking = 0;
+
+               for (t = f->t; t; t = t->nxt)
+               {       g = fsm_tbl[t->to];
+
+                       isrel |= (t->relevant&1);       /* data relevant */
+                       i += g->seen;
+
+                       if (t->step
+                       &&  t->step->n)
+                       {       switch (t->step->n->ntyp) {
+                               case IF:
+                               case DO:
+                                       haselse |= see_else(g);
+                                       break;
+                               case 'c':
+                               case 's':
+                               case 'r':
+                                       blocking = 1;
+                                       break;
+               }       }       }
+#if 0
+               if (verbose&32)
+                       printf("prescratch %d -- %d %d %d %d -- %d\n",
+                               f->from, i, isrel, blocking, haselse, is_guard(f));
+#endif
+               if (isrel                       /* 3. */                
+               ||  (i == 1 && blocking)        /* 2. */
+               ||  (i >  1 && !haselse))       /* 1. */
+               {       if (!is_guard(f))
+                       {       f->scratch |= 1;
+                               if (verbose&32)
+                               printf("scratch %d -- %d %d %d %d\n",
+                                       f->from, i, isrel, blocking, haselse);
+                       }
+               }
+       }
+}
+
+static void
+init_dom(AST *a)
+{      FSM_state *f;
+       int i, j, cnt;
+#if 0
+       (1)  D(s0) = {s0}
+       (2)  for s in S - {s0} do D(s) = S
+#endif
+
+       for (f = a->fsm; f; f = f->nxt)
+       {       if (!f->seen) continue;
+
+               f->dom = (ulong *)
+                       emalloc(a->nwords * sizeof(ulong));
+
+               if (f->from == a->i_st)
+               {       i = a->i_st / BPW;
+                       j = a->i_st % BPW;
+                       f->dom[i] = (1<<j);                     /* (1) */
+               } else                                          /* (2) */
+               {       for (i = 0; i < a->nwords; i++)
+                               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 */
+
+                       for (cnt = 0; cnt < a->nstates; cnt++)
+                               if (!fsm_tbl[cnt]->seen)
+                               {       i = cnt / BPW;
+                                       j = cnt % BPW;
+                                       f->dom[i] &= ~(1<<j);
+       }       }               }
+}
+
+static int
+dom_perculate(AST *a, FSM_state *f)
+{      static ulong *ndom = (ulong *) 0;
+       static int on = 0;
+       int i, j, cnt = 0;
+       FSM_state *g;
+       FSM_trans *t;
+
+       if (on < a->nwords)
+       {       on = a->nwords;
+               ndom = (ulong *)
+                       emalloc(on * sizeof(ulong));
+       }
+
+       for (i = 0; i < a->nwords; i++)
+               ndom[i] = (ulong) ~0;
+
+       for (t = f->p; t; t = t->nxt)   /* all reachable predecessors */
+       {       g = fsm_tbl[t->to];
+               if (g->seen)
+               for (i = 0; i < a->nwords; i++)
+                       ndom[i] &= g->dom[i];   /* (5b) */
+       }
+
+       i = f->from / BPW;
+       j = f->from % BPW;
+       ndom[i] |= (1<<j);                      /* (5a) */
+
+       for (i = 0; i < a->nwords; i++)
+               if (f->dom[i] != ndom[i])
+               {       cnt++;
+                       f->dom[i] = ndom[i];
+               }
+
+       return cnt;
+}
+
+static void
+dom_forward(AST *a)
+{      FSM_state *f;
+       int cnt;
+
+       init_dom(a);                                            /* (1,2) */
+       do {
+               cnt = 0;
+               for (f = a->fsm; f; f = f->nxt)
+               {       if (f->seen
+                       &&  f->from != a->i_st)                 /* (4) */
+                               cnt += dom_perculate(a, f);     /* (5) */
+               }
+       } while (cnt);                                          /* (3) */
+       dom_perculate(a, fsm_tbl[a->i_st]);
+}
+
+static void
+AST_dominant(void)
+{      FSM_state *f;
+       FSM_trans *t;
+       AST *a;
+       int oi;
+       static FSM_state no_state;
+#if 0
+       find dominators
+       Aho, Sethi, & Ullman, Compilers - principles, techniques, and tools
+       Addison-Wesley, 1986, p.671.
+
+       (1)  D(s0) = {s0}
+       (2)  for s in S - {s0} do D(s) = S
+
+       (3)  while any D(s) changes do
+       (4)    for s in S - {s0} do
+       (5)     D(s) = {s} union  with intersection of all D(p)
+               where p are the immediate predecessors of s
+
+       the purpose is to find proper subgraphs
+       (one entry node, one exit node)
+#endif
+       if (AST_Round == 1)     /* computed once, reused in every round */
+       for (a = ast; a; a = a->nxt)
+       {       a->nstates = 0;
+               for (f = a->fsm; f; f = f->nxt)
+               {       a->nstates++;                           /* count */
+                       fsm_tbl[f->from] = f;                   /* fast lookup */
+                       f->scratch = 0;                         /* clear scratch marks */
+               }
+               for (oi = 0; oi < a->nstates; oi++)
+                       if (!fsm_tbl[oi])
+                               fsm_tbl[oi] = &no_state;
+
+               a->nwords = (a->nstates + BPW - 1) / BPW;       /* round up */
+
+               if (verbose&32)
+               {       printf("%s (%d): ", a->p->n->name, a->i_st);
+                       printf("states=%d (max %d), words = %d, bpw %d, overflow %d\n",
+                               a->nstates, o_max, a->nwords,
+                               (int) BPW, (int) (a->nstates % BPW));
+               }
+
+               reachability(a);
+               dom_forward(a);         /* forward dominance relation */
+
+               curtail(a);             /* mark ineligible edges */
+               for (f = a->fsm; f; f = f->nxt)
+               {       t = f->p;
+                       f->p = f->t;
+                       f->t = t;       /* invert edges */
+
+                       f->mod = f->dom;
+                       f->dom = (ulong *) 0;
+               }
+               oi = a->i_st;
+               if (fsm_tbl[0]->seen)   /* end-state reachable - else leave it */
+                       a->i_st = 0;    /* becomes initial state */
+       
+               dom_forward(a);         /* reverse dominance -- don't redo reachability! */
+               act_dom(a);             /* mark proper subgraphs, if any */
+               AST_checkpairs(a);      /* selectively place 2 scratch-marks */
+
+               for (f = a->fsm; f; f = f->nxt)
+               {       t = f->p;
+                       f->p = f->t;
+                       f->t = t;       /* restore */
+               }
+               a->i_st = oi;   /* restore */
+       } else
+               for (a = ast; a; a = a->nxt)
+               {       for (f = a->fsm; f; f = f->nxt)
+                       {       fsm_tbl[f->from] = f;
+                               f->scratch &= 1; /* preserve 1-marks */
+                       }
+                       for (oi = 0; oi < a->nstates; oi++)
+                               if (!fsm_tbl[oi])
+                                       fsm_tbl[oi] = &no_state;
+
+                       curtail(a);             /* mark ineligible edges */
+
+                       for (f = a->fsm; f; f = f->nxt)
+                       {       t = f->p;
+                               f->p = f->t;
+                               f->t = t;       /* invert edges */
+                       }
+       
+                       AST_checkpairs(a);      /* recompute 2-marks */
+
+                       for (f = a->fsm; f; f = f->nxt)
+                       {       t = f->p;
+                               f->p = f->t;
+                               f->t = t;       /* restore */
+               }       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/pangen6.h b/trunk/verif/Spin/Src5.1.6/pangen6.h
new file mode 100755 (executable)
index 0000000..431349b
--- /dev/null
@@ -0,0 +1,2841 @@
+/***** spin: pangen6.h *****/
+
+/* Copyright (c) 2006-2007 by the California Institute of Technology.     */
+/* ALL RIGHTS RESERVED. United States Government Sponsorship acknowledged */
+/* Supporting routines for a multi-core extension of the SPIN software    */
+/* Developed as part of Reliable Software Engineering Project ESAS/6G     */
+/* Like all SPIN Software 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.  */
+/* Any commercial use must be negotiated with the Office of Technology    */
+/* Transfer at the California Institute of Technology.                    */
+/* Software written by Gerard J. Holzmann.  For tool documentation see:   */
+/*             http://spinroot.com/                                       */
+/* Bug-reports and/or questions can be send to: bugs@spinroot.com         */
+
+static 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 usefule -- 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];",
+       "       volatile char   m_Mask    [(VMAX + 7)/8];",
+       "       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 *);",
+       "#if 0",
+       "void enter_critical(int);",
+       "void leave_critical(int);",
+       "#endif",
+       "",
+       "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, (int) (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\", 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, *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 */",
+       "               {",
+       "#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\",",
+       "                                       worker_pids[i], (dwExitCode == STILL_ACTIVE));",
+       "#else",
+       "                               sprintf(b, \"kill -%%d %%d\", SIGKILL, worker_pids[i]);",
+       "                               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 */
+       "               {       sprintf(b, \"kill -%%d %%d\", SIGINT, worker_pids[0]);",
+       "                       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>%%d)\\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;",
+       "",
+       "struct 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 %%d)\\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;",
+       "               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., 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\",",
+       "                               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 = (struct 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 = (struct 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 */
+       "}",
+       "",
+       "       /* 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;",
+       "               }",
+       "       #else",
+       "               #error missing definition of test and set operation for this platform",
+       "       #endif",
+       "",
+       "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 %%d 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 BFS is not supported with multi-core",
+       "#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",
+       "",
+       "struct 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 (struct 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 (struct H_el *) rval;",
+       "#else",
+       "       return (struct 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 struct 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);",
+       "               for (i = j = 0; i < VMAX; i++, j = (j+1)%%8)",
+       "               {       Mask[i] = (f->m_Mask[i/8] & (1<<j)) ? 1 : 0;",
+       "               }",
+       "               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(\" line %%3d \\\"%%s\\\" \",",
+       "                                               src_all[j].src[z->_p], PanSource);",
+       "                                       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\", 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);",
+       "       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);",
+       "       }       }",
+       "",
+       "       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);",
+       "       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);",
+       "       }       }",
+       "",
+       "       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 = (struct 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 = (struct 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 BFS is not supported in multi-core mode",
+       "#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,
+};
diff --git a/trunk/verif/Spin/Src5.1.6/pc_zpp.c b/trunk/verif/Spin/Src5.1.6/pc_zpp.c
new file mode 100755 (executable)
index 0000000..5cfc61a
--- /dev/null
@@ -0,0 +1,408 @@
+/***** spin: pc_zpp.c *****/
+
+/* 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            */
+
+/* pc_zpp.c is only used in the PC version of Spin                        */
+/* it is included to avoid too great a reliance on an external cpp        */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef PC
+enum cstate { PLAIN, IN_STRING, IN_QUOTE, S_COMM, COMMENT, E_COMM };
+
+#define MAXNEST        32
+#define MAXDEF 128
+#define MAXLINE        2048
+#define GENEROUS 8192
+
+#define debug(x,y)     if (verbose) printf(x,y)
+
+static FILE *outpp /* = stdout */;
+
+static int if_truth[MAXNEST];
+static int printing[MAXNEST];
+static int if_depth, nr_defs, verbose = 0;
+static enum cstate state = PLAIN;
+static char Out1[GENEROUS], Out2[GENEROUS];
+
+static struct Defines {
+       int exists;
+       char *src, *trg;
+} d[MAXDEF];
+
+static int process(char *, int, char *);
+static int zpp_do(char *);
+
+extern char *emalloc(size_t);  /* main.c */
+
+static int
+do_define(char *p)
+{      char *q, *r, *s;
+
+       for (q = p+strlen(p)-1; q > p; q--)
+               if (*q == '\n' || *q == '\t' || *q == ' ')
+                       *q = '\0';
+               else
+                       break;
+
+       q = p + strspn(p, " \t");
+       if (!(r = strchr(q, '\t')))
+               r = strchr(q, ' ');
+       if (!r) { s = ""; goto adddef; }
+       s = r + strspn(r, " \t");
+       *r = '\0';
+       if (strchr(q, '('))
+       {       debug("zpp: #define with arguments %s\n", q);
+               return 0;
+       }
+       for (r = q+strlen(q)-1; r > q; r--)
+               if (*r == ' ' || *r == '\t')
+                       *r = '\0';
+               else
+                       break;
+       if (nr_defs >= MAXDEF)
+       {       debug("zpp: too many #defines (max %d)\n", nr_defs);
+               return 0;
+       }
+       if (strcmp(q, s) != 0)
+       {       int j;
+adddef:                for (j = 0; j < nr_defs; j++)
+                       if (!strcmp(d[j].src, q))
+                               d[j].exists = 0;
+               d[nr_defs].src = emalloc(strlen(q)+1);
+               d[nr_defs].trg = emalloc(strlen(s)+1);
+               strcpy(d[nr_defs].src, q);
+               strcpy(d[nr_defs].trg, s);
+               d[nr_defs++].exists = 1;
+       }
+       return 1;
+}
+
+static int
+isvalid(int c)
+{
+       return (isalnum(c) || c == '_');
+}
+
+static char *
+apply(char *p0)
+{      char *out, *in1, *in2, *startat;
+       int i, j;
+
+       startat = in1 = Out2; strcpy(Out2, p0);
+       out = Out1; *out = '\0';
+
+       for (i = nr_defs-1; i >= 0; i--)
+       {       if (!d[i].exists) continue;
+               j = (int) strlen(d[i].src);
+more:          in2 = strstr(startat, d[i].src);
+               if (!in2)       /* no more matches */
+               {       startat = in1;
+                       continue;
+               }
+               if ((in2 == in1 || !isvalid(*(in2-1)))
+               &&  (in2+j == '\0' || !isvalid(*(in2+j))))
+               {       *in2 = '\0';
+
+                       if (strlen(in1)+strlen(d[i].trg)+strlen(in2+j) >= GENEROUS)
+                       {
+                               printf("spin: macro expansion overflow %s -> %s ?\n",
+                                       d[i].src, d[i].trg);
+                               return in1;
+                       }
+                       strcat(out, in1);
+                       strcat(out, d[i].trg);
+                       strcat(out, in2+j);
+                       if (in1 == Out2)
+                       {       startat = in1 = Out1;
+                               out = Out2;
+                       } else
+                       {       startat = in1 = Out2;
+                               out = Out1;
+                       }
+                       *out = '\0';
+               } else
+               {       startat = in2+1;        /* +1 not +j.. */
+               }
+               goto more; /* recursive defines */
+       }
+       return in1;
+}
+
+static char *
+do_common(char *p)
+{      char *q, *s;
+
+       q = p + strspn(p, " \t");
+       for (s = (q + strlen(q) - 1); s > q; s--)
+               if (*s == ' ' || *s == '\t' || *s == '\n')
+                       *s = '\0';
+               else
+                       break;
+       return q;
+}
+
+static int
+do_undefine(char *p)
+{      int i; char *q = do_common(p);
+
+       for (i = 0; i < nr_defs; i++)
+               if (!strcmp(d[i].src, q))
+                       d[i].exists = 0;
+       return 1;
+}
+
+static char *
+check_ifdef(char *p)
+{      int i; char *q = do_common(p);
+
+       for (i = 0; i < nr_defs; i++)
+               if (d[i].exists
+               &&  !strcmp(d[i].src, q))
+                       return d[i].trg;
+       return (char *) 0;
+}
+
+static int
+do_ifdef(char *p)
+{
+       if (++if_depth >= MAXNEST)
+       {       debug("zpp: too deeply nested (max %d)\n", MAXNEST);
+               return 0;
+       }
+       if_truth[if_depth] = (check_ifdef(p) != (char *)0);
+       printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
+
+       return 1;
+}
+
+static int
+do_ifndef(char *p)
+{
+       if (++if_depth >= MAXNEST)
+       {       debug("zpp: too deeply nested (max %d)\n", MAXNEST);
+               return 0;
+       }
+       if_truth[if_depth] = (check_ifdef(p) == (char *)0);
+       printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
+
+       return 1;
+}
+
+static int
+is_simple(char *q)
+{
+       if (!q) return 0;
+       if (strcmp(q, "0") == 0)
+               if_truth[if_depth] = 0;
+       else if (strcmp(q, "1") == 0)
+               if_truth[if_depth] = 1;
+       else
+               return 0;
+       return 1;
+}
+
+static int
+do_if(char *p)
+{      char *q = do_common(p);
+       if (++if_depth >= MAXNEST)
+       {       debug("zpp: too deeply nested (max %d)\n", MAXNEST);
+               return 0;
+       }
+       if (!is_simple(q)
+       &&  !is_simple(check_ifdef(q)))
+       {       debug("zpp: cannot handle #if %s\n", q);
+               return 0;
+       }
+       printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
+
+       return 1;
+}
+
+static int
+do_else(char *unused)
+{
+       if_truth[if_depth] = 1-if_truth[if_depth];
+       printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
+
+       return 1;
+}
+
+static int
+do_endif(char *p)
+{
+       if (--if_depth < 0)
+       {       debug("zpp: unbalanced #endif %s\n", p);
+               return 0;
+       }
+       return 1;
+}
+
+static int
+do_include(char *p)
+{      char *r, *q;
+
+       q = strchr(p, '<');
+       r = strrchr(p, '>');
+       if (!q || !r)
+       {       q = strchr (p, '\"');
+               r = strrchr(p, '\"');
+               if (!q || !r || q == r)
+               {       debug("zpp: malformed #include %s", p);
+                       return 0;
+       }       }
+       *r = '\0';
+       return zpp_do(++q);
+}
+
+static int
+in_comment(char *p)
+{      char *q = p;
+
+       for (q = p; *q != '\n' && *q != '\0'; q++)
+               switch (state) {
+               case PLAIN:
+                       switch (*q) {
+                       case  '"': state = IN_STRING; break;
+                       case '\'': state = IN_QUOTE; break;
+                       case  '/': state = S_COMM; break;
+                       case '\\': q++; break;
+                       }
+                       break;
+               case IN_STRING:
+                       if (*q == '"') state = PLAIN;
+                       else if (*q == '\\') q++;
+                       break;
+               case IN_QUOTE:
+                       if (*q == '\'') state = PLAIN;
+                       else if (*q == '\\') q++;
+                       break;
+               case S_COMM:
+                       if (*q == '*')
+                       {       *(q-1) = *q = ' ';
+                               state = COMMENT;
+                       } else if (*q != '/')
+                               state = PLAIN;
+                       break;
+               case COMMENT:
+                       state = (*q == '*') ? E_COMM: COMMENT;
+                       *q = ' ';
+                       break;
+               case E_COMM:
+                       if (*q == '/')
+                               state = PLAIN;
+                       else if (*q != '*')
+                               state = COMMENT;
+                       *q = ' ';
+                       break;
+               }
+       if (state == S_COMM) state = PLAIN;
+       else if (state == E_COMM) state = COMMENT;
+       return (state == COMMENT);
+}
+
+static int
+zpp_do(char *fnm)
+{      char buf[2048], buf2[MAXLINE], *p; int n, on;
+       FILE *inp; int lno = 0, nw_lno = 0;
+
+       if ((inp = fopen(fnm, "r")) == NULL)
+       {       fprintf(stdout, "spin: error, '%s': No such file\n", fnm);
+               return 0;       /* 4.1.2 was stderr */
+       }
+       printing[0] = if_truth[0] = 1;
+       fprintf(outpp, "#line %d \"%s\"\n", lno+1, fnm);
+       while (fgets(buf, MAXLINE, inp))
+       {       lno++; n = (int) strlen(buf);
+               on = 0; nw_lno = 0;
+               while (n > 2 && buf[n-2] == '\\')
+               {       buf[n-2] = '\0';
+feedme:                        if (!fgets(buf2, MAXLINE, inp))
+                       {       debug("zpp: unexpected EOF ln %d\n", lno);
+                               return 0;       /* switch to cpp */
+                       }
+                       lno++;
+                       if (n + (int) strlen(buf2) >= 2048)
+                       {       debug("zpp: line %d too long\n", lno);
+                               return 0;
+                       }
+                       strcat(buf, buf2);
+                       n = (int) strlen(buf);
+               }
+               if (in_comment(&buf[on]))
+               {       buf[n-1] = '\0'; /* eat newline */
+                       on = n-1; nw_lno = 1;
+                       goto feedme;
+               }
+               p = buf + strspn(buf, " \t");
+               if (nw_lno && *p != '#')
+                       fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
+               if (*p == '#')
+               {       if (!process(p+1, lno+1, fnm))
+                               return 0;
+               } else if (printing[if_depth])
+                       fprintf(outpp, "%s", apply(buf));
+       }
+       fclose(inp);
+       return 1;
+}
+
+int
+try_zpp(char *fnm, char *onm)
+{      int r;
+       if ((outpp = fopen(onm, "w")) == NULL)
+               return 0;
+       r = zpp_do(fnm);
+       fclose(outpp);
+       return r;       /* 1 = ok; 0 = use cpp */
+}
+
+static struct Directives {
+       int len;
+       char *directive;
+       int (*handler)(char *);
+       int interp;
+} s[] = {
+       { 6, "define",   do_define,     1 },
+       { 4, "else",     do_else,       0 },
+       { 5, "endif",    do_endif,      0 },
+       { 5, "ifdef",    do_ifdef,      0 },
+       { 6, "ifndef",   do_ifndef,     0 },
+       { 2, "if",       do_if,         0 },
+       { 7, "include",  do_include,    1 },
+       { 8, "undefine", do_undefine,   1 },
+};
+
+static int
+process(char *q, int lno, char *fnm)
+{      char *p; int i, r;
+
+       for (p = q; *p; p++)
+               if (*p != ' ' && *p != '\t')
+                       break;
+       for (i = 0; i < (int) (sizeof(s)/sizeof(struct Directives)); i++)
+               if (!strncmp(s[i].directive, p, s[i].len))
+               {       if (s[i].interp
+                       &&  !printing[if_depth])
+                               return 1;
+                       fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
+                       r = s[i].handler(p +  s[i].len);
+                       if (i == 6)     /* include */
+                               fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
+                       return r;
+               }
+       
+       debug("zpp: unrecognized directive: %s", p);
+       return 0;
+}
+#endif
diff --git a/trunk/verif/Spin/Src5.1.6/ps_msc.c b/trunk/verif/Spin/Src5.1.6/ps_msc.c
new file mode 100755 (executable)
index 0000000..3116557
--- /dev/null
@@ -0,0 +1,445 @@
+/***** spin: ps_msc.c *****/
+
+/* 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            */
+
+/* The Postscript generation code below was written by Gerard J. Holzmann */
+/* in June 1997. Parts of the prolog template are based on similar boiler */
+/* plate in the Tcl/Tk distribution. This code is used to support Spin's  */
+/* option -M for generating a Postscript file from a simulation run.      */
+
+#include "spin.h"
+#include "version.h"
+
+/* extern void free(void *); */
+
+static char *PsPre[] = {
+       "%%%%Pages: (atend)",
+       "%%%%PageOrder: Ascend",
+       "%%%%DocumentData: Clean7Bit",
+       "%%%%Orientation: Portrait",
+       "%%%%DocumentNeededResources: font Courier-Bold",
+       "%%%%EndComments",
+       "",
+       "%%%%BeginProlog",
+       "50 dict begin",
+       "",
+       "/baseline 0 def",
+       "/height 0 def",
+       "/justify 0 def",
+       "/lineLength 0 def",
+       "/spacing 0 def",
+       "/stipple 0 def",
+       "/strings 0 def",
+       "/xoffset 0 def",
+       "/yoffset 0 def",
+       "",
+       "/ISOEncode {",
+       "    dup length dict begin",
+       "       {1 index /FID ne {def} {pop pop} ifelse} forall",
+       "       /Encoding ISOLatin1Encoding def",
+       "       currentdict",
+       "    end",
+       "    /Temporary exch definefont",
+       "} bind def",
+       "",
+       "/AdjustColor {",
+       "    CL 2 lt {",
+       "       currentgray",
+       "       CL 0 eq {",
+       "           .5 lt {0} {1} ifelse",
+       "       } if",
+       "       setgray",
+       "    } if",
+       "} bind def",
+       "",
+       "/DrawText {",
+       "    /stipple exch def",
+       "    /justify exch def",
+       "    /yoffset exch def",
+       "    /xoffset exch def",
+       "    /spacing exch def",
+       "    /strings exch def",
+       "    /lineLength 0 def",
+       "    strings {",
+       "       stringwidth pop",
+       "       dup lineLength gt {/lineLength exch def} {pop} ifelse",
+       "       newpath",
+       "    } forall",
+       "    0 0 moveto (TXygqPZ) false charpath",
+       "    pathbbox dup /baseline exch def",
+       "    exch pop exch sub /height exch def pop",
+       "    newpath",
+       "    translate",
+       "    lineLength xoffset mul",
+       "    strings length 1 sub spacing mul height add yoffset mul translate",
+       "    justify lineLength mul baseline neg translate",
+       "    strings {",
+       "       dup stringwidth pop",
+       "       justify neg mul 0 moveto",
+       "       stipple {",
+       "           gsave",
+       "           /char (X) def",
+       "           {",
+       "               char 0 3 -1 roll put",
+       "               currentpoint",
+       "               gsave",
+       "               char true charpath clip StippleText",
+       "               grestore",
+       "               char stringwidth translate",
+       "               moveto",
+       "           } forall",
+       "           grestore",
+       "       } {show} ifelse",
+       "       0 spacing neg translate",
+       "    } forall",
+       "} bind def",
+       "%%%%EndProlog",
+       "%%%%BeginSetup",
+       "/CL 2 def",
+       "%%%%IncludeResource: font Courier-Bold",
+       "%%%%EndSetup",
+       0,
+};
+
+static int MH  = 600;  /* page height - can be scaled */
+static int oMH = 600;  /* page height - not scaled */
+#define MW     500     /* page width */
+#define LH     100     /* bottom margin */
+#define RH     100     /* right margin */
+#define WW      50     /* distance between process lines */
+#define HH       8     /* vertical distance between steps */
+#define PH      14     /* height of process-tag headers */
+
+static FILE    *pfd;
+static char    **I;            /* initial procs */
+static int     *D,*R;          /* maps between depth and ldepth */
+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 char    *ProcLine;      /* active processes */
+static int     pspno = 0;      /* postscript page */
+static int     ldepth = 1;
+static int     maxx, TotSteps = 2*4096; /* max nr of steps, about 40 pages */
+static float   Scaler = (float) 1.0;
+
+extern int     ntrail, s_trail, pno, depth;
+extern Symbol  *oFname;
+extern void    exit(int);
+void putpages(void);
+void spitbox(int, int, int, char *);
+
+void
+putlegend(void)
+{
+       fprintf(pfd, "gsave\n");
+       fprintf(pfd, "/Courier-Bold findfont 8 scalefont ");
+       fprintf(pfd, "ISOEncode setfont\n");
+       fprintf(pfd, "0.000 0.000 0.000 setrgbcolor AdjustColor\n");
+       fprintf(pfd, "%d %d [\n", MW/2, LH+oMH+ 5*HH);
+       fprintf(pfd, "    (%s -- %s -- MSC -- %d)\n] 10 -0.5 0.5 0 ",
+               SpinVersion, oFname?oFname->name:"", pspno);
+       fprintf(pfd, "false DrawText\ngrestore\n");
+}
+
+void
+startpage(void)
+{      int i;
+
+       pspno++;
+       fprintf(pfd, "%%%%Page: %d %d\n", pspno, pspno);
+       putlegend();
+
+       for (i = TotSteps-1; i >= 0; i--)
+       {       if (!I[i]) continue;
+               spitbox(i, RH, -PH, I[i]);
+       }
+
+       fprintf(pfd, "save\n");
+       fprintf(pfd, "10 %d moveto\n", LH+oMH+5);
+       fprintf(pfd, "%d %d lineto\n", RH+MW, LH+oMH+5);
+       fprintf(pfd, "%d %d lineto\n", RH+MW, LH);
+       fprintf(pfd, "10 %d lineto\n", LH);
+       fprintf(pfd, "closepath clip newpath\n");
+       fprintf(pfd, "%f %f translate\n",
+               (float) RH, (float) LH);
+       memset(ProcLine, 0, 256*sizeof(char));
+       if (Scaler != 1.0)
+               fprintf(pfd, "%f %f scale\n", Scaler, Scaler);
+}
+
+void
+putprelude(void)
+{      char snap[256]; FILE *fd;
+
+       sprintf(snap, "%s.ps", oFname?oFname->name:"msc");
+       if (!(pfd = fopen(snap, "w")))
+               fatal("cannot create file '%s'", snap);
+
+       fprintf(pfd, "%%!PS-Adobe-2.0\n");
+       fprintf(pfd, "%%%%Creator: %s\n", SpinVersion);
+       fprintf(pfd, "%%%%Title: MSC %s\n", oFname?oFname->name:"--");
+       fprintf(pfd, "%%%%BoundingBox: 119 154 494 638\n");
+       ntimes(pfd, 0, 1, PsPre);
+
+       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);
+       }
+       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 *));
+       ProcLine = (char *) emalloc(1024 * sizeof(char));
+       startpage();
+}
+
+void
+putpostlude(void)
+{      putpages();
+       fprintf(pfd, "%%%%Trailer\n");
+       fprintf(pfd, "end\n");
+       fprintf(pfd, "%%%%Pages: %d\n", pspno);
+       fprintf(pfd, "%%%%EOF\n");
+       fclose(pfd);
+       /* stderr, in case user redirected output */
+       fprintf(stderr, "spin: wrote %d pages into '%s.ps'\n",
+               pspno, oFname?oFname->name:"msc");
+       exit(0);
+}
+
+void
+psline(int x0, int iy0, int x1, int iy1, float r, float g, float b, int w)
+{      int y0 = MH-iy0;
+       int y1 = MH-iy1;
+
+       if (y1 > y0) y1 -= MH;
+
+       fprintf(pfd, "gsave\n");
+       fprintf(pfd, "%d %d moveto\n", x0*WW, y0);
+       fprintf(pfd, "%d %d lineto\n", x1*WW, y1);
+       fprintf(pfd, "%d setlinewidth\n", w);
+       fprintf(pfd, "0 setlinecap\n");
+       fprintf(pfd, "1 setlinejoin\n");
+       fprintf(pfd, "%f %f %f setrgbcolor AdjustColor\n", r,g,b);
+       fprintf(pfd, "stroke\ngrestore\n");
+}
+
+void
+colbox(int x, int y, int w, int h, float r, float g, float b)
+{      fprintf(pfd, "%d %d moveto\n", x - w, y-h);
+       fprintf(pfd, "%d %d lineto\n", x + w, y-h);
+       fprintf(pfd, "%d %d lineto\n", x + w, y+h);
+       fprintf(pfd, "%d %d lineto\n", x - w, y+h);
+       fprintf(pfd, "%d %d lineto\n", x - w, y-h);
+       fprintf(pfd, "%f %f %f setrgbcolor AdjustColor\n", r,g,b);
+       fprintf(pfd, "closepath fill\n");
+}
+
+void
+putgrid(int p)
+{      int i;
+
+       for (i = p ; i >= 0; i--)
+       {       if (!ProcLine[i])
+               {       psline(i, 0, i, MH-1, (float) (0.4), (float) (0.4), (float) (1.0), 1);
+                       ProcLine[i] = 1;
+       }       }
+}
+
+void
+putarrow(int from, int to)
+{
+       T[D[from]] = D[to];
+}
+
+void
+stepnumber(int i)
+{      int y = MH-(i*HH)%MH;
+
+       fprintf(pfd, "gsave\n");
+       fprintf(pfd, "/Courier-Bold findfont 6 scalefont ");
+       fprintf(pfd, "ISOEncode setfont\n");
+       fprintf(pfd, "0.000 0.000 0.000 setrgbcolor AdjustColor\n");
+       fprintf(pfd, "%d %d [\n", -40, y);
+       fprintf(pfd, "    (%d)\n] 10 -0.5 0.5 0 ", R[i]);
+       fprintf(pfd, "false DrawText\ngrestore\n");
+       fprintf(pfd, "%d %d moveto\n", -20, y);
+       fprintf(pfd, "%d %d lineto\n", M[i]*WW, y);
+       fprintf(pfd, "1 setlinewidth\n0 setlinecap\n1 setlinejoin\n");
+       fprintf(pfd, "0.92 0.92 0.92 setrgbcolor AdjustColor\n");
+       fprintf(pfd, "stroke\n");
+}
+
+void
+spitbox(int x, int dx, int y, char *s)
+{      float r,g,b, bw; int a; char d[256];
+
+       if (!dx)
+       {       stepnumber(y);
+               putgrid(x);
+       }
+       bw = (float)2.7*(float)strlen(s);
+       colbox(x*WW+dx, MH-(y*HH)%MH, (int) (bw+1.0),
+               5, (float) 0.,(float) 0.,(float) 0.);
+       if (s[0] == '~')
+       {       switch (s[1]) {
+               case 'B': r = (float) 0.2; g = (float) 0.2; b = (float) 1.;
+                         break;
+               case 'G': r = (float) 0.2; g = (float) 1.; b = (float) 0.2;
+                         break;
+               case 'R':
+               default : r = (float) 1.; g = (float) 0.2; b = (float) 0.2;
+                         break;
+               }
+               s += 2;
+       } else if (strchr(s, '!'))
+       {       r = (float) 1.; g = (float) 1.; b = (float) 1.;
+       } else if (strchr(s, '?'))
+       {       r = (float) 0.; g = (float) 1.; b = (float) 1.;
+       } else
+       {       r = (float) 1.; g = (float) 1.; b = (float) 0.;
+               if (!dx
+               &&  sscanf(s, "%d:%250s", &a, d) == 2   /* was &d */
+               &&  a >= 0 && a < TotSteps)
+               {       if (!I[a]
+                       ||  strlen(I[a]) <= strlen(s))
+                               I[a] = emalloc((int) strlen(s)+1);
+                       strcpy(I[a], s);
+       }       }
+       colbox(x*WW+dx, MH-(y*HH)%MH, (int) bw, 4, r,g,b);
+       fprintf(pfd, "gsave\n");
+       fprintf(pfd, "/Courier-Bold findfont 8 scalefont ");
+       fprintf(pfd, "ISOEncode setfont\n");
+       fprintf(pfd, "0.000 0.000 0.000 setrgbcolor AdjustColor\n");
+       fprintf(pfd, "%d %d [\n", x*WW+dx, MH-(y*HH)%MH);
+       fprintf(pfd, "    (%s)\n] 10 -0.5 0.5 0 ", s);
+       fprintf(pfd, "false DrawText\ngrestore\n");
+}
+
+void
+putpages(void)
+{      int i, lasti=0; float nmh;
+
+       if (maxx*WW > MW-RH/2)
+       {       Scaler = (float) (MW-RH/2) / (float) (maxx*WW);
+               fprintf(pfd, "%f %f scale\n", Scaler, Scaler);
+               nmh = (float) MH; nmh /= Scaler; MH = (int) nmh;
+       }
+
+       for (i = TotSteps-1; i >= 0; i--)
+       {       if (!I[i]) continue;
+               spitbox(i, 0, 0, I[i]);
+       }
+       if (ldepth >= TotSteps) ldepth = TotSteps-1;
+       for (i = 0; i <= ldepth; i++)
+       {       if (!M[i] && !L[i]) continue;   /* no box here */
+               if (6+i*HH >= MH*pspno)
+               { fprintf(pfd, "showpage\nrestore\n"); startpage(); }
+               if (T[i] > 0)   /* red arrow */
+               {       int reali = i*HH;
+                       int realt = T[i]*HH;
+                       int topop = (reali)/MH; topop *= MH;
+                       reali -= topop;  realt -= topop;
+
+                       if (M[i] == M[T[i]] && reali == realt)
+                               /* an rv handshake */
+                               psline( M[lasti], reali+2-3*HH/2,
+                                       M[i], reali,
+                                       (float) 1.,(float) 0.,(float) 0., 2);
+                       else
+                               psline( M[i],    reali,
+                                       M[T[i]], realt,
+                                       (float) 1.,(float) 0.,(float) 0., 2);
+
+                       if (realt >= MH) T[T[i]] = -i;
+
+               } else if (T[i] < 0)    /* arrow from prev page */
+               {       int reali = (-T[i])*HH;
+                       int realt = i*HH;
+                       int topop = (realt)/MH; topop *= MH;
+                       reali -= topop;  realt -= topop;
+
+                       psline( M[-T[i]], reali,
+                               M[i],     realt,
+                               (float) 1., (float) 0., (float) 0., 2);
+               }
+               if (L[i])
+               {       spitbox(M[i], 0, i, L[i]);
+                       /* free(L[i]); */
+                       lasti = i;
+               }
+       }
+       fprintf(pfd, "showpage\nrestore\n");
+}
+
+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;
+}
+
+void
+pstext(int x, char *s)
+{      char *tmp = emalloc((int) strlen(s)+1);
+
+       strcpy(tmp, s);
+       if (depth == 0)
+               I[x] = tmp;
+       else
+       {       putbox(x);
+               if (depth >= TotSteps || ldepth >= TotSteps)
+               {       fprintf(stderr, "max nr of %d steps exceeded\n",
+                               TotSteps);
+                       fatal("aborting", (char *) 0);
+               }
+
+               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);
+       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/reprosrc.c b/trunk/verif/Spin/Src5.1.6/reprosrc.c
new file mode 100755 (executable)
index 0000000..0d4ba6b
--- /dev/null
@@ -0,0 +1,136 @@
+/***** 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            */
+
+#include <stdio.h>
+#include "spin.h"
+#include "y.tab.h"
+
+static int indent = 1;
+
+extern ProcList        *rdy;
+void repro_seq(Sequence *);
+
+void
+doindent(void)
+{      int i;
+       for (i = 0; i < indent; i++)
+               printf("   ");
+}
+
+void
+repro_sub(Element *e)
+{
+       doindent();
+       switch (e->n->ntyp) {
+       case D_STEP:
+               printf("d_step {\n");
+               break;
+       case ATOMIC:
+               printf("atomic {\n");
+               break;
+       case NON_ATOMIC:
+               printf(" {\n");
+               break;
+       }
+       indent++;
+       repro_seq(e->n->sl->this);
+       indent--;
+
+       doindent();
+       printf(" };\n");
+}
+
+void
+repro_seq(Sequence *s)
+{      Element *e;
+       Symbol *v;
+       SeqList *h;
+
+       for (e = s->frst; e; e = e->nxt)
+       {
+               v = has_lab(e, 0);
+               if (v) printf("%s:\n", v->name);
+
+               if (e->n->ntyp == UNLESS)
+               {       printf("/* normal */ {\n");
+                       repro_seq(e->n->sl->this);
+                       doindent();
+                       printf("} unless {\n");
+                       repro_seq(e->n->sl->nxt->this);
+                       doindent();
+                       printf("}; /* end unless */\n");
+               } else if (e->sub)
+               {
+                       switch (e->n->ntyp) {
+                       case DO: doindent(); printf("do\n"); indent++; break;
+                       case IF: doindent(); printf("if\n"); indent++; break;
+                       }
+
+                       for (h = e->sub; h; h = h->nxt)
+                       {       indent--; doindent(); indent++; printf("::\n");
+                               repro_seq(h->this);
+                               printf("\n");
+                       }
+
+                       switch (e->n->ntyp) {
+                       case DO: indent--; doindent(); printf("od;\n"); break;
+                       case IF: indent--; doindent(); printf("fi;\n"); break;
+                       }
+               } else
+               {       if (e->n->ntyp == ATOMIC
+                       ||  e->n->ntyp == D_STEP
+                       ||  e->n->ntyp == NON_ATOMIC)
+                               repro_sub(e);
+                       else if (e->n->ntyp != '.'
+                            &&  e->n->ntyp != '@'
+                            &&  e->n->ntyp != BREAK)
+                       {
+                               doindent();
+                               if (e->n->ntyp == C_CODE)
+                               {       printf("c_code ");
+                                       plunk_inline(stdout, e->n->sym->name, 1);
+                               } else if (e->n->ntyp == 'c'
+                                      &&  e->n->lft->ntyp == C_EXPR)
+                               {       printf("c_expr { ");
+                                       plunk_expr(stdout, e->n->lft->sym->name);
+                                       printf("} ->\n");
+                               } else
+                               {       comment(stdout, e->n, 0);
+                                       printf(";\n");
+                       }       }
+               }
+               if (e == s->last)
+                       break;
+       }
+}
+
+void
+repro_proc(ProcList *p)
+{
+       if (!p) return;
+       if (p->nxt) repro_proc(p->nxt);
+
+       if (p->det) printf("D");        /* deterministic */
+       printf("proctype %s()", p->n->name);
+       if (p->prov)
+       {       printf(" provided ");
+               comment(stdout, p->prov, 0);
+       }
+       printf("\n{\n");
+       repro_seq(p->s);
+       printf("}\n");
+}
+
+void
+repro_src(void)
+{
+       repro_proc(rdy);
+}
diff --git a/trunk/verif/Spin/Src5.1.6/run.c b/trunk/verif/Spin/Src5.1.6/run.c
new file mode 100755 (executable)
index 0000000..4c57d0b
--- /dev/null
@@ -0,0 +1,602 @@
+/***** 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            */
+
+#include <stdlib.h>
+#include "spin.h"
+#include "y.tab.h"
+
+extern RunList *X, *run;
+extern Symbol  *Fname;
+extern Element *LastStep;
+extern int     Rvous, lineno, Tval, interactive, MadeChoice;
+extern int     TstOnly, verbose, s_trail, xspin, jumpsteps, depth;
+extern int     nproc, nstop, no_print, like_java;
+
+static long    Seed = 1;
+static int     E_Check = 0, Escape_Check = 0;
+
+static int     eval_sync(Element *);
+static int     pc_enabled(Lextok *n);
+extern void    sr_buf(int, int);
+
+void
+Srand(unsigned int s)
+{      Seed = s;
+}
+
+long
+Rand(void)
+{      /* CACM 31(10), Oct 1988 */
+       Seed = 16807*(Seed%127773) - 2836*(Seed/127773);
+       if (Seed <= 0) Seed += 2147483647;
+       return Seed;
+}
+
+Element *
+rev_escape(SeqList *e)
+{      Element *r;
+
+       if (!e)
+               return (Element *) 0;
+
+       if ((r = rev_escape(e->nxt)) != ZE) /* reversed order */
+               return r;
+
+       return eval_sub(e->this->frst);         
+}
+
+Element *
+eval_sub(Element *e)
+{      Element *f, *g;
+       SeqList *z;
+       int i, j, k;
+
+       if (!e || !e->n)
+               return ZE;
+#ifdef DEBUG
+       printf("\n\teval_sub(%d %s: line %d) ",
+               e->Seqno, e->esc?"+esc":"", e->n?e->n->ln:0);
+       comment(stdout, e->n, 0);
+       printf("\n");
+#endif
+       if (e->n->ntyp == GOTO)
+       {       if (Rvous) return ZE;
+               LastStep = e;
+               f = get_lab(e->n, 1);
+               cross_dsteps(e->n, f->n);
+               return f;
+       }
+       if (e->n->ntyp == UNLESS)
+       {       /* escapes were distributed into sequence */
+               return eval_sub(e->sub->this->frst);
+       } else if (e->sub)      /* true for IF, DO, and UNLESS */
+       {       Element *has_else = ZE;
+               Element *bas_else = ZE;
+               int nr_else = 0, nr_choices = 0;
+
+               if (interactive
+               && !MadeChoice && !E_Check
+               && !Escape_Check
+               && !(e->status&(D_ATOM))
+               && depth >= jumpsteps)
+               {       printf("Select stmnt (");
+                       whoruns(0); printf(")\n");
+                       if (nproc-nstop > 1)
+                       printf("\tchoice 0: other process\n");
+               }
+               for (z = e->sub, j=0; z; z = z->nxt)
+               {       j++;
+                       if (interactive
+                       && !MadeChoice && !E_Check
+                       && !Escape_Check
+                       && !(e->status&(D_ATOM))
+                       && depth >= jumpsteps
+                       && z->this->frst
+                       && (xspin || (verbose&32) || Enabled0(z->this->frst)))
+                       {       if (z->this->frst->n->ntyp == ELSE)
+                               {       has_else = (Rvous)?ZE:z->this->frst->nxt;
+                                       nr_else = j;
+                                       continue;
+                               }
+                               printf("\tchoice %d: ", j);
+#if 0
+                               if (z->this->frst->n)
+                                       printf("line %d, ", z->this->frst->n->ln);
+#endif
+                               if (!Enabled0(z->this->frst))
+                                       printf("unexecutable, ");
+                               else
+                                       nr_choices++;
+                               comment(stdout, z->this->frst->n, 0);
+                               printf("\n");
+               }       }
+
+               if (nr_choices == 0 && has_else)
+                       printf("\tchoice %d: (else)\n", nr_else);
+
+               if (interactive && depth >= jumpsteps
+               && !Escape_Check
+               && !(e->status&(D_ATOM))
+               && !E_Check)
+               {       if (!MadeChoice)
+                       {       char buf[256];
+                               if (xspin)
+                                       printf("Make Selection %d\n\n", j);
+                               else
+                                       printf("Select [0-%d]: ", j);
+                               fflush(stdout);
+                               scanf("%64s", buf);
+                               if (isdigit(buf[0]))
+                                       k = atoi(buf);
+                               else
+                               {       if (buf[0] == 'q')
+                                               alldone(0);
+                                       k = -1;
+                               }
+                       } else
+                       {       k = MadeChoice;
+                               MadeChoice = 0;
+                       }
+                       if (k < 1 || k > j)
+                       {       if (k != 0) printf("\tchoice outside range\n");
+                               return ZE;
+                       }
+                       k--;
+               } else
+               {       if (e->n && e->n->indstep >= 0)
+                               k = 0;  /* select 1st executable guard */
+                       else
+                               k = Rand()%j;   /* nondeterminism */
+               }
+               has_else = ZE;
+               bas_else = ZE;
+               for (i = 0, z = e->sub; i < j+k; i++)
+               {       if (z->this->frst
+                       &&  z->this->frst->n->ntyp == ELSE)
+                       {       bas_else = z->this->frst;
+                               has_else = (Rvous)?ZE:bas_else->nxt;
+                               if (!interactive || depth < jumpsteps
+                               || Escape_Check
+                               || (e->status&(D_ATOM)))
+                               {       z = (z->nxt)?z->nxt:e->sub;
+                                       continue;
+                               }
+                       }
+                       if (z->this->frst
+                       &&  ((z->this->frst->n->ntyp == ATOMIC
+                         ||  z->this->frst->n->ntyp == D_STEP)
+                         &&  z->this->frst->n->sl->this->frst->n->ntyp == ELSE))
+                       {       bas_else = z->this->frst->n->sl->this->frst;
+                               has_else = (Rvous)?ZE:bas_else->nxt;
+                               if (!interactive || depth < jumpsteps
+                               || Escape_Check
+                               || (e->status&(D_ATOM)))
+                               {       z = (z->nxt)?z->nxt:e->sub;
+                                       continue;
+                               }
+                       }
+                       if (i >= k)
+                       {       if ((f = eval_sub(z->this->frst)) != ZE)
+                                       return f;
+                               else if (interactive && depth >= jumpsteps
+                               && !(e->status&(D_ATOM)))
+                               {       if (!E_Check && !Escape_Check)
+                                               printf("\tunexecutable\n");
+                                       return ZE;
+                       }       }
+                       z = (z->nxt)?z->nxt:e->sub;
+               }
+               LastStep = bas_else;
+               return has_else;
+       } else
+       {       if (e->n->ntyp == ATOMIC
+               ||  e->n->ntyp == D_STEP)
+               {       f = e->n->sl->this->frst;
+                       g = e->n->sl->this->last;
+                       g->nxt = e->nxt;
+                       if (!(g = eval_sub(f))) /* atomic guard */
+                               return ZE;
+                       return g;
+               } else if (e->n->ntyp == NON_ATOMIC)
+               {       f = e->n->sl->this->frst;
+                       g = e->n->sl->this->last;
+                       g->nxt = e->nxt;                /* close it */
+                       return eval_sub(f);
+               } else if (e->n->ntyp == '.')
+               {       if (!Rvous) return e->nxt;
+                       return eval_sub(e->nxt);
+               } else
+               {       SeqList *x;
+                       if (!(e->status & (D_ATOM))
+                       &&  e->esc && verbose&32)
+                       {       printf("Stmnt [");
+                               comment(stdout, e->n, 0);
+                               printf("] has escape(s): ");
+                               for (x = e->esc; x; x = x->nxt)
+                               {       printf("[");
+                                       g = x->this->frst;
+                                       if (g->n->ntyp == ATOMIC
+                                       ||  g->n->ntyp == NON_ATOMIC)
+                                               g = g->n->sl->this->frst;
+                                       comment(stdout, g->n, 0);
+                                       printf("] ");
+                               }
+                               printf("\n");
+                       }
+#if 0
+                       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
+                       {       Escape_Check++;
+                               if (like_java)
+                               {       if ((g = rev_escape(e->esc)) != ZE)
+                                       {       if (verbose&4)
+                                                       printf("\tEscape taken\n");
+                                               Escape_Check--;
+                                               return g;
+                                       }
+                               } else
+                               {       for (x = e->esc; x; x = x->nxt)
+                                       {       if ((g = eval_sub(x->this->frst)) != ZE)
+                                               {       if (verbose&4)
+                                                               printf("\tEscape taken\n");
+                                                       Escape_Check--;
+                                                       return g;
+                               }       }       }
+                               Escape_Check--;
+                       }
+               
+                       switch (e->n->ntyp) {
+                       case TIMEOUT: case RUN:
+                       case PRINT: case PRINTM:
+                       case C_CODE: case C_EXPR:
+                       case ASGN: case ASSERT:
+                       case 's': case 'r': case 'c':
+                               /* toplevel statements only */
+                               LastStep = e;
+                       default:
+                               break;
+                       }
+                       if (Rvous)
+                       {
+                               return (eval_sync(e))?e->nxt:ZE;
+                       }
+                       return (eval(e->n))?e->nxt:ZE;
+               }
+       }
+       return ZE; /* not reached */
+}
+
+static int
+eval_sync(Element *e)
+{      /* allow only synchronous receives
+          and related node types    */
+       Lextok *now = (e)?e->n:ZN;
+
+       if (!now
+       ||  now->ntyp != 'r'
+       ||  now->val >= 2       /* no rv with a poll */
+       ||  !q_is_sync(now))
+       {
+               return 0;
+       }
+
+       LastStep = e;
+       return eval(now);
+}
+
+static int
+assign(Lextok *now)
+{      int t;
+
+       if (TstOnly) return 1;
+
+       switch (now->rgt->ntyp) {
+       case FULL:      case NFULL:
+       case EMPTY:     case NEMPTY:
+       case RUN:       case LEN:
+               t = BYTE;
+               break;
+       default:
+               t = Sym_typ(now->rgt);
+               break;
+       }
+       typ_ck(Sym_typ(now->lft), t, "assignment"); 
+       return setval(now->lft, eval(now->rgt));
+}
+
+static int
+nonprogress(void)      /* np_ */
+{      RunList *r;
+
+       for (r = run; r; r = r->nxt)
+       {       if (has_lab(r->pc, 4))  /* 4=progress */
+                       return 0;
+       }
+       return 1;
+}
+
+int
+eval(Lextok *now)
+{
+       if (now) {
+       lineno = now->ln;
+       Fname  = now->fn;
+#ifdef DEBUG
+       printf("eval ");
+       comment(stdout, now, 0);
+       printf("\n");
+#endif
+       switch (now->ntyp) {
+       case CONST: return now->val;
+       case   '!': return !eval(now->lft);
+       case  UMIN: return -eval(now->lft);
+       case   '~': return ~eval(now->lft);
+
+       case   '/': return (eval(now->lft) / eval(now->rgt));
+       case   '*': return (eval(now->lft) * eval(now->rgt));
+       case   '-': return (eval(now->lft) - eval(now->rgt));
+       case   '+': return (eval(now->lft) + eval(now->rgt));
+       case   '%': return (eval(now->lft) % eval(now->rgt));
+       case    LT: return (eval(now->lft) <  eval(now->rgt));
+       case    GT: return (eval(now->lft) >  eval(now->rgt));
+       case   '&': return (eval(now->lft) &  eval(now->rgt));
+       case   '^': return (eval(now->lft) ^  eval(now->rgt));
+       case   '|': return (eval(now->lft) |  eval(now->rgt));
+       case    LE: return (eval(now->lft) <= eval(now->rgt));
+       case    GE: return (eval(now->lft) >= eval(now->rgt));
+       case    NE: return (eval(now->lft) != eval(now->rgt));
+       case    EQ: return (eval(now->lft) == eval(now->rgt));
+       case    OR: return (eval(now->lft) || eval(now->rgt));
+       case   AND: return (eval(now->lft) && eval(now->rgt));
+       case LSHIFT: return (eval(now->lft) << eval(now->rgt));
+       case RSHIFT: return (eval(now->lft) >> eval(now->rgt));
+       case   '?': return (eval(now->lft) ? eval(now->rgt->lft)
+                                          : eval(now->rgt->rgt));
+
+       case     'p': return remotevar(now);    /* _p for remote reference */
+       case     'q': return remotelab(now);
+       case     'R': return qrecv(now, 0);     /* test only    */
+       case     LEN: return qlen(now);
+       case    FULL: return (qfull(now));
+       case   EMPTY: return (qlen(now)==0);
+       case   NFULL: return (!qfull(now));
+       case  NEMPTY: return (qlen(now)>0);
+       case ENABLED: if (s_trail) return 1;
+                     return pc_enabled(now->lft);
+       case    EVAL: return eval(now->lft);
+       case  PC_VAL: return pc_value(now->lft);
+       case NONPROGRESS: return nonprogress();
+       case    NAME: return getval(now);
+
+       case TIMEOUT: return Tval;
+       case     RUN: return TstOnly?1:enable(now);
+
+       case   's': return qsend(now);          /* send         */
+       case   'r': return qrecv(now, 1);       /* receive or poll */
+       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 C_CODE: printf("%s:\t", now->sym->name);
+                    plunk_inline(stdout, now->sym->name, 0);
+                    return 1; /* uninterpreted */
+
+       case C_EXPR: 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;
+                    non_fatal("assertion violated", (char *) 0);
+                       printf("spin: text of failed assertion: assert(");
+                       comment(stdout, now->lft, 0);
+                       printf(")\n");
+                    if (s_trail && !xspin) return 1;
+                    wrapup(1); /* doesn't return */
+
+       case  IF: case DO: case BREAK: case UNLESS:     /* compound */
+       case   '.': return 1;   /* return label for compound */
+       case   '@': return 0;   /* stop state */
+       case  ELSE: return 1;   /* only hit here in guided trails */
+       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);
+       }}
+       return 0;
+}
+
+int
+printm(FILE *fd, Lextok *n)
+{      extern char Buf[];
+       int j;
+
+       Buf[0] = '\0';
+       if (!no_print)
+       if (!s_trail || depth >= jumpsteps) {
+               if (n->lft->ismtyp)
+                       j = n->lft->val;
+               else
+                       j = eval(n->lft);
+               sr_buf(j, 1);
+               dotag(fd, Buf);
+       }
+       return 1;
+}
+
+int
+interprint(FILE *fd, Lextok *n)
+{      Lextok *tmp = n->lft;
+       char c, *s = n->sym->name;
+       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)
+       if (!s_trail || depth >= jumpsteps) {
+       for (i = 0; i < (int) strlen(s); i++)
+               switch (s[i]) {
+               case '\"': break; /* ignore */
+               case '\\':
+                        switch(s[++i]) {
+                        case 't': strcat(Buf, "\t"); break;
+                        case 'n': strcat(Buf, "\n"); break;
+                        default:  goto onechar;
+                        }
+                        break;
+               case  '%':
+                        if ((c = s[++i]) == '%')
+                        {      strcat(Buf, "%"); /* literal */
+                               break;
+                        }
+                        if (!tmp)
+                        {      non_fatal("too few print args %s", s);
+                               break;
+                        }
+                        j = eval(tmp->lft);
+                        tmp = tmp->rgt;
+                        switch(c) {
+                        case 'c': sprintf(lbuf, "%c", j); break;
+                        case 'd': sprintf(lbuf, "%d", j); break;
+
+                        case 'e': strcpy(tBuf, Buf);   /* event name */
+                                  Buf[0] = '\0';
+                                  sr_buf(j, 1);
+                                  strcpy(lbuf, Buf);
+                                  strcpy(Buf, tBuf);
+                                  break;
+
+                        case 'o': sprintf(lbuf, "%o", j); break;
+                        case 'u': sprintf(lbuf, "%u", (unsigned) j); break;
+                        case 'x': sprintf(lbuf, "%x", j); break;
+                        default:  non_fatal("bad print cmd: '%s'", &s[i-1]);
+                                  lbuf[0] = '\0'; break;
+                        }
+                        goto append;
+               default:
+onechar:                lbuf[0] = s[i]; lbuf[1] = '\0';
+append:                         strcat(Buf, lbuf);
+                        break;
+               }
+               dotag(fd, Buf);
+       }
+       if (strlen(Buf) >= 4096) fatal("printf string too long", 0);
+       return 1;
+}
+
+static int
+Enabled1(Lextok *n)
+{      int i; int v = verbose;
+
+       if (n)
+       switch (n->ntyp) {
+       case 'c':
+               if (has_typ(n->lft, RUN))
+                       return 1;       /* conservative */
+               /* else fall through */
+       default:        /* side-effect free */
+               verbose = 0;
+               E_Check++;
+               i = eval(n);
+               E_Check--;
+               verbose = v;
+               return i;
+
+       case C_CODE: case C_EXPR:
+       case PRINT: case PRINTM:
+       case   ASGN: case ASSERT:
+               return 1;
+
+       case 's':
+               if (q_is_sync(n))
+               {       if (Rvous) return 0;
+                       TstOnly = 1; verbose = 0;
+                       E_Check++;
+                       i = eval(n);
+                       E_Check--;
+                       TstOnly = 0; verbose = v;
+                       return i;
+               }
+               return (!qfull(n));
+       case 'r':
+               if (q_is_sync(n))
+                       return 0;       /* it's never a user-choice */
+               n->ntyp = 'R'; verbose = 0;
+               E_Check++;
+               i = eval(n);
+               E_Check--;
+               n->ntyp = 'r'; verbose = v;
+               return i;
+       }
+       return 0;
+}
+
+int
+Enabled0(Element *e)
+{      SeqList *z;
+
+       if (!e || !e->n)
+               return 0;
+
+       switch (e->n->ntyp) {
+       case '@':
+               return X->pid == (nproc-nstop-1);
+       case '.':
+               return 1;
+       case GOTO:
+               if (Rvous) return 0;
+               return 1;
+       case UNLESS:
+               return Enabled0(e->sub->this->frst);
+       case ATOMIC:
+       case D_STEP:
+       case NON_ATOMIC:
+               return Enabled0(e->n->sl->this->frst);
+       }
+       if (e->sub)     /* true for IF, DO, and UNLESS */
+       {       for (z = e->sub; z; z = z->nxt)
+                       if (Enabled0(z->this->frst))
+                               return 1;
+               return 0;
+       }
+       for (z = e->esc; z; z = z->nxt)
+       {       if (Enabled0(z->this->frst))
+                       return 1;
+       }
+#if 0
+       printf("enabled1 ");
+       comment(stdout, e->n, 0);
+       printf(" ==> %s\n", Enabled1(e->n)?"yes":"nope");
+#endif
+       return Enabled1(e->n);
+}
+
+int
+pc_enabled(Lextok *n)
+{      int i = nproc - nstop;
+       int pid = eval(n);
+       int result = 0;
+       RunList *Y, *oX;
+
+       if (pid == X->pid)
+               fatal("used: enabled(pid=thisproc) [%s]", X->n->name);
+
+       for (Y = run; Y; Y = Y->nxt)
+               if (--i == pid)
+               {       oX = X; X = Y;
+                       result = Enabled0(Y->pc);
+                       X = oX;
+                       break;
+               }
+       return result;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/sched.c b/trunk/verif/Spin/Src5.1.6/sched.c
new file mode 100755 (executable)
index 0000000..ed4b085
--- /dev/null
@@ -0,0 +1,1036 @@
+/***** 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            */
+
+#include <stdlib.h>
+#include "spin.h"
+#include "y.tab.h"
+
+extern int     verbose, s_trail, analyze, no_wrapup;
+extern char    *claimproc, *eventmap, Buf[];
+extern Ordered *all_names;
+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;
+
+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            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 *);
+
+void
+runnable(ProcList *p, int weight, int noparams)
+{      RunList *r = (RunList *) emalloc(sizeof(RunList));
+
+       r->n  = p->n;
+       r->tn = p->tn;
+       r->pid = nproc++ - nstop + Skip_claim;
+
+       if ((verbose&4) || (verbose&32))
+               printf("Starting %s with pid %d\n",
+                       p->n?p->n->name:"--", r->pid);
+
+       if (!p->s)
+               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;
+
+       if (p->s->last)
+               p->s->last->status |= ENDSTATE; /* normal end state */
+
+       r->nxt = run;
+       r->prov = p->prov;
+       r->priority = weight;
+       if (noparams) setlocals(r);
+       Priority_Sum += weight;
+       run = r;
+}
+
+ProcList *
+ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov)
+       /* n=name, p=formals, s=body det=deterministic prov=provided */
+{      ProcList *r = (ProcList *) emalloc(sizeof(ProcList));
+       Lextok *fp, *fpt; int j; extern int Npars;
+
+       r->n = n;
+       r->p = p;
+       r->s = s;
+       r->prov = prov;
+       r->tn = nrRdy++;
+       if (det != 0 && det != 1)
+       {       fprintf(stderr, "spin: bad value for det (cannot happen)\n");
+       }
+       r->det = (short) det;
+       r->nxt = rdy;
+       rdy = r;
+
+       for (fp  = p, j = 0;  fp;  fp = fp->rgt)
+       for (fpt = fp->lft;  fpt; fpt = fpt->rgt)
+               j++;    /* count # of parameters */
+       Npars = max(Npars, j);
+
+       return rdy;
+}
+
+int
+find_maxel(Symbol *s)
+{      ProcList *p;
+
+       for (p = rdy; p; p = p->nxt)
+               if (p->n == s)
+                       return p->s->maxel++;
+       return Elcnt++;
+}
+
+static void
+formdump(void)
+{      ProcList *p;
+       Lextok *f, *t;
+       int cnt;
+
+       for (p = rdy; p; p = p->nxt)
+       {       if (!p->p) continue;
+               cnt = -1;
+               for (f = p->p; f; f = f->rgt)   /* types */
+               for (t = f->lft; t; t = t->rgt) /* formals */
+               {       if (t->ntyp != ',')
+                               t->sym->Nid = cnt--;    /* overload Nid */
+                       else
+                               t->lft->sym->Nid = cnt--;
+               }
+       }
+}
+
+void
+announce(char *w)
+{
+       if (columns)
+       {       extern char Buf[];
+               extern int firstrow;
+               firstrow = 1;
+               if (columns == 2)
+               {       sprintf(Buf, "%d:%s",
+                       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);
+               return;
+       }
+
+       if (dumptab
+       ||  analyze
+       ||  s_trail
+       || !(verbose&4))
+               return;
+
+       if (w)
+               printf("  0:    proc  - (%s) ", w);
+       else
+               whoruns(1);
+       printf("creates proc %2d (%s)",
+               run->pid - Have_claim,
+               run->n->name);
+       if (run->priority > 1)
+               printf(" priority %d", run->priority);
+       printf("\n");
+}
+
+#ifndef MAXP
+#define MAXP   255     /* matches max nr of processes in verifier */
+#endif
+
+int
+enable(Lextok *m)
+{      ProcList *p;
+       Symbol *s = m->sym;     /* proctype name */
+       Lextok *n = m->lft;     /* actual parameters */
+
+       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 (nproc-nstop >= MAXP)
+                       {       printf("spin: too many processes (%d max)\n", MAXP);
+                               break;
+                       }
+                       runnable(p, m->val, 0);
+                       announce((char *) 0);
+                       setparams(run, p, n);
+                       setlocals(run); /* after setparams */
+                       return run->pid - Have_claim + Skip_claim; /* effective simu pid */
+               }
+       return 0; /* process not found */
+}
+
+void
+check_param_count(int i, Lextok *m)
+{      ProcList *p;
+       Symbol *s = m->sym;     /* proctype name */
+       Lextok *f, *t;          /* formal pars */
+       int cnt = 0;
+
+       for (p = rdy; p; p = p->nxt)
+       {       if (strcmp(s->name, p->n->name) == 0)
+               {       if (m->lft)     /* actual param list */
+                       {       lineno = m->lft->ln;
+                               Fname  = m->lft->fn;
+                       }
+                       for (f = p->p;   f; f = f->rgt) /* one type at a time */
+                       for (t = f->lft; t; t = t->rgt) /* count formal params */
+                       {       cnt++;
+                       }
+                       if (i != cnt)
+                       {       printf("spin: saw %d parameters, expected %d\n", i, cnt);
+                               non_fatal("wrong number of parameters", "");
+                       }
+                       break;
+       }       }
+}
+
+void
+start_claim(int n)
+{      ProcList *p;
+       RunList  *r, *q = (RunList *) 0;
+
+       for (p = rdy; p; p = p->nxt)
+               if (p->tn == n
+               &&  strcmp(p->n->name, ":never:") == 0)
+               {       runnable(p, 1, 1);
+                       goto found;
+               }
+       printf("spin: couldn't find claim (ignored)\n");
+       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:");
+               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 (run->pid == 0) return; /* it is the first process started */
+
+       q = run; run = run->nxt;
+       q->pid = 0; q->nxt = (RunList *) 0;     /* remove */
+done:
+       Have_claim = 1;
+       for (r = run; r; r = r->nxt)
+       {       r->pid = r->pid+Have_claim;     /* adjust */
+               if (!r->nxt)
+               {       r->nxt = q;
+                       break;
+       }       }
+}
+
+int
+f_pid(char *n)
+{      RunList *r;
+       int rval = -1;
+
+       for (r = run; r; r = r->nxt)
+               if (strcmp(n, r->n->name) == 0)
+               {       if (rval >= 0)
+                       {       printf("spin: remote ref to proctype %s, ", n);
+                               printf("has more than one match: %d and %d\n",
+                                       rval, r->pid);
+                       } else
+                               rval = r->pid;
+               }
+       return rval;
+}
+
+void
+wrapup(int fini)
+{
+       limited_vis = 0;
+       if (columns)
+       {       extern void putpostlude(void);
+               if (columns == 2) putpostlude();
+               if (!no_wrapup)
+               printf("-------------\nfinal state:\n-------------\n");
+       }
+       if (no_wrapup)
+               goto short_cut;
+       if (nproc != nstop)
+       {       int ov = verbose;
+               printf("#processes: %d\n", nproc-nstop - Have_claim + Skip_claim);
+               verbose &= ~4;
+               dumpglobals();
+               verbose = ov;
+               verbose &= ~1;  /* no more globals */
+               verbose |= 32;  /* add process states */
+               for (X = run; X; X = X->nxt)
+                       talk(X);
+               verbose = ov;   /* restore */
+       }
+       printf("%d process%s created\n",
+               nproc - Have_claim + Skip_claim,
+               (xspin || nproc!=1)?"es":"");
+short_cut:
+       if (xspin) alldone(0);  /* avoid an abort from xspin */
+       if (fini)  alldone(1);
+}
+
+static char is_blocked[256];
+
+static int
+p_blocked(int p)
+{      int i, j;
+
+       is_blocked[p%256] = 1;
+       for (i = j = 0; i < nproc - nstop; i++)
+               j += is_blocked[i];
+       if (j >= nproc - nstop)
+       {       memset(is_blocked, 0, 256);
+               return 1;
+       }
+       return 0;
+}
+
+static Element *
+silent_moves(Element *e)
+{      Element *f;
+
+       if (e->n)
+       switch (e->n->ntyp) {
+       case GOTO:
+               if (Rvous) break;
+               f = get_lab(e->n, 1);
+               cross_dsteps(e->n, f->n);
+               return f; /* guard against goto cycles */
+       case UNLESS:
+               return silent_moves(e->sub->this->frst);
+       case NON_ATOMIC:
+       case ATOMIC:
+       case D_STEP:
+               e->n->sl->this->last->nxt = e->nxt;
+               return silent_moves(e->n->sl->this->frst);
+       case '.':
+               return silent_moves(e->nxt);
+       }
+       return e;
+}
+
+static RunList *
+pickproc(RunList *Y)
+{      SeqList *z; Element *has_else;
+       short Choices[256];
+       int j, k, nr_else = 0;
+
+       if (nproc <= nstop+1)
+       {       X = run;
+               return NULL;
+       }
+       if (!interactive || depth < jumpsteps)
+       {       /* was: j = (int) Rand()%(nproc-nstop); */
+               if (Priority_Sum < nproc-nstop)
+                       fatal("cannot happen - weights", (char *)0);
+               j = (int) Rand()%Priority_Sum;
+
+               while (j - X->priority >= 0)
+               {       j -= X->priority;
+                       Y = X;
+                       X = X->nxt;
+                       if (!X) { Y = NULL; X = run; }
+               }
+       } else
+       {       int only_choice = -1;
+               int no_choice = 0, proc_no_ch, proc_k;
+
+               Tval = 0;       /* new 4.2.6 */
+try_again:     printf("Select a statement\n");
+try_more:      for (X = run, k = 1; X; X = X->nxt)
+               {       if (X->pid > 255) break;
+
+                       Choices[X->pid] = (short) k;
+
+                       if (!X->pc
+                       ||  (X->prov && !eval(X->prov)))
+                       {       if (X == run)
+                                       Choices[X->pid] = 0;
+                               continue;
+                       }
+                       X->pc = silent_moves(X->pc);
+                       if (!X->pc->sub && X->pc->n)
+                       {       int unex;
+                               unex = !Enabled0(X->pc);
+                               if (unex)
+                                       no_choice++;
+                               else
+                                       only_choice = k;
+                               if (!xspin && unex && !(verbose&32))
+                               {       k++;
+                                       continue;
+                               }
+                               printf("\tchoice %d: ", k++);
+                               p_talk(X->pc, 0);
+                               if (unex)
+                                       printf(" unexecutable,");
+                               printf(" [");
+                               comment(stdout, X->pc->n, 0);
+                               if (X->pc->esc) printf(" + Escape");
+                               printf("]\n");
+                       } else {
+                       has_else = ZE;
+                       proc_no_ch = no_choice;
+                       proc_k = k;
+                       for (z = X->pc->sub, j=0; z; z = z->nxt)
+                       {       Element *y = silent_moves(z->this->frst);
+                               int unex;
+                               if (!y) continue;
+
+                               if (y->n->ntyp == ELSE)
+                               {       has_else = (Rvous)?ZE:y;
+                                       nr_else = k++;
+                                       continue;
+                               }
+
+                               unex = !Enabled0(y);
+                               if (unex)
+                                       no_choice++;
+                               else
+                                       only_choice = k;
+                               if (!xspin && unex && !(verbose&32))
+                               {       k++;
+                                       continue;
+                               }
+                               printf("\tchoice %d: ", k++);
+                               p_talk(X->pc, 0);
+                               if (unex)
+                                       printf(" unexecutable,");
+                               printf(" [");
+                               comment(stdout, y->n, 0);
+                               printf("]\n");
+                       }
+                       if (has_else)
+                       {       if (no_choice-proc_no_ch >= (k-proc_k)-1)
+                               {       only_choice = nr_else;
+                                       printf("\tchoice %d: ", nr_else);
+                                       p_talk(X->pc, 0);
+                                       printf(" [else]\n");
+                               } else
+                               {       no_choice++;
+                                       printf("\tchoice %d: ", nr_else);
+                                       p_talk(X->pc, 0);
+                                       printf(" unexecutable, [else]\n");
+                       }       }
+               }       }
+               X = run;
+               if (k - no_choice < 2 && Tval == 0)
+               {       Tval = 1;
+                       no_choice = 0; only_choice = -1;
+                       goto try_more;
+               }
+               if (xspin)
+                       printf("Make Selection %d\n\n", k-1);
+               else
+               {       if (k - no_choice < 2)
+                       {       printf("no executable choices\n");
+                               alldone(0);
+                       }
+                       printf("Select [1-%d]: ", k-1);
+               }
+               if (!xspin && k - no_choice == 2)
+               {       printf("%d\n", only_choice);
+                       j = only_choice;
+               } else
+               {       char buf[256];
+                       fflush(stdout);
+                       scanf("%64s", buf);
+                       j = -1;
+                       if (isdigit(buf[0]))
+                               j = atoi(buf);
+                       else
+                       {       if (buf[0] == 'q')
+                                       alldone(0);
+                       }
+                       if (j < 1 || j >= k)
+                       {       printf("\tchoice is outside range\n");
+                               goto try_again;
+               }       }
+               MadeChoice = 0;
+               Y = NULL;
+               for (X = run; X; Y = X, X = X->nxt)
+               {       if (!X->nxt
+                       ||   X->nxt->pid > 255
+                       ||   j < Choices[X->nxt->pid])
+                       {
+                               MadeChoice = 1+j-Choices[X->pid];
+                               break;
+               }       }
+       }
+       return Y;
+}
+
+void
+sched(void)
+{      Element *e;
+       RunList *Y = NULL;      /* previous process in run queue */
+       RunList *oX;
+       int go, notbeyond = 0;
+#ifdef PC
+       int bufmax = 100;
+#endif
+       if (dumptab)
+       {       formdump();
+               symdump();
+               dumplabels();
+               return;
+       }
+
+       if (has_enabled && u_sync > 0)
+       {       printf("spin: error, cannot use 'enabled()' in ");
+               printf("models with synchronous channels.\n");
+               nr_errs++;
+       }
+       if (analyze)
+       {       gensrc();
+               return;
+       } else if (s_trail)
+       {       match_trail();
+               return;
+       }
+       if (claimproc)
+       printf("warning: never claim not used in random simulation\n");
+       if (eventmap)
+       printf("warning: trace assertion not used in random simulation\n");
+
+       X = run;
+       Y = pickproc(Y);
+
+       while (X)
+       {       context = X->n;
+               if (X->pc && X->pc->n)
+               {       lineno = X->pc->n->ln;
+                       Fname  = X->pc->n->fn;
+               }
+               if (cutoff > 0 && depth >= cutoff)
+               {       printf("-------------\n");
+                       printf("depth-limit (-u%d steps) reached\n", cutoff);
+                       break;
+               }
+#ifdef PC
+               if (xspin && !interactive && --bufmax <= 0)
+               {       int c; /* avoid buffer overflow on pc's */
+                       printf("spin: type return to proceed\n");
+                       fflush(stdout);
+                       c = getc(stdin);
+                       if (c == 'q') wrapup(0);
+                       bufmax = 100;
+               }
+#endif
+               depth++; LastStep = ZE;
+               oX = X; /* a rendezvous could change it */
+               go = 1;
+               if (X->prov && X->pc
+               && !(X->pc->status & D_ATOM)
+               && !eval(X->prov))
+               {       if (!xspin && ((verbose&32) || (verbose&4)))
+                       {       p_talk(X->pc, 1);
+                               printf("\t<<Not Enabled>>\n");
+                       }
+                       go = 0;
+               }
+               if (go && (e = eval_sub(X->pc)))
+               {       if (depth >= jumpsteps
+                       && ((verbose&32) || (verbose&4)))
+                       {       if (X == oX)
+                               if (!(e->status & D_ATOM) || (verbose&32)) /* no talking in d_steps */
+                               {       p_talk(X->pc, 1);
+                                       printf("        [");
+                                       if (!LastStep) LastStep = X->pc;
+                                       comment(stdout, LastStep->n, 0);
+                                       printf("]\n");
+                               }
+                               if (verbose&1) dumpglobals();
+                               if (verbose&2) dumplocal(X);
+
+                               if (!(e->status & D_ATOM))
+                               if (xspin)
+                                       printf("\n");
+                       }
+                       if (oX != X
+                       ||  (X->pc->status & (ATOM|D_ATOM)))            /* new 5.0 */
+                       {       e = silent_moves(e);
+                               notbeyond = 0;
+                       }
+                       oX->pc = e; LastX = X;
+
+                       if (!interactive) Tval = 0;
+                       memset(is_blocked, 0, 256);
+
+                       if (X->pc && (X->pc->status & (ATOM|L_ATOM))
+                       &&  (notbeyond == 0 || oX != X))
+                       {       if ((X->pc->status & L_ATOM))
+                                       notbeyond = 1;
+                               continue; /* no process switch */
+                       }
+               } else
+               {       depth--;
+                       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;
+                               else
+                                       run = X->nxt;
+                               nstop++;
+                               Priority_Sum -= X->priority;
+                               if (verbose&4)
+                               {       whoruns(1);
+                                       dotag(stdout, "terminates\n");
+                               }
+                               LastX = X;
+                               if (!interactive) Tval = 0;
+                               if (nproc == nstop) break;
+                               memset(is_blocked, 0, 256);
+                               /* proc X is no longer in runlist */
+                               X = (X->nxt) ? X->nxt : run;
+                       } else
+                       {       if (p_blocked(X->pid))
+                               {       if (Tval) break;
+                                       Tval = 1;
+                                       if (depth >= jumpsteps)
+                                       {       oX = X;
+                                               X = (RunList *) 0; /* to suppress indent */
+                                               dotag(stdout, "timeout\n");
+                                               X = oX;
+               }       }       }       }
+
+               if (!run || !X) break;  /* new 5.0 */
+
+               Y = pickproc(X);
+               notbeyond = 0;
+       }
+       context = ZS;
+       wrapup(0);
+}
+
+int
+complete_rendez(void)
+{      RunList *orun = X, *tmp;
+       Element  *s_was = LastStep;
+       Element *e;
+       int j, ointer = interactive;
+
+       if (s_trail)
+               return 1;
+       if (orun->pc->status & D_ATOM)
+               fatal("rv-attempt in d_step sequence", (char *)0);
+       Rvous = 1;
+       interactive = 0;
+
+       j = (int) Rand()%Priority_Sum;  /* randomize start point */
+       X = run;
+       while (j - X->priority >= 0)
+       {       j -= X->priority;
+               X = X->nxt;
+               if (!X) X = run;
+       }
+       for (j = nproc - nstop; j > 0; j--)
+       {       if (X != orun
+               && (!X->prov || eval(X->prov))
+               && (e = eval_sub(X->pc)))
+               {       if (TstOnly)
+                       {       X = orun;
+                               Rvous = 0;
+                               goto out;
+                       }
+                       if ((verbose&32) || (verbose&4))
+                       {       tmp = orun; orun = X; X = tmp;
+                               if (!s_was) s_was = X->pc;
+                               p_talk(s_was, 1);
+                               printf("        [");
+                               comment(stdout, s_was->n, 0);
+                               printf("]\n");
+                               tmp = orun; orun = X; X = tmp;
+                               if (!LastStep) LastStep = X->pc;
+                               p_talk(LastStep, 1);
+                               printf("        [");
+                               comment(stdout, LastStep->n, 0);
+                               printf("]\n");
+                       }
+                       Rvous = 0; /* before silent_moves */
+                       X->pc = silent_moves(e);
+out:                           interactive = ointer;
+                       return 1;
+               }
+
+               X = X->nxt;
+               if (!X) X = run;
+       }
+       Rvous = 0;
+       X = orun;
+       interactive = ointer;
+       return 0;
+}
+
+/***** Runtime - Local Variables *****/
+
+static void
+addsymbol(RunList *r, Symbol  *s)
+{      Symbol *t;
+       int i;
+
+       for (t = r->symtab; t; t = t->next)
+               if (strcmp(t->name, s->name) == 0)
+                       return;         /* it's already there */
+
+       t = (Symbol *) emalloc(sizeof(Symbol));
+       t->name = s->name;
+       t->type = s->type;
+       t->hidden = s->hidden;
+       t->nbits  = s->nbits;
+       t->nel  = s->nel;
+       t->ini  = s->ini;
+       t->setat = depth;
+       t->context = r->n;
+       if (s->type != STRUCT)
+       {       if (s->val)     /* if already initialized, copy info */
+               {       t->val = (int *) emalloc(s->nel*sizeof(int));
+                       for (i = 0; i < s->nel; i++)
+                               t->val[i] = s->val[i];
+               } else
+                       (void) checkvar(t, 0);  /* initialize it */
+       } else
+       {       if (s->Sval)
+                       fatal("saw preinitialized struct %s", s->name);
+               t->Slst = s->Slst;
+               t->Snm  = s->Snm;
+               t->owner = s->owner;
+       /*      t->context = r->n; */
+       }
+       t->next = r->symtab;    /* add it */
+       r->symtab = t;
+}
+
+static void
+setlocals(RunList *r)
+{      Ordered *walk;
+       Symbol  *sp;
+       RunList *oX = X;
+
+       X = r;
+       for (walk = all_names; walk; walk = walk->next)
+       {       sp = walk->entry;
+               if (sp
+               &&  sp->context
+               &&  strcmp(sp->context->name, r->n->name) == 0
+               &&  sp->Nid >= 0
+               && (sp->type == UNSIGNED
+               ||  sp->type == BIT
+               ||  sp->type == MTYPE
+               ||  sp->type == BYTE
+               ||  sp->type == CHAN
+               ||  sp->type == SHORT
+               ||  sp->type == INT
+               ||  sp->type == STRUCT))
+               {       if (!findloc(sp))
+                       non_fatal("setlocals: cannot happen '%s'",
+                               sp->name);
+               }
+       }
+       X = oX;
+}
+
+static void
+oneparam(RunList *r, Lextok *t, Lextok *a, ProcList *p)
+{      int k; int at, ft;
+       RunList *oX = X;
+
+       if (!a)
+               fatal("missing actual parameters: '%s'", p->n->name);
+       if (t->sym->nel != 1)
+               fatal("array in parameter list, %s", t->sym->name);
+       k = eval(a->lft);
+
+       at = Sym_typ(a->lft);
+       X = r;  /* switch context */
+       ft = Sym_typ(t);
+
+       if (at != ft && (at == CHAN || ft == CHAN))
+       {       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)",
+                       p->n->name, tag1, tag2);
+               non_fatal("%s", buf);
+       }
+       t->ntyp = NAME;
+       addsymbol(r, t->sym);
+       (void) setval(t, k);
+       
+       X = oX;
+}
+
+static void
+setparams(RunList *r, ProcList *p, Lextok *q)
+{      Lextok *f, *a;  /* formal and actual pars */
+       Lextok *t;      /* list of pars of 1 type */
+
+       if (q)
+       {       lineno = q->ln;
+               Fname  = q->fn;
+       }
+       for (f = p->p, a = q; f; f = f->rgt) /* one type at a time */
+       for (t = f->lft; t; t = t->rgt, a = (a)?a->rgt:a)
+       {       if (t->ntyp != ',')
+                       oneparam(r, t, a, p);   /* plain var */
+               else
+                       oneparam(r, t->lft, a, p); /* expanded struct */
+       }
+}
+
+Symbol *
+findloc(Symbol *s)
+{      Symbol *r;
+
+       if (!X)
+       {       /* fatal("error, cannot eval '%s' (no proc)", s->name); */
+               return ZS;
+       }
+       for (r = X->symtab; r; r = r->next)
+               if (strcmp(r->name, s->name) == 0)
+                       break;
+       if (!r)
+       {       addsymbol(X, s);
+               r = X->symtab;
+       }
+       return r;
+}
+
+int
+in_bound(Symbol *r, int n)
+{
+       if (!r) return 0;
+
+       if (n >= r->nel || n < 0)
+       {       printf("spin: indexing %s[%d] - size is %d\n",
+                       r->name, n, r->nel);
+               non_fatal("indexing array \'%s\'", r->name);
+               return 0;
+       }
+       return 1;
+}
+
+int
+getlocal(Lextok *sn)
+{      Symbol *r, *s = sn->sym;
+       int n = eval(sn->lft);
+
+       r = findloc(s);
+       if (r && r->type == STRUCT)
+               return Rval_struct(sn, r, 1); /* 1 = check init */
+       if (in_bound(r, n))
+               return cast_val(r->type, r->val[n], r->nbits);
+       return 0;
+}
+
+int
+setlocal(Lextok *p, int m)
+{      Symbol *r = findloc(p->sym);
+       int n = eval(p->lft);
+
+       if (in_bound(r, n))
+       {       if (r->type == STRUCT)
+                       (void) Lval_struct(p, r, 1, m); /* 1 = check init */
+               else
+               {
+#if 0
+                       if (r->nbits > 0)
+                               m = (m & ((1<<r->nbits)-1));
+                       r->val[n] = m;
+#else
+                       r->val[n] = cast_val(r->type, m, r->nbits);
+#endif
+                       r->setat = depth;
+       }       }
+
+       return 1;
+}
+
+void
+whoruns(int lnr)
+{      if (!X) return;
+
+       if (lnr) printf("%3d:   ", depth);
+       printf("proc ");
+       if (Have_claim && X->pid == 0)
+               printf(" -");
+       else
+               printf("%2d", X->pid - Have_claim);
+       printf(" (%s) ", X->n->name);
+}
+
+static void
+talk(RunList *r)
+{
+       if ((verbose&32) || (verbose&4))
+       {       p_talk(r->pc, 1);
+               printf("\n");
+               if (verbose&1) dumpglobals();
+               if (verbose&2) dumplocal(r);
+       }
+}
+
+void
+p_talk(Element *e, int lnr)
+{      static int lastnever = -1;
+       int newnever = -1;
+
+       if (e && e->n)
+               newnever = e->n->ln;
+
+       if (Have_claim && X && X->pid == 0
+       &&  lastnever != newnever && e)
+       {       if (xspin)
+               {       printf("MSC: ~G line %d\n", newnever);
+#if 0
+                       printf("%3d:    proc  - (NEVER) line   %d \"never\" ",
+                               depth, newnever);
+                       printf("(state 0)\t[printf('MSC: never\\\\n')]\n");
+               } else
+               {       printf("%3d:    proc  - (NEVER) line   %d \"never\"\n",
+                               depth, newnever);
+#endif
+               }
+               lastnever = newnever;
+       }
+
+       whoruns(lnr);
+       if (e)
+       {       printf("line %3d %s (state %d)",
+                       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 */
+               {       printf(" <valid end state>");
+               }
+       }
+}
+
+int
+remotelab(Lextok *n)
+{      int i;
+
+       lineno = n->ln;
+       Fname  = n->fn;
+       if (n->sym->type != 0 && n->sym->type != LABEL)
+       {       printf("spin: error, type: %d\n", n->sym->type);
+               fatal("not a labelname: '%s'", n->sym->name);
+       }
+       if (n->indstep >= 0)
+       {       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);
+       return i;
+}
+
+int
+remotevar(Lextok *n)
+{      int prno, i, added=0;
+       RunList *Y, *oX;
+       Lextok *onl;
+       Symbol *os;
+
+       lineno = n->ln;
+       Fname  = n->fn;
+
+       if (!n->lft->lft)
+               prno = f_pid(n->lft->sym->name);
+       else
+       {       prno = eval(n->lft->lft); /* pid - can cause recursive call */
+#if 0
+               if (n->lft->lft->ntyp == CONST) /* user-guessed pid */
+#endif
+               {       prno += Have_claim;
+                       added = Have_claim;
+       }       }
+
+       if (prno < 0)
+               return 0;       /* non-existing process */
+#if 0
+       i = nproc - nstop;
+       for (Y = run; Y; Y = Y->nxt)
+       {       --i;
+               printf("        %s: i=%d, prno=%d, ->pid=%d\n", Y->n->name, i, prno, Y->pid);
+       }
+#endif
+       i = nproc - nstop;
+       for (Y = run; Y; Y = Y->nxt)
+       if (--i == prno)
+       {       if (strcmp(Y->n->name, n->lft->sym->name) != 0)
+               {       printf("spin: remote reference error on '%s[%d]'\n",
+                               n->lft->sym->name, prno-added);
+                       non_fatal("refers to wrong proctype '%s'", Y->n->name);
+               }
+               if (strcmp(n->sym->name, "_p") == 0)
+               {       if (Y->pc)
+                               return Y->pc->seqno;
+                       /* harmless, can only happen with -t */
+                       return 0;
+               }
+#if 1
+               /* new 4.0 allow remote variables */
+               oX = X;
+               X = Y;
+
+               onl = n->lft;
+               n->lft = n->rgt;
+
+               os = n->sym;
+               n->sym = findloc(n->sym);
+
+               i = getval(n);
+
+               n->sym = os;
+               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);
+       printf("have only:\n");
+       i = nproc - nstop - 1;
+       for (Y = run; Y; Y = Y->nxt, i--)
+               if (!strcmp(Y->n->name, n->lft->sym->name))
+               printf("\t%d\t%s\n", i, Y->n->name);
+
+       return 0;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/spin b/trunk/verif/Spin/Src5.1.6/spin
new file mode 100755 (executable)
index 0000000..6b70f42
Binary files /dev/null and b/trunk/verif/Spin/Src5.1.6/spin differ
diff --git a/trunk/verif/Spin/Src5.1.6/spin.h b/trunk/verif/Spin/Src5.1.6/spin.h
new file mode 100755 (executable)
index 0000000..aa55c6f
--- /dev/null
@@ -0,0 +1,404 @@
+/***** spin: spin.h *****/
+
+/* Copyright (c) 1989-2007 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            */
+
+#ifndef SEEN_SPIN_H
+#define SEEN_SPIN_H
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#ifndef PC
+#include <memory.h>
+#endif
+
+typedef struct Lextok {
+       unsigned short  ntyp;   /* node type */
+       short   ismtyp;         /* CONST derived from MTYP */
+       int     val;            /* value attribute */
+       int     ln;             /* line number */
+       int     indstep;        /* part of d_step sequence */
+       struct Symbol   *fn;    /* file name */
+       struct Symbol   *sym;   /* symbol reference */
+        struct Sequence *sq;   /* sequence */
+        struct SeqList *sl;    /* sequence list */
+       struct Lextok   *lft, *rgt; /* children in parse tree */
+} Lextok;
+
+typedef struct Slicer {
+       Lextok  *n;             /* global var, usable as slice criterion */
+       short   code;           /* type of use: DEREF_USE or normal USE */
+       short   used;           /* set when handled */
+       struct Slicer *nxt;     /* linked list */
+} Slicer;
+
+typedef struct Access {
+       struct Symbol   *who;   /* proctype name of accessor */
+       struct Symbol   *what;  /* proctype name of accessed */
+       int     cnt, typ;       /* parameter nr and, e.g., 's' or 'r' */
+       struct Access   *lnk;   /* linked list */
+} Access;
+
+typedef struct Symbol {
+       char    *name;
+       int     Nid;            /* unique number for the name */
+       unsigned short  type;   /* bit,short,.., chan,struct  */
+       unsigned char   hidden; /* bit-flags:
+                                  1=hide, 2=show,
+                                  4=bit-equiv,   8=byte-equiv,
+                                 16=formal par, 32=inline par,
+                                 64=treat as if local; 128=read at least once
+                                */
+       unsigned char   colnr;  /* for use with xspin during simulation */
+       int     nbits;          /* optional width specifier */
+       int     nel;            /* 1 if scalar, >1 if array   */
+       int     setat;          /* last depth value changed   */
+       int     *val;           /* runtime value(s), initl 0  */
+       Lextok  **Sval; /* values for structures */
+
+       int     xu;             /* exclusive r or w by 1 pid  */
+       struct Symbol   *xup[2];  /* xr or xs proctype  */
+       struct Access   *access;/* e.g., senders and receives of chan */
+       Lextok  *ini;   /* initial value, or chan-def */
+       Lextok  *Slst;  /* template for structure if struct */
+       struct Symbol   *Snm;   /* name of the defining struct */
+       struct Symbol   *owner; /* set for names of subfields in typedefs */
+       struct Symbol   *context; /* 0 if global, or procname */
+       struct Symbol   *next;  /* linked list */
+} Symbol;
+
+typedef struct Ordered {       /* links all names in Symbol table */ 
+       struct Symbol   *entry;
+       struct Ordered  *next;
+} Ordered;
+
+typedef struct Queue {
+       short   qid;            /* runtime q index */
+       int     qlen;           /* nr messages stored */
+       int     nslots, nflds;  /* capacity, flds/slot */
+       int     setat;          /* last depth value changed */
+       int     *fld_width;     /* type of each field */
+       int     *contents;      /* the values stored */
+       int     *stepnr;        /* depth when each msg was sent */
+       struct Queue    *nxt;   /* linked list */
+} Queue;
+
+typedef struct FSM_state {     /* used in pangen5.c - dataflow */
+       int from;               /* state number */
+       int seen;               /* used for dfs */
+       int in;                 /* nr of incoming edges */
+       int cr;                 /* has reachable 1-relevant successor */
+       int scratch;
+       unsigned long *dom, *mod; /* to mark dominant nodes */
+       struct FSM_trans *t;    /* outgoing edges */
+       struct FSM_trans *p;    /* incoming edges, predecessors */
+       struct FSM_state *nxt;  /* linked list of all states */
+} FSM_state;
+
+typedef struct FSM_trans {     /* used in pangen5.c - dataflow */
+       int to;
+       short   relevant;       /* when sliced */
+       short   round;          /* ditto: iteration when marked */
+       struct FSM_use *Val[2]; /* 0=reads, 1=writes */
+       struct Element *step;
+       struct FSM_trans *nxt;
+} FSM_trans;
+
+typedef struct FSM_use {       /* used in pangen5.c - dataflow */
+       Lextok *n;
+       Symbol *var;
+       int special;
+       struct FSM_use *nxt;
+} FSM_use;
+
+typedef struct Element {
+       Lextok  *n;             /* defines the type & contents */
+       int     Seqno;          /* identifies this el within system */
+       int     seqno;          /* identifies this el within a proc */
+       int     merge;          /* set by -O if step can be merged */
+       int     merge_start;
+       int     merge_single;
+       short   merge_in;       /* nr of incoming edges */
+       short   merge_mark;     /* state was generated in merge sequence */
+       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 */
+       struct Element  *Nxt;   /* linked list - for global lookup */
+       struct Element  *nxt;   /* linked list - program structure */
+} Element;
+
+typedef struct Sequence {
+       Element *frst;
+       Element *last;          /* links onto continuations */
+       Element *extent;        /* last element in original */
+       int     maxel;          /* 1+largest id in sequence */
+} Sequence;
+
+typedef struct SeqList {
+       Sequence        *this;  /* one sequence */
+       struct SeqList  *nxt;   /* linked list  */
+} SeqList;
+
+typedef struct Label {
+       Symbol  *s;
+       Symbol  *c;
+       Element *e;
+       int     visible;        /* label referenced in claim (slice relevant) */
+       struct Label    *nxt;
+} Label;
+
+typedef struct Lbreak {
+       Symbol  *l;
+       struct Lbreak   *nxt;
+} Lbreak;
+
+typedef struct RunList {
+       Symbol  *n;             /* name            */
+       int     tn;             /* ordinal of type */
+       int     pid;            /* process id      */
+       int     priority;       /* for simulations only */
+       Element *pc;            /* current stmnt   */
+       Sequence *ps;           /* used by analyzer generator */
+       Lextok  *prov;          /* provided clause */
+       Symbol  *symtab;        /* local variables */
+       struct RunList  *nxt;   /* linked list */
+} RunList;
+
+typedef struct ProcList {
+       Symbol  *n;             /* name       */
+       Lextok  *p;             /* parameters */
+       Sequence *s;            /* body       */
+       Lextok  *prov;          /* provided clause */
+       short   tn;             /* ordinal number */
+       unsigned char   det;    /* deterministic */
+       unsigned char   unsafe; /* contains global var inits */
+       struct ProcList *nxt;   /* linked list */
+} ProcList;
+
+typedef        Lextok *Lexptr;
+
+#define YYSTYPE        Lexptr
+
+#define ZN     (Lextok *)0
+#define ZS     (Symbol *)0
+#define ZE     (Element *)0
+
+#define DONE     1             /* status bits of elements */
+#define ATOM     2             /* part of an atomic chain */
+#define L_ATOM   4             /* last element in a chain */
+#define I_GLOB    8            /* inherited global ref    */
+#define DONE2   16             /* used in putcode and main*/
+#define D_ATOM  32             /* deterministic atomic    */
+#define ENDSTATE 64            /* normal endstate         */
+#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 */
+
+#define XR             1       /* non-shared receive-only */
+#define XS             2       /* non-shared send-only    */
+#define XX             4       /* overrides XR or XS tag  */
+
+#define CODE_FRAG      2       /* auto-numbered code-fragment */
+#define CODE_DECL      4       /* auto-numbered c_decl */
+#define PREDEF         3       /* predefined name: _p, _last */
+
+#define UNSIGNED  5            /* val defines width in bits */
+#define BIT      1             /* also equal to width in bits */
+#define BYTE     8             /* ditto */
+#define SHORT   16             /* ditto */
+#define INT     32             /* ditto */
+#define        CHAN     64             /* not */
+#define STRUCT 128             /* user defined structure name */
+
+#define SOMETHINGBIG   65536
+#define RATHERSMALL    512
+
+#ifndef max
+#define max(a,b) (((a)<(b)) ? (b) : (a))
+#endif
+
+enum   { INIV, PUTV, LOGV };   /* for pangen[14].c */
+
+/***** prototype definitions *****/
+Element        *eval_sub(Element *);
+Element        *get_lab(Lextok *, int);
+Element        *huntele(Element *, int, int);
+Element        *huntstart(Element *);
+Element        *target(Element *);
+
+Lextok *do_unless(Lextok *, Lextok *);
+Lextok *expand(Lextok *, int);
+Lextok *getuname(Symbol *);
+Lextok *mk_explicit(Lextok *, int, int);
+Lextok *nn(Lextok *, int, Lextok *, Lextok *);
+Lextok *rem_lab(Symbol *, Lextok *, Symbol *);
+Lextok *rem_var(Symbol *, Lextok *, Symbol *, Lextok *);
+Lextok *tail_add(Lextok *, Lextok *);
+
+ProcList *ready(Symbol *, Lextok *, Sequence *, int, Lextok *);
+
+SeqList        *seqlist(Sequence *, SeqList *);
+Sequence *close_seq(int);
+
+Symbol *break_dest(void);
+Symbol *findloc(Symbol *);
+Symbol *has_lab(Element *, int);
+Symbol *lookup(char *);
+Symbol *prep_inline(Symbol *, Lextok *);
+
+char   *emalloc(size_t);
+long   Rand(void);
+
+int    any_oper(Lextok *, int);
+int    any_undo(Lextok *);
+int    c_add_sv(FILE *);
+int    cast_val(int, int, int);
+int    checkvar(Symbol *, int);
+int    Cnt_flds(Lextok *);
+int    cnt_mpars(Lextok *);
+int    complete_rendez(void);
+int    enable(Lextok *);
+int    Enabled0(Element *);
+int    eval(Lextok *);
+int    find_lab(Symbol *, Symbol *, int);
+int    find_maxel(Symbol *);
+int    full_name(FILE *, Lextok *, Symbol *, int);
+int    getlocal(Lextok *);
+int    getval(Lextok *);
+int    glob_inline(char *);
+int    has_typ(Lextok *, int);
+int    in_bound(Symbol *, int);
+int    interprint(FILE *, Lextok *);
+int    printm(FILE *, Lextok *);
+int    ismtype(char *);
+int    isproctype(char *);
+int    isutype(char *);
+int    Lval_struct(Lextok *, Symbol *, int, int);
+int    main(int, char **);
+int    pc_value(Lextok *);
+int    proper_enabler(Lextok *);
+int    putcode(FILE *, Sequence *, Element *, int, int, int);
+int    q_is_sync(Lextok *);
+int    qlen(Lextok *);
+int    qfull(Lextok *);
+int    qmake(Symbol *);
+int    qrecv(Lextok *, int);
+int    qsend(Lextok *);
+int    remotelab(Lextok *);
+int    remotevar(Lextok *);
+int    Rval_struct(Lextok *, Symbol *, int);
+int    setlocal(Lextok *, int);
+int    setval(Lextok *, int);
+int    sputtype(char *, int);
+int    Sym_typ(Lextok *);
+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);
+void   add_seq(Lextok *);
+void   alldone(int);
+void   announce(char *);
+void   c_state(Symbol *, Symbol *, Symbol *);
+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 *);
+void   c_track(Symbol *, Symbol *, Symbol *);
+void   c_var(FILE *, char *, Symbol *);
+void   c_wrapper(FILE *);
+void   chanaccess(void);
+void   check_param_count(int, Lextok *);
+void   checkrun(Symbol *, int);
+void   comment(FILE *, Lextok *, int);
+void   cross_dsteps(Lextok *, Lextok *);
+void   doq(Symbol *, int, RunList *);
+void   dotag(FILE *, char *);
+void   do_locinits(FILE *);
+void   do_var(FILE *, int, char *, Symbol *, char *, char *, char *);
+void   dump_struct(Symbol *, char *, RunList *);
+void   dumpclaims(FILE *, int, char *);
+void   dumpglobals(void);
+void   dumplabels(void);
+void   dumplocal(RunList *);
+void   dumpsrc(int, int);
+void   fatal(char *, char *);
+void   fix_dest(Symbol *, Symbol *);
+void   genaddproc(void);
+void   genaddqueue(void);
+void   gencodetable(FILE *);
+void   genheader(void);
+void   genother(void);
+void   gensrc(void);
+void   gensvmap(void);
+void   genunio(void);
+void   ini_struct(Symbol *);
+void   loose_ends(void);
+void   make_atomic(Sequence *, int);
+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   open_seq(int);
+void   p_talk(Element *, int);
+void   pickup_inline(Symbol *, Lextok *);
+void   plunk_c_decls(FILE *);
+void   plunk_c_fcts(FILE *);
+void   plunk_expr(FILE *, char *);
+void   plunk_inline(FILE *, char *, int);
+void   prehint(Symbol *);
+void   preruse(FILE *, Lextok *);
+void   prune_opts(Lextok *);
+void   pstext(int, char *);
+void   pushbreak(void);
+void   putname(FILE *, char *, Lextok *, int, char *);
+void   putremote(FILE *, Lextok *, int);
+void   putskip(int);
+void   putsrc(Element *);
+void   putstmnt(FILE *, Lextok *, int);
+void   putunames(FILE *);
+void   rem_Seq(void);
+void   runnable(ProcList *, int, int);
+void   sched(void);
+void   setaccess(Symbol *, Symbol *, int, int);
+void   set_lab(Symbol *, Element *);
+void   setmtype(Lextok *);
+void   setpname(Lextok *);
+void   setptype(Lextok *, int, Lextok *);
+void   setuname(Lextok *);
+void   setutype(Lextok *, Symbol *, Lextok *);
+void   setxus(Lextok *, int);
+void   Srand(unsigned);
+void   start_claim(int);
+void   struct_name(Lextok *, Symbol *, int, char *);
+void   symdump(void);
+void   symvar(Symbol *);
+void   trackchanuse(Lextok *, Lextok *, int);
+void   trackvar(Lextok *, Lextok *);
+void   trackrun(Lextok *);
+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 *, ...);
+#endif
diff --git a/trunk/verif/Spin/Src5.1.6/spin.y b/trunk/verif/Spin/Src5.1.6/spin.y
new file mode 100755 (executable)
index 0000000..3d6cb77
--- /dev/null
@@ -0,0 +1,731 @@
+/***** 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            */
+
+%{
+#include "spin.h"
+#include <stdarg.h>
+
+#define YYDEBUG        0
+#define Stop   nn(ZN,'@',ZN,ZN)
+
+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 void    count_runs(Lextok *);
+extern void    no_internals(Lextok *);
+extern void    any_runs(Lextok *);
+extern void    validref(Lextok *, Lextok *);
+extern char    yytext[];
+
+int    Mpars = 0;      /* max nr of message parameters  */
+int    Expand_Ok = 0, realread = 1, IArgs = 0, NamesNotAdded = 0;
+char   *claimproc = (char *) 0;
+char   *eventmap = (char *) 0;
+
+static int     Embedded = 0, inEventMap = 0, has_ini = 0;
+
+%}
+
+%token ASSERT PRINT PRINTM
+%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 ATOMIC NON_ATOMIC D_STEP UNLESS
+%token  TIMEOUT NONPROGRESS
+%token ACTIVE PROCTYPE D_PROCTYPE
+%token HIDDEN SHOW ISLOCAL
+%token PRIORITY PROVIDED
+%token FULL EMPTY NFULL NEMPTY
+%token CONST TYPE XU                   /* val */
+%token NAME UNAME PNAME INAME          /* sym */
+%token STRING CLAIM TRACE INIT         /* sym */
+
+%right ASGN
+%left  SND O_SND RCV R_RCV /* SND doubles as boolean negation */
+%left  OR
+%left  AND
+%left  '|'
+%left  '^'
+%left  '&'
+%left  EQ NE
+%left  GT LT GE LE
+%left  LSHIFT RSHIFT
+%left  '+' '-'
+%left  '*' '/' '%'
+%left  INCR DECR
+%right '~' UMIN NEG
+%left  DOT
+%%
+
+/** PROMELA Grammar Rules **/
+
+program        : units         { yytext[0] = '\0'; }
+       ;
+
+units  : unit
+       | units unit
+       ;
+
+unit   : proc          /* proctype { }       */
+       | init          /* init { }           */
+       | claim         /* never claim        */
+       | events        /* event assertions   */
+       | one_decl      /* variables, chans   */
+       | utype         /* user defined types */
+       | c_fcts        /* c functions etc.   */
+       | ns            /* named sequence     */
+       | SEMI          /* optional separator */
+       | error
+       ;
+
+proc   : inst          /* optional instantiator */
+         proctype NAME {
+                         setptype($3, PROCTYPE, ZN);
+                         setpname($3);
+                         context = $3->sym;
+                         context->ini = $2; /* linenr and file */
+                         Expand_Ok++; /* expand struct names in decl */
+                         has_ini = 0;
+                       }
+         '(' decl ')'  { Expand_Ok--;
+                         if (has_ini)
+                         fatal("initializer in parameter list", (char *) 0);
+                       }
+         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;
+                               for (j = 0; j < $1->val; j++)
+                               runnable(rl, $9?$9->val:1, 1);
+                               announce(":root:");
+                               if (dumptab) $3->sym->ini = $1;
+                         }
+                         if (rl && has_ini == 1)       /* global initializations, unsafe */
+                         {     /* printf("proctype %s has initialized data\n",
+                                       $3->sym->name);
+                                */
+                               rl->unsafe = 1;
+                         }
+                         context = ZS;
+                       }
+       ;
+
+proctype: PROCTYPE     { $$ = nn(ZN,CONST,ZN,ZN); $$->val = 0; }
+       | D_PROCTYPE    { $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
+       ;
+
+inst   : /* empty */   { $$ = ZN; }
+       | ACTIVE        { $$ = nn(ZN,CONST,ZN,ZN); $$->val = 1; }
+       | ACTIVE '[' CONST ']' {
+                         $$ = nn(ZN,CONST,ZN,ZN); $$->val = $3->val;
+                         if ($3->val > 255)
+                               non_fatal("max nr of processes is 255\n", "");
+                       }
+       | ACTIVE '[' NAME ']' {
+                         $$ = nn(ZN,CONST,ZN,ZN);
+                         $$->val = 0;
+                         if (!$3->sym->type)
+                               non_fatal("undeclared variable %s",
+                                       $3->sym->name);
+                         else if ($3->sym->ini->ntyp != CONST)
+                               non_fatal("need constant initializer for %s\n",
+                                       $3->sym->name);
+                         else
+                               $$->val = $3->sym->ini->val;
+                       }
+       ;
+
+init   : INIT          { context = $1->sym; }
+         Opt_priority
+         body          { ProcList *rl;
+                         rl = ready(context, ZN, $4->sq, 0, ZN);
+                         runnable(rl, $3?$3->val:1, 1);
+                         announce(":root:");
+                         context = ZS;
+                       }
+       ;
+
+claim  : CLAIM         { context = $1->sym;
+                         if (claimproc)
+                               non_fatal("claim %s redefined", claimproc);
+                         claimproc = $1->sym->name;
+                       }
+         body          { (void) ready($1->sym, ZN, $3->sq, 0, ZN);
+                         context = ZS;
+                       }
+       ;
+
+events : TRACE         { context = $1->sym;
+                         if (eventmap)
+                               non_fatal("trace %s redefined", eventmap);
+                         eventmap = $1->sym->name;
+                         inEventMap++;
+                       }
+         body          { (void) ready($1->sym, ZN, $3->sq, 0, ZN);
+                         context = ZS;
+                         inEventMap--;
+                       }
+       ;
+
+utype  : TYPEDEF NAME          { if (context)
+                                  fatal("typedef %s must be global",
+                                               $2->sym->name);
+                                  owner = $2->sym;
+                               }
+         '{' decl_lst '}'      { setuname($5); owner = ZS; }
+       ;
+
+nm     : NAME                  { $$ = $1; }
+       | INAME                 { $$ = $1;
+                                 if (IArgs)
+                                 fatal("invalid use of '%s'", $1->sym->name);
+                               }
+       ;
+
+ns     : INLINE nm '('         { NamesNotAdded++; }
+         args ')'              { prep_inline($2->sym, $5);
+                                 NamesNotAdded--;
+                               }
+       ;
+
+c_fcts : ccode                 { /* leaves pseudo-inlines with sym of
+                                  * type CODE_FRAG or CODE_DECL in global context
+                                  */
+                               }
+       | cstate
+       ;
+
+cstate : C_STATE STRING STRING {
+                                 c_state($2->sym, $3->sym, ZS);
+                                 has_code = has_state = 1;
+                               }
+       | C_TRACK STRING STRING {
+                                 c_track($2->sym, $3->sym, ZS);
+                                 has_code = has_state = 1;
+                               }
+       | C_STATE STRING STRING STRING {
+                                 c_state($2->sym, $3->sym, $4->sym);
+                                 has_code = has_state = 1;
+                               }
+       | C_TRACK STRING STRING STRING {
+                                 c_track($2->sym, $3->sym, $4->sym);
+                                 has_code = has_state = 1;
+                               }
+       ;
+
+ccode  : C_CODE                { Symbol *s;
+                                 NamesNotAdded++;
+                                 s = prep_inline(ZS, ZN);
+                                 NamesNotAdded--;
+                                 $$ = nn(ZN, C_CODE, ZN, ZN);
+                                 $$->sym = s;
+                                 has_code = 1;
+                               }
+       | C_DECL                { Symbol *s;
+                                 NamesNotAdded++;
+                                 s = prep_inline(ZS, ZN);
+                                 NamesNotAdded--;
+                                 s->type = CODE_DECL;
+                                 $$ = nn(ZN, C_CODE, ZN, ZN);
+                                 $$->sym = s;
+                                 has_code = 1;
+                               }
+       ;
+cexpr  : C_EXPR                { Symbol *s;
+                                 NamesNotAdded++;
+                                 s = prep_inline(ZS, ZN);
+                                 NamesNotAdded--;
+                                 $$ = nn(ZN, C_EXPR, ZN, ZN);
+                                 $$->sym = s;
+                                 no_side_effects(s->name);
+                                 has_code = 1;
+                               }
+       ;
+
+body   : '{'                   { open_seq(1); }
+          sequence OS          { add_seq(Stop); }
+          '}'                  { $$->sq = close_seq(0); }
+       ;
+
+sequence: step                 { if ($1) add_seq($1); }
+       | sequence MS step      { if ($3) add_seq($3); }
+       ;
+
+step    : one_decl             { $$ = ZN; }
+       | XU vref_lst           { setxus($2, $1->val); $$ = ZN; }
+       | 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); }
+       ;
+
+vis    : /* empty */           { $$ = ZN; }
+       | HIDDEN                { $$ = $1; }
+       | SHOW                  { $$ = $1; }
+       | ISLOCAL               { $$ = $1; }
+       ;
+
+asgn:  /* empty */
+       | ASGN
+       ;
+
+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);
+                               }
+       | vis TYPE asgn '{' nlst '}' {
+                                 if ($2->val != MTYPE)
+                                       fatal("malformed declaration", 0);
+                                 setmtype($5);
+                                 if ($1)
+                                       non_fatal("cannot %s mtype (ignored)",
+                                               $1->sym->name);
+                                 if (context != ZS)
+                                       fatal("mtype declaration must be global", 0);
+                               }
+       ;
+
+decl_lst: one_decl             { $$ = nn(ZN, ',', $1, ZN); }
+       | one_decl SEMI
+         decl_lst              { $$ = nn(ZN, ',', $1, $3); }
+       ;
+
+decl    : /* empty */          { $$ = ZN; }
+       | decl_lst              { $$ = $1; }
+       ;
+
+vref_lst: varref               { $$ = nn($1, XU, $1, ZN); }
+       | varref ',' vref_lst   { $$ = nn($1, XU, $1, $3); }
+       ;
+
+var_list: ivar                 { $$ = nn($1, TYPE, ZN, ZN); }
+       | ivar ',' var_list     { $$ = nn($1, TYPE, ZN, $3); }
+       ;
+
+ivar    : vardcl               { $$ = $1;
+                                 $1->sym->ini = nn(ZN,CONST,ZN,ZN);
+                                 $1->sym->ini->val = 0;
+                               }
+       | vardcl ASGN expr      { $1->sym->ini = $3; $$ = $1;
+                                 trackvar($1,$3);
+                                 if ($3->ntyp == CONST
+                                 || ($3->ntyp == NAME && $3->sym->context))
+                                 {     has_ini = 2; /* local init */
+                                 } else
+                                 {     has_ini = 1; /* possibly global */
+                                 }
+                               }
+       | vardcl ASGN ch_init   { $1->sym->ini = $3;
+                                 $$ = $1; has_ini = 1;
+                               }
+       ;
+
+ch_init : '[' CONST ']' 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;
+                               }
+       ;
+
+vardcl  : NAME                 { $1->sym->nel = 1; $$ = $1; }
+       | NAME ':' CONST        { $1->sym->nbits = $3->val;
+                                 if ($3->val >= 8*sizeof(long))
+                                 {     non_fatal("width-field %s too large",
+                                               $1->sym->name);
+                                       $3->val = 8*sizeof(long)-1;
+                                 }
+                                 $1->sym->nel = 1; $$ = $1;
+                               }
+       | NAME '[' CONST ']'    { $1->sym->nel = $3->val; $$ = $1; }
+       ;
+
+varref : cmpnd                 { $$ = mk_explicit($1, Expand_Ok, NAME); }
+       ;
+
+pfld   : NAME                  { $$ = nn($1, NAME, ZN, ZN); }
+       | NAME                  { owner = ZS; }
+         '[' expr ']'          { $$ = nn($1, NAME, $4, ZN); }
+       ;
+
+cmpnd  : pfld                  { Embedded++;
+                                 if ($1->sym->type == STRUCT)
+                                       owner = $1->sym->Snm;
+                               }
+         sfld                  { $$ = $1; $$->rgt = $3;
+                                 if ($3 && $1->sym->type != STRUCT)
+                                       $1->sym->type = STRUCT;
+                                 Embedded--;
+                                 if (!Embedded && !NamesNotAdded
+                                 &&  !$1->sym->type)
+                                  non_fatal("undeclared variable: %s",
+                                               $1->sym->name);
+                                 if ($3) validref($1, $3->lft);
+                                 owner = ZS;
+                               }
+       ;
+
+sfld   : /* empty */           { $$ = ZN; }
+       | '.' cmpnd %prec DOT   { $$ = nn(ZN, '.', $2, ZN); }
+       ;
+
+stmnt  : Special               { $$ = $1; }
+       | Stmnt                 { $$ = $1;
+                                 if (inEventMap)
+                                  non_fatal("not an event", (char *)0);
+                               }
+       ;
+
+Special : varref RCV           { Expand_Ok++; }
+         rargs                 { Expand_Ok--; has_io++;
+                                 $$ = nn($1,  'r', $1, $4);
+                                 trackchanuse($4, ZN, 'R');
+                               }
+       | varref SND            { Expand_Ok++; }
+         margs                 { Expand_Ok--; has_io++;
+                                 $$ = nn($1, 's', $1, $4);
+                                 $$->val=0; trackchanuse($4, ZN, 'S');
+                                 any_runs($4);
+                               }
+       | IF options FI         { $$ = nn($1, IF, ZN, ZN);
+                                 $$->sl = $2->sl;
+                                 prune_opts($$);
+                               }
+       | DO                    { pushbreak(); }
+          options OD           { $$ = nn($1, DO, ZN, ZN);
+                                 $$->sl = $3->sl;
+                                 prune_opts($$);
+                               }
+       | BREAK                 { $$ = nn(ZN, GOTO, ZN, ZN);
+                                 $$->sym = break_dest();
+                               }
+       | GOTO NAME             { $$ = nn($2, GOTO, ZN, ZN);
+                                 if ($2->sym->type != 0
+                                 &&  $2->sym->type != LABEL) {
+                                       non_fatal("bad label-name %s",
+                                       $2->sym->name);
+                                 }
+                                 $2->sym->type = LABEL;
+                               }
+       | NAME ':' stmnt        { $$ = nn($1, ':',$3, ZN);
+                                 if ($1->sym->type != 0
+                                 &&  $1->sym->type != LABEL) {
+                                       non_fatal("bad label-name %s",
+                                       $1->sym->name);
+                                 }
+                                 $1->sym->type = LABEL;
+                               }
+       ;
+
+Stmnt  : varref ASGN expr      { $$ = nn($1, ASGN, $1, $3);
+                                 trackvar($1, $3);
+                                 nochan_manip($1, $3, 0);
+                                 no_internals($1);
+                               }
+       | varref INCR           { $$ = nn(ZN,CONST, ZN, ZN); $$->val = 1;
+                                 $$ = nn(ZN,  '+', $1, $$);
+                                 $$ = nn($1, ASGN, $1, $$);
+                                 trackvar($1, $1);
+                                 no_internals($1);
+                                 if ($1->sym->type == CHAN)
+                                  fatal("arithmetic on chan", (char *)0);
+                               }
+       | varref DECR           { $$ = nn(ZN,CONST, ZN, ZN); $$->val = 1;
+                                 $$ = nn(ZN,  '-', $1, $$);
+                                 $$ = nn($1, ASGN, $1, $$);
+                                 trackvar($1, $1);
+                                 no_internals($1);
+                                 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); }
+       | ASSERT full_expr      { $$ = nn(ZN, ASSERT, $2, ZN); AST_track($2, 0); }
+       | ccode                 { $$ = $1; }
+       | varref R_RCV          { Expand_Ok++; }
+         rargs                 { Expand_Ok--; has_io++;
+                                 $$ = nn($1,  'r', $1, $4);
+                                 $$->val = has_random = 1;
+                                 trackchanuse($4, ZN, 'R');
+                               }
+       | varref RCV            { Expand_Ok++; }
+         LT rargs GT           { Expand_Ok--; has_io++;
+                                 $$ = nn($1, 'r', $1, $5);
+                                 $$->val = 2;  /* fifo poll */
+                                 trackchanuse($5, ZN, 'R');
+                               }
+       | varref R_RCV          { Expand_Ok++; }
+         LT rargs GT           { Expand_Ok--; has_io++;        /* rrcv poll */
+                                 $$ = nn($1, 'r', $1, $5);
+                                 $$->val = 3; has_random = 1;
+                                 trackchanuse($5, ZN, 'R');
+                               }
+       | varref O_SND          { Expand_Ok++; }
+         margs                 { Expand_Ok--; has_io++;
+                                 $$ = nn($1, 's', $1, $4);
+                                 $$->val = has_sorted = 1;
+                                 trackchanuse($4, ZN, 'S');
+                                 any_runs($4);
+                               }
+       | full_expr             { $$ = nn(ZN, 'c', $1, ZN); count_runs($$); }
+       | ELSE                  { $$ = nn(ZN,ELSE,ZN,ZN);
+                               }
+       | ATOMIC   '{'          { open_seq(0); }
+          sequence OS '}'      { $$ = nn($1, ATOMIC, ZN, ZN);
+                                 $$->sl = seqlist(close_seq(3), 0);
+                                 make_atomic($$->sl->this, 0);
+                               }
+       | D_STEP '{'            { open_seq(0); rem_Seq(); }
+          sequence OS '}'      { $$ = nn($1, D_STEP, ZN, ZN);
+                                 $$->sl = seqlist(close_seq(4), 0);
+                                 make_atomic($$->sl->this, D_ATOM);
+                                 unrem_Seq();
+                               }
+       | '{'                   { open_seq(0); }
+         sequence OS '}'       { $$ = nn(ZN, NON_ATOMIC, ZN, ZN);
+                                 $$->sl = seqlist(close_seq(5), 0);
+                               }
+       | INAME                 { IArgs++; }
+         '(' args ')'          { pickup_inline($1->sym, $4); IArgs--; }
+         Stmnt                 { $$ = $7; }
+       ;
+
+options : option               { $$->sl = seqlist($1->sq, 0); }
+       | option options        { $$->sl = seqlist($1->sq, $2->sl); }
+       ;
+
+option  : SEP                  { open_seq(0); }
+          sequence OS          { $$ = nn(ZN,0,ZN,ZN);
+                                 $$->sq = close_seq(6); }
+       ;
+
+OS     : /* empty */
+       | SEMI                  { /* redundant semi at end of sequence */ }
+       ;
+
+MS     : SEMI                  { /* at least one semi-colon */ }
+       | MS SEMI               { /* but more are okay too   */ }
+       ;
+
+aname  : NAME                  { $$ = $1; }
+       | PNAME                 { $$ = $1; }
+       ;
+
+expr    : '(' expr ')'         { $$ = $2; }
+       | expr '+' expr         { $$ = nn(ZN, '+', $1, $3); }
+       | expr '-' expr         { $$ = nn(ZN, '-', $1, $3); }
+       | expr '*' expr         { $$ = nn(ZN, '*', $1, $3); }
+       | expr '/' expr         { $$ = nn(ZN, '/', $1, $3); }
+       | expr '%' expr         { $$ = nn(ZN, '%', $1, $3); }
+       | expr '&' expr         { $$ = nn(ZN, '&', $1, $3); }
+       | expr '^' expr         { $$ = nn(ZN, '^', $1, $3); }
+       | expr '|' expr         { $$ = nn(ZN, '|', $1, $3); }
+       | expr GT expr          { $$ = nn(ZN,  GT, $1, $3); }
+       | expr LT expr          { $$ = nn(ZN,  LT, $1, $3); }
+       | expr GE expr          { $$ = nn(ZN,  GE, $1, $3); }
+       | expr LE expr          { $$ = nn(ZN,  LE, $1, $3); }
+       | expr EQ expr          { $$ = nn(ZN,  EQ, $1, $3); }
+       | expr NE expr          { $$ = nn(ZN,  NE, $1, $3); }
+       | expr AND expr         { $$ = nn(ZN, AND, $1, $3); }
+       | expr OR  expr         { $$ = nn(ZN,  OR, $1, $3); }
+       | expr LSHIFT expr      { $$ = nn(ZN, LSHIFT,$1, $3); }
+       | expr RSHIFT expr      { $$ = nn(ZN, RSHIFT,$1, $3); }
+       | '~' expr              { $$ = nn(ZN, '~', $2, ZN); }
+       | '-' expr %prec UMIN   { $$ = nn(ZN, UMIN, $2, ZN); }
+       | SND expr %prec NEG    { $$ = nn(ZN, '!', $2, ZN); }
+
+       | '(' expr SEMI expr ':' expr ')' {
+                                 $$ = nn(ZN,  OR, $4, $6);
+                                 $$ = nn(ZN, '?', $2, $$);
+                               }
+
+       | RUN aname             { Expand_Ok++;
+                                 if (!context)
+                                  fatal("used 'run' outside proctype",
+                                       (char *) 0);
+                               }
+         '(' args ')'
+         Opt_priority          { Expand_Ok--;
+                                 $$ = nn($2, RUN, $5, ZN);
+                                 $$->val = ($7) ? $7->val : 1;
+                                 trackchanuse($5, $2, 'A'); trackrun($$);
+                               }
+       | LEN '(' varref ')'    { $$ = nn($3, LEN, $3, ZN); }
+       | ENABLED '(' expr ')'  { $$ = nn(ZN, ENABLED, $3, ZN);
+                                 has_enabled++;
+                               }
+       | varref RCV            { Expand_Ok++; }
+         '[' rargs ']'         { Expand_Ok--; has_io++;
+                                 $$ = nn($1, 'R', $1, $5);
+                               }
+       | varref R_RCV          { Expand_Ok++; }
+         '[' rargs ']'         { Expand_Ok--; has_io++;
+                                 $$ = nn($1, 'R', $1, $5);
+                                 $$->val = has_random = 1;
+                               }
+       | varref                { $$ = $1; trapwonly($1 /*, "varref" */); }
+       | cexpr                 { $$ = $1; }
+       | CONST                 { $$ = nn(ZN,CONST,ZN,ZN);
+                                 $$->ismtyp = $1->ismtyp;
+                                 $$->val = $1->val;
+                               }
+       | TIMEOUT               { $$ = nn(ZN,TIMEOUT, ZN, ZN); }
+       | NONPROGRESS           { $$ = nn(ZN,NONPROGRESS, ZN, ZN);
+                                 has_np++;
+                               }
+       | PC_VAL '(' expr ')'   { $$ = nn(ZN, PC_VAL, $3, ZN);
+                                 has_pcvalue++;
+                               }
+       | PNAME '[' expr ']' '@' NAME
+                               { $$ = rem_lab($1->sym, $3, $6->sym); }
+       | PNAME '[' expr ']' ':' pfld
+                               { $$ = 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); }
+       ;
+
+Opt_priority:  /* none */      { $$ = ZN; }
+       | PRIORITY CONST        { $$ = $2; }
+       ;
+
+full_expr:     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);
+                               }
+       ;
+
+       /* an Expr cannot be negated - to protect Probe expressions */
+Expr   : Probe                 { $$ = $1; }
+       | '(' Expr ')'          { $$ = $2; }
+       | 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); }
+       ;
+
+basetype: TYPE                 { $$->sym = ZS;
+                                 $$->val = $1->val;
+                                 if ($$->val == UNSIGNED)
+                                 fatal("unsigned cannot be used as mesg type", 0);
+                               }
+       | UNAME                 { $$->sym = $1->sym;
+                                 $$->val = STRUCT;
+                               }
+       | error                 /* e.g., unsigned ':' const */
+       ;
+
+typ_list: basetype             { $$ = nn($1, $1->val, ZN, ZN); }
+       | basetype ',' typ_list { $$ = nn($1, $1->val, ZN, $3); }
+       ;
+
+args    : /* empty */          { $$ = ZN; }
+       | arg                   { $$ = $1; }
+       ;
+
+prargs  : /* empty */          { $$ = ZN; }
+       | ',' arg               { $$ = $2; }
+       ;
+
+margs   : arg                  { $$ = $1; }
+       | expr '(' arg ')'      { if ($1->ntyp == ',')
+                                       $$ = tail_add($1, $3);
+                                 else
+                                       $$ = nn(ZN, ',', $1, $3);
+                               }
+       ;
+
+arg     : expr                 { if ($1->ntyp == ',')
+                                       $$ = $1;
+                                 else
+                                       $$ = nn(ZN, ',', $1, ZN);
+                               }
+       | expr ',' arg          { if ($1->ntyp == ',')
+                                       $$ = tail_add($1, $3);
+                                 else
+                                       $$ = nn(ZN, ',', $1, $3);
+                               }
+       ;
+
+rarg   : varref                { $$ = $1; trackvar($1, $1);
+                                 trapwonly($1 /*, "rarg" */); }
+       | EVAL '(' expr ')'     { $$ = nn(ZN,EVAL,$3,ZN);
+                                 trapwonly($1 /*, "eval rarg" */); }
+       | CONST                 { $$ = nn(ZN,CONST,ZN,ZN);
+                                 $$->ismtyp = $1->ismtyp;
+                                 $$->val = $1->val;
+                               }
+       | '-' CONST %prec UMIN  { $$ = nn(ZN,CONST,ZN,ZN);
+                                 $$->val = - ($2->val);
+                               }
+       ;
+
+rargs  : rarg                  { if ($1->ntyp == ',')
+                                       $$ = $1;
+                                 else
+                                       $$ = nn(ZN, ',', $1, ZN);
+                               }
+       | rarg ',' rargs        { if ($1->ntyp == ',')
+                                       $$ = tail_add($1, $3);
+                                 else
+                                       $$ = nn(ZN, ',', $1, $3);
+                               }
+       | rarg '(' rargs ')'    { if ($1->ntyp == ',')
+                                       $$ = tail_add($1, $3);
+                                 else
+                                       $$ = nn(ZN, ',', $1, $3);
+                               }
+       | '(' rargs ')'         { $$ = $2; }
+       ;
+
+nlst   : NAME                  { $$ = nn($1, NAME, ZN, ZN);
+                                 $$ = nn(ZN, ',', $$, ZN); }
+       | nlst NAME             { $$ = nn($2, NAME, ZN, ZN);
+                                 $$ = nn(ZN, ',', $$, $1);
+                               }
+       | nlst ','              { $$ = $1; /* commas optional */ }
+       ;
+%%
+
+void
+yyerror(char *fmt, ...)
+{
+       non_fatal(fmt, (char *) 0);
+}
diff --git a/trunk/verif/Spin/Src5.1.6/spinlex.c b/trunk/verif/Spin/Src5.1.6/spinlex.c
new file mode 100755 (executable)
index 0000000..9265c87
--- /dev/null
@@ -0,0 +1,1405 @@
+/***** 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            */
+
+#include <stdlib.h>
+#include "spin.h"
+#include "y.tab.h"
+
+#define MAXINL 16      /* max recursion depth inline fcts */
+#define MAXPAR 32      /* max params to an inline call */
+#define MAXLEN 512     /* max len of an actual parameter text */
+
+typedef struct IType {
+       Symbol *nm;             /* name of the type */
+       Lextok *cn;             /* contents */
+       Lextok *params;         /* formal pars if any */
+       char   **anms;          /* literal text for actual pars */
+       char   *prec;           /* precondition for c_code or c_expr */
+       int    dln, cln;        /* def and call linenr */
+       Symbol *dfn, *cfn;      /* def and call filename */
+       struct IType *nxt;      /* linked list */
+} IType;
+
+typedef struct C_Added {
+       Symbol *s;
+       Symbol *t;
+       Symbol *ival;
+       struct C_Added *nxt;
+} C_Added;
+
+extern RunList *X;
+extern ProcList        *rdy;
+extern Symbol  *Fname;
+extern Symbol  *context, *owner;
+extern YYSTYPE yylval;
+extern short   has_last, has_code;
+extern int     verbose, IArgs, hastrack, separate;
+
+short  has_stack = 0;
+int    lineno  = 1;
+char   yytext[2048];
+FILE   *yyin, *yyout;
+
+static C_Added *c_added, *c_tracked;
+static IType   *Inline_stub[MAXINL];
+static char    *ReDiRect;
+static char    *Inliner[MAXINL], IArg_cont[MAXPAR][MAXLEN];
+static unsigned char   in_comment=0;
+static int     IArgno = 0, Inlining = -1;
+static int     check_name(char *);
+
+#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; }
+
+#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; }
+
+#define ValToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->val = x; \
+                       if (!in_comment) return y; else goto again; }
+
+#define SymToken(x, y) { yylval = nn(ZN,0,ZN,ZN); yylval->sym = x; \
+                       if (!in_comment) return y; else goto again; }
+#endif
+
+static int     getinline(void);
+static void    uninline(void);
+
+#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 (Inlining<0)
+               c = getc(yyin);
+       else
+               c = getinline();
+       if (0)
+       {       printf("<%c:%d>[%d] ", c, c, Inlining);
+       }
+       return c;
+}
+
+static void
+Ungetch(int c)
+{
+       if (Inlining<0)
+               ungetc(c,yyin);
+       else
+               uninline();
+#if 1
+       printf("<bs>");
+#endif
+}
+#endif
+
+static int
+notquote(int c)
+{      return (c != '\"' && c != '\n');
+}
+
+int
+isalnum_(int c)
+{      return (isalnum(c) || c == '_');
+}
+
+static int
+isalpha_(int c)
+{      return isalpha(c);      /* could be macro */
+}
+       
+static int
+isdigit_(int c)
+{      return isdigit(c);      /* could be macro */
+}
+
+static void
+getword(int first, int (*tst)(int))
+{      int i=0, c;
+
+       yytext[i++]= (char) first;
+       while (tst(c = Getchar()))
+       {       yytext[i++] = (char) c;
+               if (c == '\\')
+               {       c = Getchar();
+                       yytext[i++] = (char) c; /* no tst */
+       }       }
+       yytext[i] = '\0';
+       Ungetch(c);
+}
+
+static int
+follow(int tok, int ifyes, int ifno)
+{      int c;
+
+       if ((c = Getchar()) == tok)
+               return ifyes;
+       Ungetch(c);
+
+       return ifno;
+}
+
+static IType *seqnames;
+
+static void
+def_inline(Symbol *s, int ln, char *ptr, char *prc, Lextok *nms)
+{      IType *tmp;
+       char *nw = (char *) emalloc(strlen(ptr)+1);
+       strcpy(nw, ptr);
+
+       for (tmp = seqnames; tmp; tmp = tmp->nxt)
+               if (!strcmp(s->name, tmp->nm->name))
+               {       non_fatal("procedure name %s redefined",
+                               tmp->nm->name);
+                       tmp->cn = (Lextok *) nw;
+                       tmp->params = nms;
+                       tmp->dln = ln;
+                       tmp->dfn = Fname;
+                       return;
+               }
+       tmp = (IType *) emalloc(sizeof(IType));
+       tmp->nm = s;
+       tmp->cn = (Lextok *) nw;
+       tmp->params = nms;
+       if (strlen(prc) > 0)
+       {       tmp->prec = (char *) emalloc(strlen(prc)+1);
+               strcpy(tmp->prec, prc);
+       }
+       tmp->dln = ln;
+       tmp->dfn = Fname;
+       tmp->nxt = seqnames;
+       seqnames = tmp;
+}
+
+void
+gencodetable(FILE *fd)
+{      IType *tmp;
+       char *q;
+       int cnt;
+
+       if (separate == 2) return;
+
+       fprintf(fd, "struct {\n");
+       fprintf(fd, "   char *c; char *t;\n");
+       fprintf(fd, "} code_lookup[] = {\n");
+
+       if (has_code)
+       for (tmp = seqnames; tmp; tmp = tmp->nxt)
+               if (tmp->nm->type == CODE_FRAG
+               ||  tmp->nm->type == CODE_DECL)
+               {       fprintf(fd, "\t{ \"%s\", ",
+                               tmp->nm->name);
+                       q = (char *) tmp->cn;
+
+                       while (*q == '\n' || *q == '\r' || *q == '\\')
+                               q++;
+
+                       fprintf(fd, "\"");
+                       cnt = 0;
+                       while (*q && cnt < 1024) /* pangen1.h allows 2048 */
+                       {       switch (*q) {
+                               case '"':
+                                       fprintf(fd, "\\\"");
+                                       break;
+                               case '%':
+                                       fprintf(fd, "%%");
+                                       break;
+                               case '\n':
+                                       fprintf(fd, "\\n");
+                                       break;
+                               default:
+                                       putc(*q, fd);
+                                       break;
+                               }
+                               q++; cnt++;
+                       }
+                       if (*q) fprintf(fd, "...");
+                       fprintf(fd, "\"");
+                       fprintf(fd, " },\n");
+               }
+
+       fprintf(fd, "   { (char *) 0, \"\" }\n");
+       fprintf(fd, "};\n");
+}
+
+static int
+iseqname(char *t)
+{      IType *tmp;
+
+       for (tmp = seqnames; tmp; tmp = tmp->nxt)
+       {       if (!strcmp(t, tmp->nm->name))
+                       return 1;
+       }
+       return 0;
+}
+
+static int
+getinline(void)
+{      int c;
+
+       if (ReDiRect)
+       {       c = *ReDiRect++;
+               if (c == '\0')
+               {       ReDiRect = (char *) 0;
+                       c = *Inliner[Inlining]++;
+               }
+       } else
+               c = *Inliner[Inlining]++;
+
+       if (c == '\0')
+       {       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);
+#endif
+               return Getchar();
+       }
+       return c;
+}
+
+static void
+uninline(void)
+{
+       if (ReDiRect)
+               ReDiRect--;
+       else
+               Inliner[Inlining]--;
+}
+
+IType *
+find_inline(char *s)
+{      IType *tmp;
+
+       for (tmp = seqnames; tmp; tmp = tmp->nxt)
+               if (!strcmp(s, tmp->nm->name))
+                       break;
+       if (!tmp)
+               fatal("cannot happen, missing inline def %s", s);
+
+       return tmp;
+}
+
+void
+c_state(Symbol *s, Symbol *t, Symbol *ival)    /* name, scope, ival */
+{      C_Added *r;
+
+       r = (C_Added *) emalloc(sizeof(C_Added));
+       r->s = s;       /* pointer to a data object */
+       r->t = t;       /* size of object, or "global", or "local proctype_name"  */
+       r->ival = ival;
+       r->nxt = c_added;
+       c_added = r;
+}
+
+void
+c_track(Symbol *s, Symbol *t, Symbol *stackonly)       /* name, size */
+{      C_Added *r;
+
+       r = (C_Added *) emalloc(sizeof(C_Added));
+       r->s = s;
+       r->t = t;
+       r->ival = stackonly;    /* abuse of name */
+       r->nxt = c_tracked;
+       c_tracked = r;
+
+       if (stackonly != ZS)
+       {       if (strcmp(stackonly->name, "\"Matched\"") == 0)
+                       r->ival = ZS;   /* the default */
+               else if (strcmp(stackonly->name, "\"UnMatched\"") != 0
+                    &&  strcmp(stackonly->name, "\"unMatched\"") != 0
+                    &&  strcmp(stackonly->name, "\"StackOnly\"") != 0)
+                       non_fatal("expecting '[Un]Matched', saw %s", stackonly->name);
+               else
+                       has_stack = 1;  /* unmatched stack */
+       }
+}
+
+char *
+jump_etc(char *op)
+{      char *p = op;
+
+       /* kludgy - try to get the type separated from the name */
+
+       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 */
+
+       if (*p == '\0')
+               fatal("c_state format (%s)", op);
+
+       if (strchr(p, '[')
+       &&  !strchr(p, '{'))
+       {       non_fatal("array initialization error, c_state (%s)", p);
+               return (char *) 0;
+       }
+
+       return p;
+}
+
+void
+c_add_globinit(FILE *fd)
+{      C_Added *r;
+       char *p, *q;
+
+       fprintf(fd, "void\nglobinit(void)\n{\n");
+       for (r = c_added; r; r = r->nxt)
+       {       if (r->ival == ZS)
+                       continue;
+
+               if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0)
+               {       for (q = r->ival->name; *q; q++)
+                       {       if (*q == '\"')
+                                       *q = ' ';
+                               if (*q == '\\')
+                                       *q++ = ' '; /* skip over the next */
+                       }
+                       p = jump_etc(r->s->name);       /* e.g., "int **q" */
+                       if (p)
+                       fprintf(fd, "   now.%s = %s;\n", p, r->ival->name);
+
+               } else
+               if (strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0)
+               {       for (q = r->ival->name; *q; q++)
+                       {       if (*q == '\"')
+                                       *q = ' ';
+                               if (*q == '\\')
+                                       *q++ = ' '; /* skip over the next */
+                       }
+                       p = jump_etc(r->s->name);       /* e.g., "int **q" */
+                       if (p)
+                       fprintf(fd, "   %s = %s;\n", p, r->ival->name); /* no now. prefix */
+
+       }       }
+       fprintf(fd, "}\n");
+}
+
+void
+c_add_locinit(FILE *fd, int tpnr, char *pnm)
+{      C_Added *r;
+       char *p, *q, *s;
+       int frst = 1;
+
+       fprintf(fd, "void\nlocinit%d(int h)\n{\n", tpnr);
+       for (r = c_added; r; r = r->nxt)
+               if (r->ival != ZS
+               &&  strncmp(r->t->name, " Local", strlen(" Local")) == 0)
+               {       for (q = r->ival->name; *q; q++)
+                               if (*q == '\"')
+                                       *q = ' ';
+                       
+                       p = jump_etc(r->s->name);       /* e.g., "int **q" */
+
+                       q = r->t->name + strlen(" Local");
+                       while (*q == ' ' || *q == '\t')
+                               q++;                    /* process name */
+
+                       s = (char *) emalloc(strlen(q)+1);
+                       strcpy(s, q);
+
+                       q = &s[strlen(s)-1];
+                       while (*q == ' ' || *q == '\t')
+                               *q-- = '\0';
+
+                       if (strcmp(pnm, s) != 0)
+                               continue;
+
+                       if (frst)
+                       {       fprintf(fd, "\tuchar *this = pptr(h);\n");
+                               frst = 0;
+                       }
+
+                       if (p)
+                       fprintf(fd, "           ((P%d *)this)->%s = %s;\n",
+                               tpnr, p, r->ival->name);
+
+               }
+       fprintf(fd, "}\n");
+}
+
+/* tracking:
+       1. for non-global and non-local c_state decls: add up all the sizes in c_added
+       2. add a global char array of that size into now
+       3. generate a routine that memcpy's the required values into that array
+       4. generate a call to that routine
+ */
+
+void
+c_preview(void)
+{      C_Added *r;
+
+       hastrack = 0;
+       if (c_tracked)
+               hastrack = 1;
+       else
+       for (r = c_added; r; r = r->nxt)
+               if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
+               &&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
+               &&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
+               {       hastrack = 1;   /* c_state variant now obsolete */
+                       break;
+               }
+}
+
+int
+c_add_sv(FILE *fd)     /* 1+2 -- called in pangen1.c */
+{      C_Added *r;
+       int cnt = 0;
+
+       if (!c_added && !c_tracked) return 0;
+
+       for (r = c_added; r; r = r->nxt)        /* pickup global decls */
+               if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0)
+                       fprintf(fd, "   %s;\n", r->s->name);
+
+       for (r = c_added; r; r = r->nxt)
+               if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
+               &&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
+               &&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
+               {       cnt++;  /* obsolete use */
+               }
+
+       for (r = c_tracked; r; r = r->nxt)
+               cnt++;          /* preferred use */
+
+       if (cnt == 0) return 0;
+
+       cnt = 0;
+       fprintf(fd, "   uchar c_state[");
+       for (r = c_added; r; r = r->nxt)
+               if (strncmp(r->t->name, " Global ", strlen(" Global ")) != 0
+               &&  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) != 0
+               &&  strncmp(r->t->name, " Local",  strlen(" Local"))  != 0)
+               {       fprintf(fd, "%ssizeof(%s)",
+                               (cnt==0)?"":"+", r->t->name);
+                       cnt++;
+               }
+
+       for (r = c_tracked; r; r = r->nxt)
+       {       if (r->ival != ZS) continue;
+
+               fprintf(fd, "%s%s",
+                       (cnt==0)?"":"+", r->t->name);
+               cnt++;
+       }
+
+       if (cnt == 0) fprintf(fd, "4"); /* now redundant */
+       fprintf(fd, "];\n");
+       return 1;
+}
+
+void
+c_stack_size(FILE *fd)
+{      C_Added *r;
+       int cnt = 0;
+
+       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");
+       }
+}
+
+void
+c_add_stack(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)
+               {       cnt++;
+               }
+
+       if (cnt > 0)
+       {       fprintf(fd, "   uchar c_stack[StackSize];\n");
+       }
+}
+
+void
+c_add_hidden(FILE *fd)
+{      C_Added *r;
+
+       for (r = c_added; r; r = r->nxt)        /* pickup hidden decls */
+               if (strncmp(r->t->name, "\"Hidden\"", strlen("\"Hidden\"")) == 0)
+               {       r->s->name[strlen(r->s->name)-1] = ' ';
+                       fprintf(fd, "%s;        /* Hidden */\n", &r->s->name[1]);
+                       r->s->name[strlen(r->s->name)-1] = '"';
+               }
+       /* called before c_add_def - quotes are still there */
+}
+
+void
+c_add_loc(FILE *fd, char *s)   /* state vector entries for proctype s */
+{      C_Added *r;
+       static char buf[1024];
+       char *p;
+
+       if (!c_added) return;
+
+       strcpy(buf, s);
+       strcat(buf, " ");
+       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");
+                       while (*p == ' ' || *p == '\t')
+                               p++;
+                       if (strcmp(p, buf) == 0)
+                               fprintf(fd, "   %s;\n", r->s->name);
+               }
+}
+void
+c_add_def(FILE *fd)    /* 3 - called in plunk_c_fcts() */
+{      C_Added *r;
+
+       fprintf(fd, "#if defined(C_States) && defined(HAS_TRACK)\n");
+       for (r = c_added; r; r = r->nxt)
+       {       r->s->name[strlen(r->s->name)-1] = ' ';
+               r->s->name[0] = ' '; /* remove the "s */
+
+               r->t->name[strlen(r->t->name)-1] = ' ';
+               r->t->name[0] = ' ';
+
+               if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
+               ||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
+               ||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
+                       continue;
+
+               if (strchr(r->s->name, '&'))
+                       fatal("dereferencing state object: %s", r->s->name);
+
+               fprintf(fd, "extern %s %s;\n", r->t->name, r->s->name);
+       }
+       for (r = c_tracked; r; r = r->nxt)
+       {       r->s->name[strlen(r->s->name)-1] = ' ';
+               r->s->name[0] = ' '; /* remove " */
+
+               r->t->name[strlen(r->t->name)-1] = ' ';
+               r->t->name[0] = ' ';
+       }
+
+       if (separate == 2)
+       {       fprintf(fd, "#endif\n");
+               return;
+       }
+
+       if (has_stack)
+       {       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, "   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;
+       
+                       fprintf(fd, "\tif(%s)\n", r->s->name);
+                       fprintf(fd, "\t\tmemcpy(p_t_r, %s, %s);\n",
+                               r->s->name, r->t->name);
+                       fprintf(fd, "\telse\n");
+                       fprintf(fd, "\t\tmemset(p_t_r, 0, %s);\n",
+                               r->t->name);
+                       fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
+               }
+               fprintf(fd, "}\n\n");
+       }
+
+       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, "#endif\n");
+       for (r = c_added; r; r = r->nxt)
+       {       if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
+               ||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
+               ||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
+                       continue;
+
+               fprintf(fd, "\tmemcpy(p_t_r, &%s, sizeof(%s));\n",
+                       r->s->name, r->t->name);
+               fprintf(fd, "\tp_t_r += sizeof(%s);\n", r->t->name);
+       }
+
+       for (r = c_tracked; r; r = r->nxt)
+       {       if (r->ival) continue;
+
+               fprintf(fd, "\tif(%s)\n", r->s->name);
+               fprintf(fd, "\t\tmemcpy(p_t_r, %s, %s);\n",
+                       r->s->name, r->t->name);
+               fprintf(fd, "\telse\n");
+               fprintf(fd, "\t\tmemset(p_t_r, 0, %s);\n",
+                       r->t->name);
+               fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
+       }
+
+       fprintf(fd, "}\n");
+
+       if (has_stack)
+       {       fprintf(fd, "void\nc_unstack(uchar *p_t_r)\n{\n");
+               fprintf(fd, "#ifdef VERBOSE\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;
+
+                       fprintf(fd, "\tif(%s)\n", r->s->name);
+                       fprintf(fd, "\t\tmemcpy(%s, p_t_r, %s);\n",
+                               r->s->name, r->t->name);
+                       fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
+               }
+               fprintf(fd, "}\n");
+       }
+
+       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, "#endif\n");
+       for (r = c_added; r; r = r->nxt)
+       {       if (strncmp(r->t->name, " Global ", strlen(" Global ")) == 0
+               ||  strncmp(r->t->name, " Hidden ", strlen(" Hidden ")) == 0
+               ||  strncmp(r->t->name, " Local",  strlen(" Local"))  == 0)
+                       continue;
+
+               fprintf(fd, "\tmemcpy(&%s, p_t_r, sizeof(%s));\n",
+                       r->s->name, r->t->name);
+               fprintf(fd, "\tp_t_r += sizeof(%s);\n", r->t->name);
+       }
+       for (r = c_tracked; r; r = r->nxt)
+       {       if (r->ival != ZS) continue;
+
+               fprintf(fd, "\tif(%s)\n", r->s->name);
+               fprintf(fd, "\t\tmemcpy(%s, p_t_r, %s);\n",
+                       r->s->name, r->t->name);
+               fprintf(fd, "\tp_t_r += %s;\n", r->t->name);
+       }
+
+       fprintf(fd, "}\n");
+       fprintf(fd, "#endif\n");
+}
+
+void
+plunk_reverse(FILE *fd, IType *p, int matchthis)
+{      char *y, *z;
+
+       if (!p) return;
+       plunk_reverse(fd, p->nxt, matchthis);
+
+       if (!p->nm->context
+       &&   p->nm->type == matchthis)
+       {       fprintf(fd, "\n/* start of %s */\n", p->nm->name);
+               z = (char *) p->cn;
+               while (*z == '\n' || *z == '\r' || *z == '\\')
+                       z++;
+               /* e.g.: \#include "..." */
+
+               y = z;
+               while ((y = strstr(y, "\\#")) != NULL)
+               {       *y = '\n'; y++;
+               }
+
+               fprintf(fd, "%s\n", z);
+               fprintf(fd, "\n/* end of %s */\n", p->nm->name);
+       }
+}
+
+void
+plunk_c_decls(FILE *fd)
+{
+       plunk_reverse(fd, seqnames, CODE_DECL);
+}
+
+void
+plunk_c_fcts(FILE *fd)
+{
+       if (separate == 2 && hastrack)
+       {       c_add_def(fd);
+               return;
+       }
+
+       c_add_hidden(fd);
+       plunk_reverse(fd, seqnames, CODE_FRAG);
+
+       if (c_added || c_tracked)       /* enables calls to c_revert and c_update */
+               fprintf(fd, "#define C_States   1\n");
+       else
+               fprintf(fd, "#undef C_States\n");
+
+       if (hastrack)
+               c_add_def(fd);
+
+       c_add_globinit(fd);
+       do_locinits(fd);
+}
+
+static void
+check_inline(IType *tmp)
+{      char buf[128];
+       ProcList *p;
+
+       if (!X) return;
+
+       for (p = rdy; p; p = p->nxt)
+       {       if (strcmp(p->n->name, X->n->name) == 0)
+                       continue;
+               sprintf(buf, "P%s->", p->n->name);
+               if (strstr((char *)tmp->cn, buf))
+               {       printf("spin: in proctype %s, ref to object in proctype %s\n",
+                               X->n->name, p->n->name);
+                       fatal("invalid variable ref in '%s'", tmp->nm->name);
+       }       }
+}
+
+void
+plunk_expr(FILE *fd, char *s)
+{      IType *tmp;
+
+       tmp = find_inline(s);
+       check_inline(tmp);
+
+       fprintf(fd, "%s", (char *) tmp->cn);
+}
+
+void
+preruse(FILE *fd, Lextok *n)   /* check a condition for c_expr with preconditions */
+{      IType *tmp;
+
+       if (!n) return;
+       if (n->ntyp == C_EXPR)
+       {       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, "_m = 3; goto P999; } } \n\t\t");
+               }
+       } else
+       {       preruse(fd, n->rgt);
+               preruse(fd, n->lft);
+       }
+}
+
+int
+glob_inline(char *s)
+{      IType *tmp;
+       char *bdy;
+
+       tmp = find_inline(s);
+       bdy = (char *) tmp->cn;
+       return (strstr(bdy, "now.")             /* global ref or   */
+       ||      strchr(bdy, '(') > bdy);        /* possible C-function call */
+}
+
+void
+plunk_inline(FILE *fd, char *s, int how)       /* c_code with precondition */
+{      IType *tmp;
+
+       tmp = find_inline(s);
+       check_inline(tmp);
+
+       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, "%s", (char *) tmp->cn);
+       fprintf(fd, " }\n");
+}
+
+void
+no_side_effects(char *s)
+{      IType *tmp;
+       char *t;
+
+       /* could still defeat this check via hidden
+        * side effects in function calls,
+        * but this will catch at least some cases
+        */
+
+       tmp = find_inline(s);
+       t = (char *) tmp->cn;
+
+       if (strchr(t, ';')
+       ||  strstr(t, "++")
+       ||  strstr(t, "--"))
+       {
+bad:           lineno = tmp->dln;
+               Fname = tmp->dfn;
+               non_fatal("c_expr %s has side-effects", s);
+               return;
+       }
+       while ((t = strchr(t, '=')) != NULL)
+       {       if (*(t-1) == '!'
+               ||  *(t-1) == '>'
+               ||  *(t-1) == '<')
+               {       t++;
+                       continue;
+               }
+               t++;
+               if (*t != '=')
+                       goto bad;
+               t++;
+       }
+}
+
+void
+pickup_inline(Symbol *t, Lextok *apars)
+{      IType *tmp; Lextok *p, *q; int j;
+
+       tmp = find_inline(t->name);
+
+       if (++Inlining >= MAXINL)
+               fatal("inline fcts too deeply nested", 0);
+       tmp->cln = lineno;      /* remember calling point */
+       tmp->cfn = Fname;       /* and filename */
+
+       for (p = apars, q = tmp->params, j = 0; p && q; p = p->rgt, q = q->rgt)
+               j++; /* count them */
+       if (p || q)
+               fatal("wrong nr of params on call of '%s'", t->name);
+
+       tmp->anms  = (char **) emalloc(j * sizeof(char *));
+       for (p = apars, j = 0; p; p = p->rgt, j++)
+       {       tmp->anms[j] = (char *) emalloc(strlen(IArg_cont[j])+1);
+               strcpy(tmp->anms[j], IArg_cont[j]);
+       }
+
+       lineno = tmp->dln;      /* linenr of def */
+       Fname = tmp->dfn;       /* filename of same */
+       Inliner[Inlining] = (char *)tmp->cn;
+       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);
+#endif
+       for (j = 0; j < Inlining; j++)
+               if (Inline_stub[j] == Inline_stub[Inlining])
+               fatal("cyclic inline attempt on: %s", t->name);
+}
+
+static void
+do_directive(int first)
+{      int c = first;  /* handles lines starting with pound */
+
+       getword(c, isalpha_);
+
+       if (strcmp(yytext, "#ident") == 0)
+               goto done;
+
+       if ((c = Getchar()) != ' ')
+               fatal("malformed preprocessor directive - # .", 0);
+
+       if (!isdigit_(c = Getchar()))
+               fatal("malformed preprocessor directive - # .lineno", 0);
+
+       getword(c, isdigit_);
+       lineno = atoi(yytext);  /* pickup the line number */
+
+       if ((c = Getchar()) == '\n')
+               return; /* no filename */
+
+       if (c != ' ')
+               fatal("malformed preprocessor directive - .fname", 0);
+
+       if ((c = Getchar()) != '\"')
+               fatal("malformed preprocessor directive - .fname", 0);
+
+       getword(c, notquote);
+       if (Getchar() != '\"')
+               fatal("malformed preprocessor directive - fname.", 0);
+
+       strcat(yytext, "\"");
+       Fname = lookup(yytext);
+done:
+       while (Getchar() != '\n')
+               ;
+}
+
+void
+precondition(char *q)
+{      int c, nest = 1;
+
+       for (;;)
+       {       c = Getchar();
+               *q++ = c;
+               switch (c) {
+               case '\n':
+                       lineno++;
+                       break;
+               case '[':
+                       nest++;
+                       break;
+               case ']':
+                       if (--nest <= 0)
+                       {       *--q = '\0';
+                               return;
+                       }
+                       break;
+               }
+       }
+       fatal("cannot happen", (char *) 0); /* unreachable */
+}
+
+
+Symbol *
+prep_inline(Symbol *s, Lextok *nms)
+{      int c, nest = 1, dln, firstchar, cnr;
+       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?s->name:"--");
+                       t->lft->sym->hidden |= 32;
+               }
+
+       if (!s) /* C_Code fragment */
+       {       s = (Symbol *) emalloc(sizeof(Symbol));
+               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;
+
+       p = &Buf1[0];
+       Buf2[0] = '\0';
+       for (;;)
+       {       c = Getchar();
+               switch (c) {
+               case '[':
+                       if (s->type != CODE_FRAG)
+                               goto bad;
+                       precondition(&Buf2[0]); /* e.g., c_code [p] { r = p-r; } */
+                       continue;
+               case '{':
+                       break;
+               case '\n':
+                       lineno++;
+                       /* fall through */
+               case ' ': case '\t': case '\f': case '\r':
+                       continue;
+               default :
+                        printf("spin: saw char '%c'\n", c);
+bad:                    fatal("bad inline: %s", s->name);
+               }
+               break;
+       }
+       dln = lineno;
+       if (s->type == CODE_FRAG)
+       {       if (verbose&32)
+                       sprintf(Buf1, "\t/* line %d %s */\n\t\t",
+                               lineno, Fname->name);
+               else
+                       strcpy(Buf1, "");
+       } else
+               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 - Buf1 >= SOMETHINGBIG)
+               fatal("inline text too long", 0);
+       switch (c) {
+       case '\n':
+               lineno++;
+               cnr = 0;
+               break;
+       case '{':
+               cnr++;
+               nest++;
+               break;
+       case '}':
+               cnr++;
+               if (--nest <= 0)
+               {       *p = '\0';
+                       if (s->type == CODE_FRAG)
+                               *--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;
+       case '#':
+               if (cnr == 0)
+               {       p--;
+                       do_directive(c); /* reads to newline */
+                       break;
+               } /* else fall through */
+       default:
+               firstchar = 0;
+       case '\t':
+       case ' ':
+       case '\f':
+               cnr++;
+               break;
+       }
+       goto more;
+}
+
+static int
+lex(void)
+{      int c;
+
+again:
+       c = Getchar();
+       yytext[0] = (char) c;
+       yytext[1] = '\0';
+       switch (c) {
+       case '\n':              /* newline */
+               lineno++;
+       case '\r':              /* carriage return */
+               goto again;
+
+       case  ' ': case '\t': case '\f':        /* white space */
+               goto again;
+
+       case '#':               /* preprocessor directive */
+               if (in_comment) goto again;
+               do_directive(c);
+               goto again;
+
+       case '\"':
+               getword(c, notquote);
+               if (Getchar() != '\"')
+                       fatal("string not terminated", yytext);
+               strcat(yytext, "\"");
+               SymToken(lookup(yytext), STRING)
+
+       case '\'':      /* new 3.0.9 */
+               c = Getchar();
+               if (c == '\\')
+               {       c = Getchar();
+                       if (c == 'n') c = '\n';
+                       else if (c == 'r') c = '\r';
+                       else if (c == 't') c = '\t';
+                       else if (c == 'f') c = '\f';
+               }
+               if (Getchar() != '\'' && !in_comment)
+                       fatal("character quote missing: %s", yytext);
+               ValToken(c, CONST)
+
+       default:
+               break;
+       }
+
+       if (isdigit_(c))
+       {       getword(c, isdigit_);
+               ValToken(atoi(yytext), CONST)
+       }
+
+       if (isalpha_(c) || c == '_')
+       {       getword(c, isalnum_);
+               if (!in_comment)
+               {       c = check_name(yytext);
+                       if (c) return c;
+                       /* else fall through */
+               }
+               goto again;
+       }
+
+       switch (c) {
+       case '/': c = follow('*', 0, '/');
+                 if (!c) { in_comment = 1; goto again; }
+                 break;
+       case '*': c = follow('/', 0, '*');
+                 if (!c) { in_comment = 0; goto again; }
+                 break;
+       case ':': c = follow(':', SEP, ':'); break;
+       case '-': c = follow('>', SEMI, follow('-', DECR, '-')); break;
+       case '+': c = follow('+', INCR, '+'); break;
+       case '<': c = follow('<', LSHIFT, follow('=', LE, LT)); break;
+       case '>': c = follow('>', RSHIFT, follow('=', GE, GT)); break;
+       case '=': c = follow('=', EQ, ASGN); break;
+       case '!': c = follow('=', NE, follow('!', O_SND, SND)); break;
+       case '?': c = follow('?', R_RCV, RCV); break;
+       case '&': c = follow('&', AND, '&'); break;
+       case '|': c = follow('|', OR, '|'); break;
+       case ';': c = SEMI; break;
+       default : break;
+       }
+       Token(c)
+}
+
+static struct {
+       char *s;        int tok;        int val;        char *sym;
+} Names[] = {
+       {"active",      ACTIVE,         0,              0},
+       {"assert",      ASSERT,         0,              0},
+       {"atomic",      ATOMIC,         0,              0},
+       {"bit",         TYPE,           BIT,            0},
+       {"bool",        TYPE,           BIT,            0},
+       {"break",       BREAK,          0,              0},
+       {"byte",        TYPE,           BYTE,           0},
+       {"c_code",      C_CODE,         0,              0},
+       {"c_decl",      C_DECL,         0,              0},
+       {"c_expr",      C_EXPR,         0,              0},
+       {"c_state",     C_STATE,        0,              0},
+       {"c_track",     C_TRACK,        0,              0},
+       {"D_proctype",  D_PROCTYPE,     0,              0},
+       {"do",          DO,             0,              0},
+       {"chan",        TYPE,           CHAN,           0},
+       {"else",        ELSE,           0,              0},
+       {"empty",       EMPTY,          0,              0},
+       {"enabled",     ENABLED,        0,              0},
+       {"eval",        EVAL,           0,              0},
+       {"false",       CONST,          0,              0},
+       {"fi",          FI,             0,              0},
+       {"full",        FULL,           0,              0},
+       {"goto",        GOTO,           0,              0},
+       {"hidden",      HIDDEN,         0,              ":hide:"},
+       {"if",          IF,             0,              0},
+       {"init",        INIT,           0,              ":init:"},
+       {"int",         TYPE,           INT,            0},
+       {"len",         LEN,            0,              0},
+       {"local",       ISLOCAL,        0,              ":local:"},
+       {"mtype",       TYPE,           MTYPE,          0},
+       {"nempty",      NEMPTY,         0,              0},
+       {"never",       CLAIM,          0,              ":never:"},
+       {"nfull",       NFULL,          0,              0},
+       {"notrace",     TRACE,          0,              ":notrace:"},
+       {"np_",         NONPROGRESS,    0,              0},
+       {"od",          OD,             0,              0},
+       {"of",          OF,             0,              0},
+       {"pc_value",    PC_VAL,         0,              0},
+       {"pid",         TYPE,           BYTE,           0},
+       {"printf",      PRINT,          0,              0},
+       {"printm",      PRINTM,         0,              0},
+       {"priority",    PRIORITY,       0,              0},
+       {"proctype",    PROCTYPE,       0,              0},
+       {"provided",    PROVIDED,       0,              0},
+       {"run",         RUN,            0,              0},
+       {"d_step",      D_STEP,         0,              0},
+       {"inline",      INLINE,         0,              0},
+       {"short",       TYPE,           SHORT,          0},
+       {"skip",        CONST,          1,              0},
+       {"timeout",     TIMEOUT,        0,              0},
+       {"trace",       TRACE,          0,              ":trace:"},
+       {"true",        CONST,          1,              0},
+       {"show",        SHOW,           0,              ":show:"},
+       {"typedef",     TYPEDEF,        0,              0},
+       {"unless",      UNLESS,         0,              0},
+       {"unsigned",    TYPE,           UNSIGNED,       0},
+       {"xr",          XU,             XR,             0},
+       {"xs",          XU,             XS,             0},
+       {0,             0,              0,              0},
+};
+
+static int
+check_name(char *s)
+{      int i;
+
+       yylval = nn(ZN, 0, ZN, ZN);
+       for (i = 0; Names[i].s; i++)
+               if (strcmp(s, Names[i].s) == 0)
+               {       yylval->val = Names[i].val;
+                       if (Names[i].sym)
+                               yylval->sym = lookup(Names[i].sym);
+                       return Names[i].tok;
+               }
+
+       if ((yylval->val = ismtype(s)) != 0)
+       {       yylval->ismtyp = 1;
+               return CONST;
+       }
+
+       if (strcmp(s, "_last") == 0)
+               has_last++;
+
+       if (Inlining >= 0 && !ReDiRect)
+       {       Lextok *tt, *t = Inline_stub[Inlining]->params;
+
+               for (i = 0; t; t = t->rgt, i++)                         /* formal pars */
+                if (!strcmp(s, t->lft->sym->name)                      /* varname matches formal */
+                &&   strcmp(s, Inline_stub[Inlining]->anms[i]) != 0)   /* actual pars */
+                {
+#if 0
+                       if (verbose&32)
+                       printf("\tline %d, replace %s in call of '%s' with %s\n",
+                               lineno, s,
+                               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);
+wrong:                                 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)) == '.')
+                                       {       goto wrong;
+                                       }
+                                       ptr++;
+                       }       }
+                       ReDiRect = Inline_stub[Inlining]->anms[i];
+                       return 0;
+       }        }
+
+       yylval->sym = lookup(s);        /* symbol table */
+       if (isutype(s))
+               return UNAME;
+       if (isproctype(s))
+               return PNAME;
+       if (iseqname(s))
+               return INAME;
+
+       return NAME;
+}
+
+int
+yylex(void)
+{      static int last = 0;
+       static int hold = 0;
+       int c;
+       /*
+        * repair two common syntax mistakes with
+        * semi-colons before or after a '}'
+        */
+       if (hold)
+       {       c = hold;
+               hold = 0;
+       } else
+       {       c = lex();
+               if (last == ELSE
+               &&  c != SEMI
+               &&  c != FI)
+               {       hold = c;
+                       last = 0;
+                       return SEMI;
+               }
+               if (last == '}'
+               &&  c != PROCTYPE
+               &&  c != INIT
+               &&  c != CLAIM
+               &&  c != SEP
+               &&  c != FI
+               &&  c != OD
+               &&  c != '}'
+               &&  c != UNLESS
+               &&  c != SEMI
+               &&  c != EOF)
+               {       hold = c;
+                       last = 0;
+                       return SEMI;    /* insert ';' */
+               }
+               if (c == SEMI)
+               {       /* if context, we're not in a typedef
+                        * because they're global.
+                        * if owner, we're at the end of a ref
+                        * to a struct field -- prevent that the
+                        * lookahead is interpreted as a field of
+                        * the same struct...
+                        */
+                       if (context) owner = ZS;
+                       hold = lex();   /* look ahead */
+                       if (hold == '}'
+                       ||  hold == SEMI)
+                       {       c = hold; /* omit ';' */
+                               hold = 0;
+                       }
+               }
+       }
+       last = c;
+
+       if (IArgs)
+       {       static int IArg_nst = 0;
+
+               if (strcmp(yytext, ",") == 0)
+               {       IArg_cont[++IArgno][0] = '\0';
+               } else if (strcmp(yytext, "(") == 0)
+               {       if (IArg_nst++ == 0)
+                       {       IArgno = 0;
+                               IArg_cont[0][0] = '\0';
+                       } else
+                               strcat(IArg_cont[IArgno], yytext);
+               } else if (strcmp(yytext, ")") == 0)
+               {       if (--IArg_nst > 0)
+                               strcat(IArg_cont[IArgno], yytext);
+               } else if (c == CONST && yytext[0] == '\'')
+               {       sprintf(yytext, "'%c'", yylval->val);
+                       strcat(IArg_cont[IArgno], yytext);
+               } else if (c == CONST)
+               {       sprintf(yytext, "%d", yylval->val);
+                       strcat(IArg_cont[IArgno], yytext);
+               } else
+               {
+                       switch (c) {
+                       case SEP:       strcpy(yytext, "::"); break;
+                       case SEMI:      strcpy(yytext, ";"); break;
+                       case DECR:      strcpy(yytext, "--"); break;
+                       case INCR:      strcpy(yytext, "++"); break;
+                       case LSHIFT:    strcpy(yytext, "<<"); break;
+                       case RSHIFT:    strcpy(yytext, ">>"); break;
+                       case LE:        strcpy(yytext, "<="); break;
+                       case LT:        strcpy(yytext, "<"); break;
+                       case GE:        strcpy(yytext, ">="); break;
+                       case GT:        strcpy(yytext, ">"); break;
+                       case EQ:        strcpy(yytext, "=="); break;
+                       case ASGN:      strcpy(yytext, "="); break;
+                       case NE:        strcpy(yytext, "!="); break;
+                       case R_RCV:     strcpy(yytext, "??"); break;
+                       case RCV:       strcpy(yytext, "?"); break;
+                       case O_SND:     strcpy(yytext, "!!"); break;
+                       case SND:       strcpy(yytext, "!"); break;
+                       case AND:       strcpy(yytext, "&&"); break;
+                       case OR:        strcpy(yytext, "||"); break;
+                       }
+                       strcat(IArg_cont[IArgno], yytext);
+               }
+       }
+       return c;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/structs.c b/trunk/verif/Spin/Src5.1.6/structs.c
new file mode 100755 (executable)
index 0000000..fe90e16
--- /dev/null
@@ -0,0 +1,664 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+typedef struct UType {
+       Symbol *nm;     /* name of the type */
+       Lextok *cn;     /* contents */
+       struct UType *nxt;      /* linked list */
+} UType;
+
+extern Symbol  *Fname;
+extern int     lineno, depth, Expand_Ok, has_hidden;
+
+Symbol *owner;
+
+static UType *Unames = 0;
+static UType *Pnames = 0;
+
+static Lextok  *cpnn(Lextok *, int, int, int);
+extern void    sr_mesg(FILE *, int, int);
+
+void
+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",
+                               tmp->nm->name);
+                       return;
+               }
+
+       tmp = (UType *) emalloc(sizeof(UType));
+       tmp->nm = owner;
+       tmp->cn = n;
+       tmp->nxt = Unames;
+       Unames = tmp;
+}
+
+static void
+putUname(FILE *fd, UType *tmp)
+{      Lextok *fp, *tl;
+
+       if (!tmp) return;
+       putUname(fd, tmp->nxt); /* postorder */
+       fprintf(fd, "struct %s { /* user defined type */\n",
+               tmp->nm->name);
+       for (fp = tmp->cn; fp; fp = fp->rgt)
+       for (tl = fp->lft; tl; tl = tl->rgt)
+               typ2c(tl->sym);
+       fprintf(fd, "};\n");
+}
+
+void
+putunames(FILE *fd)
+{
+       putUname(fd, Unames);
+}
+
+int
+isutype(char *t)
+{      UType *tmp;
+
+       for (tmp = Unames; tmp; tmp = tmp->nxt)
+       {       if (!strcmp(t, tmp->nm->name))
+                       return 1;
+       }
+       return 0;
+}
+
+Lextok *
+getuname(Symbol *t)
+{      UType *tmp;
+
+       for (tmp = Unames; tmp; tmp = tmp->nxt)
+       {       if (!strcmp(t->name, tmp->nm->name))
+                       return tmp->cn;
+       }
+       fatal("%s is not a typename", t->name);
+       return (Lextok *)0;
+}
+
+void
+setutype(Lextok *p, Symbol *t, Lextok *vis)    /* user-defined types */
+{      int oln = lineno;
+       Symbol *ofn = Fname;
+       Lextok *m, *n;
+
+       m = getuname(t);
+       for (n = p; n; n = n->rgt)
+       {       lineno = n->ln;
+               Fname = n->fn;
+               if (n->sym->type)
+               non_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);
+
+               if (Expand_Ok)
+                       n->sym->hidden |= (4|8|16); /* formal par */
+
+               if (vis)
+               {       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:", (size_t) 7) == 0)
+                               n->sym->hidden |= 64;
+               }
+               n->sym->type = STRUCT;  /* classification   */
+               n->sym->Slst = m;       /* structure itself */
+               n->sym->Snm  = t;       /* name of typedef  */
+               n->sym->Nid  = 0;       /* this is no chan  */
+               n->sym->hidden |= 4;
+               if (n->sym->nel <= 0)
+               non_fatal("bad array size for '%s'", n->sym->name);
+       }
+       lineno = oln;
+       Fname = ofn;
+}
+
+static Symbol *
+do_same(Lextok *n, Symbol *v, int xinit)
+{      Lextok *tmp, *fp, *tl;
+       int ix = eval(n->lft);
+       int oln = lineno;
+       Symbol *ofn = Fname;
+
+       lineno = n->ln;
+       Fname = n->fn;
+       
+       /* n->sym->type == STRUCT
+        * index:               n->lft
+        * subfields:           n->rgt
+        * structure template:  n->sym->Slst
+        * runtime values:      n->sym->Sval
+        */
+       if (xinit) ini_struct(v);       /* once, at top level */
+
+       if (ix >= v->nel || ix < 0)
+       {       printf("spin: indexing %s[%d] - size is %d\n",
+                               v->name, ix, v->nel);
+               fatal("indexing error \'%s\'", v->name);
+       }
+       if (!n->rgt || !n->rgt->lft)
+       {       non_fatal("no subfields %s", v->name);  /* i.e., wants all */
+               lineno = oln; Fname = ofn;
+               return ZS;
+       }
+
+       if (n->rgt->ntyp != '.')
+       {       printf("bad subfield type %d\n", n->rgt->ntyp);
+               alldone(1);
+       }
+
+       tmp = n->rgt->lft;
+       if (tmp->ntyp != NAME && tmp->ntyp != TYPE)
+       {       printf("bad subfield entry %d\n", tmp->ntyp);
+               alldone(1);
+       }
+       for (fp = v->Sval[ix]; fp; fp = fp->rgt)
+       for (tl = fp->lft; tl; tl = tl->rgt)
+               if (!strcmp(tl->sym->name, tmp->sym->name))
+               {       lineno = oln; Fname = ofn;
+                       return tl->sym;
+               }
+       fatal("cannot locate subfield %s", tmp->sym->name);
+       return ZS;
+}
+
+int
+Rval_struct(Lextok *n, Symbol *v, int xinit)   /* n varref, v valref */
+{      Symbol *tl;
+       Lextok *tmp;
+       int ix;
+
+       if (!n || !(tl = do_same(n, v, xinit)))
+               return 0;
+
+       tmp = n->rgt->lft;
+       if (tmp->sym->type == STRUCT)
+       {       return Rval_struct(tmp, tl, 0);
+       } else if (tmp->rgt)
+               fatal("non-zero 'rgt' on non-structure", 0);
+
+       ix = eval(tmp->lft);
+       if (ix >= tl->nel || ix < 0)
+               fatal("indexing error \'%s\'", tl->name);
+
+       return cast_val(tl->type, tl->val[ix], tl->nbits);
+}
+
+int
+Lval_struct(Lextok *n, Symbol *v, int xinit, int a)  /* a = assigned value */
+{      Symbol *tl;
+       Lextok *tmp;
+       int ix;
+
+       if (!(tl = do_same(n, v, xinit)))
+               return 1;
+
+       tmp = n->rgt->lft;
+       if (tmp->sym->type == STRUCT)
+               return Lval_struct(tmp, tl, 0, a);
+       else if (tmp->rgt)
+               fatal("non-zero 'rgt' on non-structure", 0);
+
+       ix = eval(tmp->lft);
+       if (ix >= tl->nel || ix < 0)
+               fatal("indexing error \'%s\'", tl->name);
+
+       if (tl->nbits > 0)
+               a = (a & ((1<<tl->nbits)-1));
+
+       if (a != tl->val[ix])
+       {       tl->val[ix] = a;
+               tl->setat = depth;
+       }
+       return 1;
+}
+
+int
+Cnt_flds(Lextok *m)
+{      Lextok *fp, *tl, *n;
+       int cnt = 0;
+
+       if (m->ntyp == ',')
+       {       n = m;
+               goto is_lst;
+       }
+       if (!m->sym || m->ntyp != STRUCT)
+               return 1;
+
+       n = getuname(m->sym);
+is_lst:
+       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)
+                               fatal("array of structures in param list, %s",
+                                       tl->sym->name);
+                       cnt += Cnt_flds(tl->sym->Slst);
+               }  else
+                       cnt += tl->sym->nel;
+       }
+       return cnt;
+}
+
+int
+Sym_typ(Lextok *t)
+{      Symbol *s = t->sym;
+
+       if (!s) return 0;
+
+       if (s->type != STRUCT)
+               return s->type;
+
+       if (!t->rgt
+       ||   t->rgt->ntyp != '.'        /* gh: had ! in wrong place */
+       ||  !t->rgt->lft)
+               return STRUCT;          /* not a field reference */
+
+       return Sym_typ(t->rgt->lft);
+}
+
+int
+Width_set(int *wdth, int i, Lextok *n)
+{      Lextok *fp, *tl;
+       int j = i, k;
+
+       for (fp = n; fp; fp = fp->rgt)
+       for (tl = fp->lft; tl; tl = tl->rgt)
+       {       if (tl->sym->type == STRUCT)
+                       j = Width_set(wdth, j, tl->sym->Slst);
+               else
+               {       for (k = 0; k < tl->sym->nel; k++, j++)
+                               wdth[j] = tl->sym->type;
+       }       }
+       return j;
+}
+
+void
+ini_struct(Symbol *s)
+{      int i; Lextok *fp, *tl;
+
+       if (s->type != STRUCT)  /* last step */
+       {       (void) checkvar(s, 0);
+               return;
+       }
+       if (s->Sval == (Lextok **) 0)
+       {       s->Sval = (Lextok **) emalloc(s->nel * sizeof(Lextok *));
+               for (i = 0; i < s->nel; i++)
+               {       s->Sval[i] = cpnn(s->Slst, 1, 1, 1);
+
+                       for (fp = s->Sval[i]; fp; fp = fp->rgt)
+                       for (tl = fp->lft; tl; tl = tl->rgt)
+                               ini_struct(tl->sym);
+       }       }
+}
+
+static Lextok *
+cpnn(Lextok *s, int L, int R, int S)
+{      Lextok *d; extern int Nid;
+
+       if (!s) return ZN;
+
+       d = (Lextok *) emalloc(sizeof(Lextok));
+       d->ntyp = s->ntyp;
+       d->val  = s->val;
+       d->ln   = s->ln;
+       d->fn   = s->fn;
+       d->sym  = s->sym;
+       if (L) d->lft = cpnn(s->lft, 1, 1, S);
+       if (R) d->rgt = cpnn(s->rgt, 1, 1, S);
+
+       if (S && s->sym)
+       {       d->sym = (Symbol *) emalloc(sizeof(Symbol));
+               memcpy(d->sym, s->sym, sizeof(Symbol));
+               if (d->sym->type == CHAN)
+                       d->sym->Nid = ++Nid;
+       }
+       if (s->sq || s->sl)
+               fatal("cannot happen cpnn", (char *) 0);
+
+       return d;
+}
+
+int
+full_name(FILE *fd, Lextok *n, Symbol *v, int xinit)
+{      Symbol *tl;
+       Lextok *tmp;
+       int hiddenarrays = 0;
+
+       fprintf(fd, "%s", v->name);
+
+       if (!n || !(tl = do_same(n, v, xinit)))
+               return 0;
+       tmp = n->rgt->lft;
+
+       if (tmp->sym->type == STRUCT)
+       {       fprintf(fd, ".");
+               hiddenarrays = full_name(fd, tmp, tl, 0);
+               goto out;
+       }
+       fprintf(fd, ".%s", tl->name);
+out:   if (tmp->sym->nel > 1)
+       {       fprintf(fd, "[%d]", eval(tmp->lft));
+               hiddenarrays = 1;
+       }
+       return hiddenarrays;
+}
+
+void
+validref(Lextok *p, Lextok *c)
+{      Lextok *fp, *tl;
+       char lbuf[512];
+
+       for (fp = p->sym->Slst; fp; fp = fp->rgt)
+       for (tl = fp->lft; tl; tl = tl->rgt)
+               if (strcmp(tl->sym->name, c->sym->name) == 0)
+                       return;
+
+       sprintf(lbuf, "no field '%s' defined in structure '%s'\n",
+               c->sym->name, p->sym->name);
+       non_fatal(lbuf, (char *) 0);
+}
+
+void
+struct_name(Lextok *n, Symbol *v, int xinit, char *buf)
+{      Symbol *tl;
+       Lextok *tmp;
+       char lbuf[512];
+
+       if (!n || !(tl = do_same(n, v, xinit)))
+               return;
+       tmp = n->rgt->lft;
+       if (tmp->sym->type == STRUCT)
+       {       strcat(buf, ".");
+               struct_name(tmp, tl, 0, buf);
+               return;
+       }
+       sprintf(lbuf, ".%s", tl->name);
+       strcat(buf, lbuf);
+       if (tmp->sym->nel > 1)
+       {       sprintf(lbuf, "[%d]", eval(tmp->lft));
+               strcat(buf, lbuf);
+       }
+}
+
+void
+walk2_struct(char *s, Symbol *z)
+{      Lextok *fp, *tl;
+       char eprefix[128];
+       int ix;
+       extern void Done_case(char *, Symbol *);
+
+       ini_struct(z);
+       if (z->nel == 1)
+               sprintf(eprefix, "%s%s.", s, z->name);
+       for (ix = 0; ix < z->nel; ix++)
+       {       if (z->nel > 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)
+               {       if (tl->sym->type == STRUCT)
+                               walk2_struct(eprefix, tl->sym);
+                       else if (tl->sym->type == CHAN)
+                               Done_case(eprefix, tl->sym);
+       }       }
+}
+
+void
+walk_struct(FILE *ofd, int dowhat, char *s, Symbol *z, char *a, char *b, char *c)
+{      Lextok *fp, *tl;
+       char eprefix[128];
+       int ix;
+
+       ini_struct(z);
+       if (z->nel == 1)
+               sprintf(eprefix, "%s%s.", s, z->name);
+       for (ix = 0; ix < z->nel; ix++)
+       {       if (z->nel > 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)
+               {       if (tl->sym->type == STRUCT)
+                        walk_struct(ofd, dowhat, eprefix, tl->sym, a,b,c);
+                       else
+                        do_var(ofd, dowhat, eprefix, tl->sym, a,b,c);
+       }       }
+}
+
+void
+c_struct(FILE *fd, char *ipref, Symbol *z)
+{      Lextok *fp, *tl;
+       char pref[256], eprefix[300];
+       int ix;
+
+       ini_struct(z);
+
+       for (ix = 0; ix < z->nel; ix++)
+       for (fp = z->Sval[ix]; fp; fp = fp->rgt)
+       for (tl = fp->lft; tl; tl = tl->rgt)
+       {       strcpy(eprefix, ipref);
+               if (z->nel > 1)
+               {       /* insert index before last '.' */
+                       eprefix[strlen(eprefix)-1] = '\0';
+                       sprintf(pref, "[ %d ].", ix);
+                       strcat(eprefix, pref);
+               }
+               if (tl->sym->type == STRUCT)
+               {       strcat(eprefix, tl->sym->name);
+                       strcat(eprefix, ".");
+                       c_struct(fd, eprefix, tl->sym);
+               } else
+                       c_var(fd, eprefix, tl->sym);
+       }
+}
+
+void
+dump_struct(Symbol *z, char *prefix, RunList *r)
+{      Lextok *fp, *tl;
+       char eprefix[256];
+       int ix, jx;
+
+       ini_struct(z);
+
+       for (ix = 0; ix < z->nel; ix++)
+       {       if (z->nel > 1)
+                       sprintf(eprefix, "%s[%d]", prefix, ix);
+               else
+                       strcpy(eprefix, prefix);
+               
+               for (fp = z->Sval[ix]; fp; fp = fp->rgt)
+               for (tl = fp->lft; tl; tl = tl->rgt)
+               {       if (tl->sym->type == STRUCT)
+                       {       char pref[300];
+                               strcpy(pref, eprefix);
+                               strcat(pref, ".");
+                               strcat(pref, tl->sym->name);
+                               dump_struct(tl->sym, pref, r);
+                       } else
+                       for (jx = 0; jx < tl->sym->nel; jx++)
+                       {       if (tl->sym->type == CHAN)
+                                       doq(tl->sym, jx, r);
+                               else
+                               {       printf("\t\t");
+                                       if (r)
+                                       printf("%s(%d):", r->n->name, r->pid);
+                                       printf("%s.%s", eprefix, tl->sym->name);
+                                       if (tl->sym->nel > 1)
+                                               printf("[%d]", jx);
+                                       printf(" = ");
+                                       sr_mesg(stdout, tl->sym->val[jx],
+                                               tl->sym->type == MTYPE);
+                                       printf("\n");
+               }       }       }
+       }
+}
+
+static int
+retrieve(Lextok **targ, int i, int want, Lextok *n, int Ntyp)
+{      Lextok *fp, *tl;
+       int j = i, k;
+
+       for (fp = n; fp; fp = fp->rgt)
+       for (tl = fp->lft; tl; tl = tl->rgt)
+       {       if (tl->sym->type == STRUCT)
+               {       j = retrieve(targ, j, want, tl->sym->Slst, Ntyp);
+                       if (j < 0)
+                       {       Lextok *x = cpnn(tl, 1, 0, 0);
+                               x->rgt = nn(ZN, '.', (*targ), ZN);
+                               (*targ) = x;
+                               return -1;
+                       }
+               } else
+               {       for (k = 0; k < tl->sym->nel; k++, j++)
+                       {       if (j == want)
+                               {       *targ = cpnn(tl, 1, 0, 0);
+                                       (*targ)->lft = nn(ZN, CONST, ZN, ZN);
+                                       (*targ)->lft->val = k;
+                                       if (Ntyp)
+                                       (*targ)->ntyp = (short) Ntyp;
+                                       return -1;
+                               }
+       }       }       }
+       return j;
+}
+
+static int
+is_explicit(Lextok *n)
+{
+       if (!n) return 0;
+       if (!n->sym) fatal("unexpected - no symbol", 0);
+       if (n->sym->type != STRUCT) return 1;
+       if (!n->rgt) return 0;
+       if (n->rgt->ntyp != '.')
+       {       lineno = n->ln;
+               Fname  = n->fn;
+               printf("ntyp %d\n", n->rgt->ntyp);
+               fatal("unexpected %s, no '.'", n->sym->name);
+       }
+       return is_explicit(n->rgt->lft);
+}
+
+Lextok *
+expand(Lextok *n, int Ok)
+       /* turn rgt-lnked list of struct nms, into ',' list of flds */
+{      Lextok *x = ZN, *y;
+
+       if (!Ok) return n;
+
+       while (n)
+       {       y = mk_explicit(n, 1, 0);
+               if (x)
+                       (void) tail_add(x, y);
+               else
+                       x = y;
+
+               n = n->rgt;
+       }
+       return x;
+}
+
+Lextok *
+mk_explicit(Lextok *n, int Ok, int Ntyp)
+       /* produce a single ',' list of fields */
+{      Lextok *bld = ZN, *x;
+       int i, cnt; extern int IArgs;
+
+       if (n->sym->type != STRUCT
+       ||  is_explicit(n))
+               return n;
+
+       if (n->rgt
+       &&  n->rgt->ntyp == '.'
+       &&  n->rgt->lft
+       &&  n->rgt->lft->sym
+       &&  n->rgt->lft->sym->type == STRUCT)
+       {       Lextok *y;
+               bld = mk_explicit(n->rgt->lft, Ok, Ntyp);
+               for (x = bld; x; x = x->rgt)
+               {       y = cpnn(n, 1, 0, 0);
+                       y->rgt = nn(ZN, '.', x->lft, ZN);
+                       x->lft = y;
+               }
+
+               return bld;
+       }
+
+       if (!Ok || !n->sym->Slst)
+       {       if (IArgs) return n;
+               printf("spin: saw '");
+               comment(stdout, n, 0);
+               printf("'\n");
+               fatal("incomplete structure ref '%s'", n->sym->name);
+       }
+
+       cnt = Cnt_flds(n->sym->Slst);
+       for (i = cnt-1; i >= 0; i--)
+       {       bld = nn(ZN, ',', ZN, bld);
+               if (retrieve(&(bld->lft), 0, i, n->sym->Slst, Ntyp) >= 0)
+               {       printf("cannot retrieve field %d\n", i);
+                       fatal("bad structure %s", n->sym->name);
+               }
+               x = cpnn(n, 1, 0, 0);
+               x->rgt = nn(ZN, '.', bld->lft, ZN);
+               bld->lft = x;
+       }
+       return bld;
+}
+
+Lextok *
+tail_add(Lextok *a, Lextok *b)
+{      Lextok *t;
+
+       for (t = a; t->rgt; t = t->rgt)
+               if (t->ntyp != ',')
+               fatal("unexpected type - tail_add", 0);
+       t->rgt = b;
+       return a;
+}
+
+void
+setpname(Lextok *n)
+{      UType *tmp;
+
+       for (tmp = Pnames; tmp; tmp = tmp->nxt)
+               if (!strcmp(n->sym->name, tmp->nm->name))
+               {       non_fatal("proctype %s redefined",
+                               n->sym->name);
+                       return;
+               }
+       tmp = (UType *) emalloc(sizeof(UType));
+       tmp->nm = n->sym;
+       tmp->nxt = Pnames;
+       Pnames = tmp;
+}
+
+int
+isproctype(char *t)
+{      UType *tmp;
+
+       for (tmp = Pnames; tmp; tmp = tmp->nxt)
+       {       if (!strcmp(t, tmp->nm->name))
+                       return 1;
+       }
+       return 0;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/sym.c b/trunk/verif/Spin/Src5.1.6/sym.c
new file mode 100755 (executable)
index 0000000..823dbf0
--- /dev/null
@@ -0,0 +1,533 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+extern Symbol  *Fname, *owner;
+extern int     lineno, depth, verbose, NamesNotAdded, deadvar, has_hidden;
+extern short   has_xu;
+
+Symbol *context = ZS;
+Ordered        *all_names = (Ordered *)0;
+int    Nid = 0;
+
+Lextok *Mtype = (Lextok *) 0;
+
+static Ordered *last_name = (Ordered *)0;
+static Symbol  *symtab[Nhash+1];
+static Lextok *runstmnts = ZN;
+
+static int
+samename(Symbol *a, Symbol *b)
+{
+       if (!a && !b) return 1;
+       if (!a || !b) return 0;
+       return !strcmp(a->name, b->name);
+}
+
+int
+hash(char *s)
+{      int h=0;
+
+       while (*s)
+       {       h += *s++;
+               h <<= 1;
+               if (h&(Nhash+1))
+                       h |= 1;
+       }
+       return h&Nhash;
+}
+
+Symbol *
+lookup(char *s)
+{      Symbol *sp; Ordered *no;
+       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 (context)                            /* in proctype */
+       for (sp = symtab[h]; sp; sp = sp->next)
+               if (strcmp(sp->name, s) == 0
+               && !sp->context
+               &&  samename(sp->owner, owner))
+                       return sp;              /* global */
+
+       sp = (Symbol *) emalloc(sizeof(Symbol));
+       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 */
+
+       if (NamesNotAdded == 0)
+       {       sp->next = symtab[h];
+               symtab[h] = sp;
+               no = (Ordered *) emalloc(sizeof(Ordered));
+               no->entry = sp;
+               if (!last_name)
+                       last_name = all_names = no;
+               else
+               {       last_name->next = no;
+                       last_name = no;
+       }       }
+
+       return sp;
+}
+
+void
+trackvar(Lextok *n, Lextok *m)
+{      Symbol *sp = n->sym;
+
+       if (!sp) return;        /* a structure list */
+       switch (m->ntyp) {
+       case NAME:
+               if (m->sym->type != BIT)
+               {       sp->hidden |= 4;
+                       if (m->sym->type != BYTE)
+                               sp->hidden |= 8;
+               }
+               break;
+       case CONST:
+               if (m->val != 0 && m->val != 1)
+                       sp->hidden |= 4;
+               if (m->val < 0 || m->val > 256)
+                       sp->hidden |= 8; /* ditto byte-equiv */
+               break;
+       default:        /* unknown */
+               sp->hidden |= (4|8); /* not known bit-equiv */
+       }
+}
+
+void
+trackrun(Lextok *n)
+{
+       runstmnts = nn(ZN, 0, n, runstmnts);
+}
+
+void
+checkrun(Symbol *parnm, int posno)
+{      Lextok *n, *now, *v; int i, m;
+       int res = 0; char buf[16], buf2[16];
+
+       for (n = runstmnts; n; n = n->rgt)
+       {       now = n->lft;
+               if (now->sym != parnm->context)
+                       continue;
+               for (v = now->lft, i = 0; v; v = v->rgt, i++)
+                       if (i == posno)
+                       {       m = v->lft->ntyp;
+                               if (m == CONST)
+                               {       m = v->lft->val;
+                                       if (m != 0 && m != 1)
+                                               res |= 4;
+                                       if (m < 0 || m > 256)
+                                               res |= 8;
+                               } else if (m == NAME)
+                               {       m = v->lft->sym->type;
+                                       if (m != BIT)
+                                       {       res |= 4;
+                                               if (m != BYTE)
+                                                       res |= 8;
+                                       }
+                               } else
+                                       res |= (4|8); /* unknown */
+                               break;
+       }               }
+       if (!(res&4) || !(res&8))
+       {       if (!(verbose&32)) return;
+               strcpy(buf2, (!(res&4))?"bit":"byte");
+               sputtype(buf, parnm->type);
+               i = (int) strlen(buf);
+               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?parnm->context->name:"", buf, parnm->name);
+               printf(" '%s %s'\n", buf2, parnm->name);
+       }
+}
+
+void
+trackchanuse(Lextok *m, Lextok *w, int t)
+{      Lextok *n = m; int cnt = 1;
+       while (n)
+       {       if (n->lft
+               &&  n->lft->sym
+               &&  n->lft->sym->type == CHAN)
+                       setaccess(n->lft->sym, w?w->sym:ZS, cnt, t);
+               n = n->rgt; cnt++;
+       }
+}
+
+void
+setptype(Lextok *n, int t, Lextok *vis)        /* predefined types */
+{      int oln = lineno, cnt = 1; extern int Expand_Ok;
+
+       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;
+               }
+               n->sym->type = (short) t;
+
+               if (Expand_Ok)
+               {       n->sym->hidden |= (4|8|16); /* formal par */
+                       if (t == CHAN)
+                       setaccess(n->sym, ZS, cnt, 'F');
+               }
+               if (t == UNSIGNED)
+               {       if (n->sym->nbits < 0 || n->sym->nbits >= 32)
+                       fatal("(%s) has invalid width-field", n->sym->name);
+                       if (n->sym->nbits == 0)
+                       {       n->sym->nbits = 16;
+                               non_fatal("unsigned without width-field", 0);
+                       }
+               } else if (n->sym->nbits > 0)
+               {       non_fatal("(%s) only an unsigned can have width-field",
+                               n->sym->name);
+               }
+               if (vis)
+               {       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:", (size_t) 6) == 0)
+                       {       n->sym->hidden |= 2;
+                       } else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
+                       {       n->sym->hidden |= 64;
+                       }
+               }
+               if (t == CHAN)
+                       n->sym->Nid = ++Nid;
+               else
+               {       n->sym->Nid = 0;
+                       if (n->sym->ini
+                       &&  n->sym->ini->ntyp == CHAN)
+                       {       Fname = n->fn;
+                               lineno = n->ln;
+                               fatal("chan initializer for non-channel %s",
+                               n->sym->name);
+                       }
+               }
+               if (n->sym->nel <= 0)
+               { lineno = n->ln; Fname = n->fn;
+                 non_fatal("bad array size for '%s'", n->sym->name);
+                 lineno = oln;
+               }
+               n = n->rgt; cnt++;
+       }
+}
+
+static void
+setonexu(Symbol *sp, int t)
+{
+       sp->xu |= t;
+       if (t == XR || t == XS)
+       {       if (sp->xup[t-1]
+               &&  strcmp(sp->xup[t-1]->name, context->name))
+               {       printf("error: x[rs] claims from %s and %s\n",
+                               sp->xup[t-1]->name, context->name);
+                       non_fatal("conflicting claims on chan '%s'",
+                               sp->name);
+               }
+               sp->xup[t-1] = context;
+       }
+}
+
+static void
+setallxu(Lextok *n, int t)
+{      Lextok *fp, *tl;
+
+       for (fp = n; fp; fp = fp->rgt)
+       for (tl = fp->lft; tl; tl = tl->rgt)
+       {       if (tl->sym->type == STRUCT)
+                       setallxu(tl->sym->Slst, t);
+               else if (tl->sym->type == CHAN)
+                       setonexu(tl->sym, t);
+       }
+}
+
+Lextok *Xu_List = (Lextok *) 0;
+
+void
+setxus(Lextok *p, int t)
+{      Lextok *m, *n;
+
+       has_xu = 1; 
+       if (!context)
+       {       lineno = p->ln;
+               Fname = p->fn;
+               fatal("non-local x[rs] assertion", (char *)0);
+       }
+       for (m = p; m; m = m->rgt)
+       {       Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok));
+               Xu_new->val = t;
+               Xu_new->lft = m->lft;
+               Xu_new->sym = context;
+               Xu_new->rgt = Xu_List;
+               Xu_List = Xu_new;
+
+               n = m->lft;
+               if (n->sym->type == STRUCT)
+                       setallxu(n->sym->Slst, t);
+               else if (n->sym->type == CHAN)
+                       setonexu(n->sym, t);
+               else
+               {       int oln = lineno;
+                       lineno = n->ln; Fname = n->fn;
+                       non_fatal("xr or xs of non-chan '%s'",
+                               n->sym->name);
+                       lineno = oln;
+               }
+       }
+}
+
+void
+setmtype(Lextok *m)
+{      Lextok *n;
+       int cnt, oln = lineno;
+
+       if (m) { lineno = m->ln; Fname = m->fn; }
+
+       if (!Mtype)
+               Mtype = m;
+       else
+       {       for (n = Mtype; n->rgt; n = n->rgt)
+                       ;
+               n->rgt = m;     /* concatenate */
+       }
+
+       for (n = Mtype, cnt = 1; n; n = n->rgt, cnt++)  /* syntax check */
+       {       if (!n->lft || !n->lft->sym
+               ||   n->lft->ntyp != NAME
+               ||   n->lft->lft)       /* indexed variable */
+                       fatal("bad mtype definition", (char *)0);
+
+               /* label the name */
+               if (n->lft->sym->type != MTYPE)
+               {       n->lft->sym->hidden |= 128;     /* is used */
+                       n->lft->sym->type = MTYPE;
+                       n->lft->sym->ini = nn(ZN,CONST,ZN,ZN);
+                       n->lft->sym->ini->val = cnt;
+               } else if (n->lft->sym->ini->val != cnt)
+                       non_fatal("name %s appears twice in mtype declaration",
+                               n->lft->sym->name);
+       }
+       lineno = oln;
+       if (cnt > 256)
+       fatal("too many mtype elements (>255)", (char *)0);
+}
+
+int
+ismtype(char *str)     /* name to number */
+{      Lextok *n;
+       int cnt = 1;
+
+       for (n = Mtype; n; n = n->rgt)
+       {       if (strcmp(str, n->lft->sym->name) == 0)
+                       return cnt;
+               cnt++;
+       }
+       return 0;
+}
+
+int
+sputtype(char *foo, int m)
+{
+       switch (m) {
+       case UNSIGNED:  strcpy(foo, "unsigned "); break;
+       case BIT:       strcpy(foo, "bit   "); break;
+       case BYTE:      strcpy(foo, "byte  "); break;
+       case CHAN:      strcpy(foo, "chan  "); break;
+       case SHORT:     strcpy(foo, "short "); break;
+       case INT:       strcpy(foo, "int   "); break;
+       case MTYPE:     strcpy(foo, "mtype "); break;
+       case STRUCT:    strcpy(foo, "struct"); break;
+       case PROCTYPE:  strcpy(foo, "proctype"); break;
+       case LABEL:     strcpy(foo, "label "); return 0;
+       default:        strcpy(foo, "value "); return 0;
+       }
+       return 1;
+}
+
+
+static int
+puttype(int m)
+{      char buf[128];
+
+       if (sputtype(buf, m))
+       {       printf("%s", buf);
+               return 1;
+       }
+       return 0;
+}
+
+void
+symvar(Symbol *sp)
+{      Lextok *m;
+
+       if (!puttype(sp->type))
+               return;
+
+       printf("\t");
+       if (sp->owner) printf("%s.", sp->owner->name);
+       printf("%s", sp->name);
+       if (sp->nel > 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 */
+               printf("\t%s", sp->Snm->name);
+       else
+               printf("\t%d", eval(sp->ini));
+
+       if (sp->owner)
+               printf("\t<:struct-field:>");
+       else
+       if (!sp->context)
+               printf("\t<:global:>");
+       else
+               printf("\t<%s>", sp->context->name);
+
+       if (sp->Nid < 0)        /* formal parameter */
+               printf("\t<parameter %d>", -(sp->Nid));
+       else
+               printf("\t<variable>");
+       if (sp->type == CHAN && sp->ini)
+       {       int i;
+               for (m = sp->ini->rgt, i = 0; m; m = m->rgt)
+                       i++;
+               printf("\t%d\t", i);
+               for (m = sp->ini->rgt; m; m = m->rgt)
+               {       if (m->ntyp == STRUCT)
+                               printf("struct %s", m->sym->name);
+                       else
+                               (void) puttype(m->ntyp);
+                       if (m->rgt) printf("\t");
+               }
+       }
+       printf("\n");
+}
+
+void
+symdump(void)
+{      Ordered *walk;
+
+       for (walk = all_names; walk; walk = walk->next)
+               symvar(walk->entry);
+}
+
+void
+chname(Symbol *sp)
+{      printf("chan ");
+       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);
+       printf("\t");
+}
+
+static struct X {
+       int typ; char *nm;
+} xx[] = {
+       { 'A', "exported as run parameter" },
+       { 'F', "imported as proctype parameter" },
+       { 'L', "used as l-value in asgnmnt" },
+       { 'V', "used as r-value in asgnmnt" },
+       { 'P', "polled in receive stmnt" },
+       { 'R', "used as parameter in receive stmnt" },
+       { 'S', "used as parameter in send stmnt" },
+       { 'r', "received from" },
+       { 's', "sent to" },
+};
+
+static void
+chan_check(Symbol *sp)
+{      Access *a; int i, b=0, d;
+
+       if (verbose&1) goto report;     /* -C -g */
+
+       for (a = sp->access; a; a = a->lnk)
+               if (a->typ == 'r')
+                       b |= 1;
+               else if (a->typ == 's')
+                       b |= 2;
+       if (b == 3 || (sp->hidden&16))  /* balanced or formal par */
+               return;
+report:
+       chname(sp);
+       for (i = d = 0; i < (int) (sizeof(xx)/sizeof(struct X)); i++)
+       {       b = 0;
+               for (a = sp->access; a; a = a->lnk)
+                       if (a->typ == xx[i].typ) b++;
+               if (b == 0) continue; d++;
+               printf("\n\t%s by: ", xx[i].nm);
+               for (a = sp->access; a; a = a->lnk)
+                 if (a->typ == xx[i].typ)
+                 {     printf("%s", a->who->name);
+                       if (a->what) printf(" to %s", a->what->name);
+                       if (a->cnt)  printf(" par %d", a->cnt);
+                       if (--b > 0) printf(", ");
+                 }
+       }
+       printf("%s\n", (!d)?"\n\tnever used under this name":"");
+}
+
+void
+chanaccess(void)
+{      Ordered *walk;
+       char buf[128];
+       extern int Caccess, separate;
+       extern short has_code;
+
+       for (walk = all_names; walk; walk = walk->next)
+       {       if (!walk->entry->owner)
+               switch (walk->entry->type) {
+               case CHAN:
+                       if (Caccess) chan_check(walk->entry);
+                       break;
+               case MTYPE:
+               case BIT:
+               case BYTE:
+               case SHORT:
+               case INT:
+               case UNSIGNED:
+                       if ((walk->entry->hidden&128))  /* was: 32 */
+                               continue;
+
+                       if (!separate
+                       &&  !walk->entry->context
+                       &&  !has_code
+                       &&   deadvar)
+                               walk->entry->hidden |= 1; /* auto-hide */
+
+                       if (!(verbose&32) || has_code) continue;
+
+                       printf("spin: warning, %s, ", Fname->name);
+                       sputtype(buf, walk->entry->type);
+                       if (walk->entry->context)
+                               printf("proctype %s",
+                                       walk->entry->context->name);
+                       else
+                               printf("global");
+                       printf(", '%s%s' variable is never used\n",
+                               buf, walk->entry->name);
+       }       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/tl.h b/trunk/verif/Spin/Src5.1.6/tl.h
new file mode 100755 (executable)
index 0000000..1e6c094
--- /dev/null
@@ -0,0 +1,128 @@
+/***** 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            */
+
+/* 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>
+
+typedef struct Symbol {
+       char            *name;
+       struct Symbol   *next;  /* linked list, symbol table */
+} Symbol;
+
+typedef struct Node {
+       short           ntyp;   /* node type */
+       struct Symbol   *sym;
+       struct Node     *lft;   /* tree */
+       struct Node     *rgt;   /* tree */
+       struct Node     *nxt;   /* if linked list */
+} Node;
+
+typedef struct Graph {
+       Symbol          *name;
+       Symbol          *incoming;
+       Symbol          *outgoing;
+       Symbol          *oldstring;
+       Symbol          *nxtstring;
+       Node            *New;
+       Node            *Old;
+       Node            *Other;
+       Node            *Next;
+       unsigned char   isred[64], isgrn[64];
+       unsigned char   redcnt, grncnt;
+       unsigned char   reachable;
+       struct Graph    *nxt;
+} Graph;
+
+typedef struct Mapping {
+       char    *from;
+       Graph   *to;
+       struct Mapping  *nxt;
+} Mapping;
+
+enum {
+       ALWAYS=257,
+       AND,            /* 258 */
+       EQUIV,          /* 259 */
+       EVENTUALLY,     /* 260 */
+       FALSE,          /* 261 */
+       IMPLIES,        /* 262 */
+       NOT,            /* 263 */
+       OR,             /* 264 */
+       PREDICATE,      /* 265 */
+       TRUE,           /* 266 */
+       U_OPER,         /* 267 */
+       V_OPER          /* 268 */
+#ifdef NXT
+       , NEXT          /* 269 */
+#endif
+};
+
+Node   *Canonical(Node *);
+Node   *canonical(Node *);
+Node   *cached(Node *);
+Node   *dupnode(Node *);
+Node   *getnode(Node *);
+Node   *in_cache(Node *);
+Node   *push_negation(Node *);
+Node   *right_linked(Node *);
+Node   *tl_nn(int, Node *, Node *);
+
+Symbol *tl_lookup(char *);
+Symbol *getsym(Symbol *);
+Symbol *DoDump(Node *);
+
+extern char    *emalloc(size_t);       /* in main.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);
+
+void   *tl_emalloc(int);
+void   a_stats(void);
+void   addtrans(Graph *, char *, Node *, char *);
+void   cache_stats(void);
+void   dump(Node *);
+void   exit(int);
+void   Fatal(char *, char *);
+void   fatal(char *, char *);
+void   fsm_print(void);
+void   releasenode(int, Node *);
+void   tfree(void *);
+void   tl_explain(int);
+void   tl_UnGetchar(void);
+void   tl_parse(void);
+void   tl_yyerror(char *);
+void   trans(Node *);
+
+#define ZN     (Node *)0
+#define ZS     (Symbol *)0
+#define Nhash  255     /* must match size in spin.h */
+#define True   tl_nn(TRUE,  ZN, ZN)
+#define False  tl_nn(FALSE, ZN, ZN)
+#define Not(a) push_negation(tl_nn(NOT, a, ZN))
+#define rewrite(n)     canonical(right_linked(n))
+
+typedef Node   *Nodeptr;
+#define YYSTYPE         Nodeptr
+
+#define Debug(x)       { if (tl_verbose) printf(x); }
+#define Debug2(x,y)    { if (tl_verbose) printf(x,y); }
+#define Dump(x)                { if (tl_verbose) dump(x); }
+#define Explain(x)     { if (tl_verbose) tl_explain(x); }
+
+#define Assert(x, y)   { if (!(x)) { tl_explain(y); \
+                         Fatal(": assertion failed\n",(char *)0); } }
diff --git a/trunk/verif/Spin/Src5.1.6/tl_buchi.c b/trunk/verif/Spin/Src5.1.6/tl_buchi.c
new file mode 100755 (executable)
index 0000000..7dd9d30
--- /dev/null
@@ -0,0 +1,666 @@
+/***** 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            */
+
+/* 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;
+
+FILE   *tl_out;        /* if standalone: = stdout; */
+
+typedef struct Transition {
+       Symbol *name;
+       Node *cond;
+       int redundant, merged, marked;
+       struct Transition *nxt;
+} Transition;
+
+typedef struct State {
+       Symbol  *name;
+       Transition *trans;
+       Graph   *colors;
+       unsigned char redundant;
+       unsigned char accepting;
+       unsigned char reachable;
+       struct State *nxt;
+} State;
+
+static State *never = (State *) 0;
+static int hitsall;
+
+static int
+sametrans(Transition *s, Transition *t)
+{
+       if (strcmp(s->name->name, t->name->name) != 0)
+               return 0;
+       return isequal(s->cond, t->cond);
+}
+
+static Node *
+Prune(Node *p)
+{
+       if (p)
+       switch (p->ntyp) {
+       case PREDICATE:
+       case NOT:
+       case FALSE:
+       case TRUE:
+#ifdef NXT
+       case NEXT:
+#endif
+               return p;
+       case OR:
+               p->lft = Prune(p->lft);
+               if (!p->lft)
+               {       releasenode(1, p->rgt);
+                       return ZN;
+               }
+               p->rgt = Prune(p->rgt);
+               if (!p->rgt)
+               {       releasenode(1, p->lft);
+                       return ZN;
+               }
+               return p;
+       case AND:
+               p->lft = Prune(p->lft);
+               if (!p->lft)
+                       return Prune(p->rgt);
+               p->rgt = Prune(p->rgt);
+               if (!p->rgt)
+                       return p->lft;
+               return p;
+       }
+       releasenode(1, p);
+       return ZN;
+}
+
+static State *
+findstate(char *nm)
+{      State *b;
+       for (b = never; b; b = b->nxt)
+               if (!strcmp(b->name->name, nm))
+                       return b;
+       if (strcmp(nm, "accept_all"))
+       {       if (strncmp(nm, "accept", 6))
+               {       int i; char altnm[64];
+                       for (i = 0; i < 64; i++)
+                               if (nm[i] == '_')
+                                       break;
+                       if (i >= 64)
+                               Fatal("name too long %s", nm);
+                       sprintf(altnm, "accept%s", &nm[i]);
+                       return findstate(altnm);
+               }
+       /*      Fatal("buchi: no state %s", nm); */
+       }
+       return (State *) 0;
+}
+
+static void
+Dfs(State *b)
+{      Transition *t;
+
+       if (!b || b->reachable) return;
+       b->reachable = 1;
+
+       if (b->redundant)
+               printf("/* redundant state %s */\n",
+                       b->name->name);
+       for (t = b->trans; t; t = t->nxt)
+       {       if (!t->redundant)
+               {       Dfs(findstate(t->name->name));
+                       if (!hitsall
+                       &&  strcmp(t->name->name, "accept_all") == 0)
+                               hitsall = 1;
+               }
+       }
+}
+
+void
+retarget(char *from, char *to)
+{      State *b;
+       Transition *t;
+       Symbol *To = tl_lookup(to);
+
+       if (tl_verbose) printf("replace %s with %s\n", from, to);
+
+       for (b = never; b; b = b->nxt)
+       {       if (!strcmp(b->name->name, from))
+                       b->redundant = 1;
+               else
+               for (t = b->trans; t; t = t->nxt)
+               {       if (!strcmp(t->name->name, from))
+                               t->name = To;
+       }       }
+}
+
+#ifdef NXT
+static Node *
+nonxt(Node *n)
+{
+       switch (n->ntyp) {
+       case U_OPER:
+       case V_OPER:
+       case NEXT:
+               return ZN;
+       case OR:
+               n->lft = nonxt(n->lft);
+               n->rgt = nonxt(n->rgt);
+               if (!n->lft || !n->rgt)
+                       return True;
+               return n;
+       case AND:
+               n->lft = nonxt(n->lft);
+               n->rgt = nonxt(n->rgt);
+               if (!n->lft)
+               {       if (!n->rgt)
+                               n = ZN;
+                       else
+                               n = n->rgt;
+               } else if (!n->rgt)
+                       n = n->lft;
+               return n;
+       }
+       return n;
+}
+#endif
+
+static Node *
+combination(Node *s, Node *t)
+{      Node *nc;
+#ifdef NXT
+       Node *a = nonxt(s);
+       Node *b = nonxt(t);
+
+       if (tl_verbose)
+       {       printf("\tnonxtA: "); dump(a);
+               printf("\n\tnonxtB: "); dump(b);
+               printf("\n");
+       }
+       /* if there's only a X(f), its equivalent to true */
+       if (!a || !b)
+               nc = True;
+       else
+               nc = tl_nn(OR, a, b);
+#else
+       nc = tl_nn(OR, s, t);
+#endif
+       if (tl_verbose)
+       {       printf("\tcombo: "); dump(nc);
+               printf("\n");
+       }
+       return nc;
+}
+
+Node *
+unclutter(Node *n, char *snm)
+{      Node *t, *s, *v, *u;
+       Symbol *w;
+
+       /* check only simple cases like !q && q */
+       for (t = n; t; t = t->rgt)
+       {       if (t->rgt)
+               {       if (t->ntyp != AND || !t->lft)
+                               return n;
+                       if (t->lft->ntyp != PREDICATE
+#ifdef NXT
+                       &&  t->lft->ntyp != NEXT
+#endif
+                       &&  t->lft->ntyp != NOT)
+                               return n;
+               } else
+               {       if (t->ntyp != PREDICATE
+#ifdef NXT
+                       &&  t->ntyp != NEXT
+#endif
+                       &&  t->ntyp != NOT)
+                               return n;
+               }
+       }
+
+       for (t = n; t; t = t->rgt)
+       {       if (t->rgt)
+                       v = t->lft;
+               else
+                       v = t;
+               if (v->ntyp == NOT
+               &&  v->lft->ntyp == PREDICATE)
+               {       w = v->lft->sym;
+                       for (s = n; s; s = s->rgt)
+                       {       if (s == t) continue;
+                               if (s->rgt)
+                                       u = s->lft;
+                               else
+                                       u = s;
+                               if (u->ntyp == PREDICATE
+                               &&  strcmp(u->sym->name, w->name) == 0)
+                               {       if (tl_verbose)
+                                       {       printf("BINGO %s:\t", snm);
+                                               dump(n);
+                                               printf("\n");
+                                       }
+                                       return False;
+                               }
+                       }
+       }       }
+       return n;
+}
+
+static void
+clutter(void)
+{      State *p;
+       Transition *s;
+
+       for (p = never; p; p = p->nxt)
+       for (s = p->trans; s; s = s->nxt)
+       {       s->cond = unclutter(s->cond, p->name->name);
+               if (s->cond
+               &&  s->cond->ntyp == FALSE)
+               {       if (s != p->trans 
+                       ||  s->nxt)
+                               s->redundant = 1;
+               }
+       }
+}
+
+static void
+showtrans(State *a)
+{      Transition *s;
+
+       for (s = a->trans; s; s = s->nxt)
+       {       printf("%s ", s->name?s->name->name:"-");
+               dump(s->cond);
+               printf(" %d %d %d\n", s->redundant, s->merged, s->marked);
+       }
+}
+
+static int
+mergetrans(void)
+{      State *b;
+       Transition *s, *t;
+       Node *nc; int cnt = 0;
+
+       for (b = never; b; b = b->nxt)
+       {       if (!b->reachable) continue;
+
+               for (s = b->trans; s; s = s->nxt)
+               {       if (s->redundant) continue;
+
+                       for (t = s->nxt; t; t = t->nxt)
+                       if (!t->redundant
+                       &&  !strcmp(s->name->name, t->name->name))
+                       {       if (tl_verbose)
+                               {       printf("===\nstate %s, trans to %s redundant\n",
+                                       b->name->name, s->name->name);
+                                       showtrans(b);
+                                       printf(" conditions ");
+                                       dump(s->cond); printf(" <-> ");
+                                       dump(t->cond); printf("\n");
+                               }
+
+                               if (!s->cond) /* same as T */
+                               {       releasenode(1, t->cond); /* T or t */
+                                       nc = True;
+                               } else if (!t->cond)
+                               {       releasenode(1, s->cond);
+                                       nc = True;
+                               } else
+                               {       nc = combination(s->cond, t->cond);
+                               }
+                               t->cond = rewrite(nc);
+                               t->merged = 1;
+                               s->redundant = 1;
+                               cnt++;
+                               break;
+       }       }       }
+       return cnt;
+}
+
+static int
+all_trans_match(State *a, State *b)
+{      Transition *s, *t;
+       int found, result = 0;
+
+       if (a->accepting != b->accepting)
+               goto done;
+
+       for (s = a->trans; s; s = s->nxt)
+       {       if (s->redundant) continue;
+               found = 0;
+               for (t = b->trans; t; t = t->nxt)
+               {       if (t->redundant) continue;
+                       if (sametrans(s, t))
+                       {       found = 1;
+                               t->marked = 1;
+                               break;
+               }       }
+               if (!found)
+                       goto done;
+       }
+       for (s = b->trans; s; s = s->nxt)
+       {       if (s->redundant || s->marked) continue;
+               found = 0;
+               for (t = a->trans; t; t = t->nxt)
+               {       if (t->redundant) continue;
+                       if (sametrans(s, t))
+                       {       found = 1;
+                               break;
+               }       }
+               if (!found)
+                       goto done;
+       }
+       result = 1;
+done:
+       for (s = b->trans; s; s = s->nxt)
+               s->marked = 0;
+       return result;
+}
+
+#ifndef NO_OPT
+#define BUCKY
+#endif
+
+#ifdef BUCKY
+static int
+all_bucky(State *a, State *b)
+{      Transition *s, *t;
+       int found, result = 0;
+
+       for (s = a->trans; s; s = s->nxt)
+       {       if (s->redundant) continue;
+               found = 0;
+               for (t = b->trans; t; t = t->nxt)
+               {       if (t->redundant) continue;
+
+                       if (isequal(s->cond, t->cond))
+                       {       if (strcmp(s->name->name, b->name->name) == 0
+                               &&  strcmp(t->name->name, a->name->name) == 0)
+                               {       found = 1;      /* they point to each other */
+                                       t->marked = 1;
+                                       break;
+                               }
+                               if (strcmp(s->name->name, t->name->name) == 0
+                               &&  strcmp(s->name->name, "accept_all") == 0)
+                               {       found = 1;
+                                       t->marked = 1;
+                                       break;
+                               /* same exit from which there is no return */
+                               }
+                       }
+               }
+               if (!found)
+                       goto done;
+       }
+       for (s = b->trans; s; s = s->nxt)
+       {       if (s->redundant || s->marked) continue;
+               found = 0;
+               for (t = a->trans; t; t = t->nxt)
+               {       if (t->redundant) continue;
+
+                       if (isequal(s->cond, t->cond))
+                       {       if (strcmp(s->name->name, a->name->name) == 0
+                               &&  strcmp(t->name->name, b->name->name) == 0)
+                               {       found = 1;
+                                       t->marked = 1;
+                                       break;
+                               }
+                               if (strcmp(s->name->name, t->name->name) == 0
+                               &&  strcmp(s->name->name, "accept_all") == 0)
+                               {       found = 1;
+                                       t->marked = 1;
+                                       break;
+                               }
+                       }
+               }
+               if (!found)
+                       goto done;
+       }
+       result = 1;
+done:
+       for (s = b->trans; s; s = s->nxt)
+               s->marked = 0;
+       return result;
+}
+
+static int
+buckyballs(void)
+{      State *a, *b, *c, *d;
+       int m, cnt=0;
+
+       do {
+               m = 0; cnt++;
+               for (a = never; a; a = a->nxt)
+               {       if (!a->reachable) continue;
+
+                       if (a->redundant) continue;
+
+                       for (b = a->nxt; b; b = b->nxt)
+                       {       if (!b->reachable) continue;
+
+                               if (b->redundant) continue;
+
+                               if (all_bucky(a, b))
+                               {       m++;
+                                       if (tl_verbose)
+                                       {       printf("%s bucky match %s\n",
+                                               a->name->name, b->name->name);
+                                       }
+
+                                       if (a->accepting && !b->accepting)
+                                       {       if (strcmp(b->name->name, "T0_init") == 0)
+                                               {       c = a; d = b;
+                                                       b->accepting = 1;
+                                               } else
+                                               {       c = b; d = a;
+                                               }
+                                       } else
+                                       {       c = a; d = b;
+                                       }
+
+                                       retarget(c->name->name, d->name->name);
+                                       if (!strncmp(c->name->name, "accept", 6)
+                                       &&  Max_Red == 0)
+                                       {       char buf[64];
+                                               sprintf(buf, "T0%s", &(c->name->name[6]));
+                                               retarget(buf, d->name->name);
+                                       }
+                                       break;
+                               }
+               }       }
+       } while (m && cnt < 10);
+       return cnt-1;
+}
+#endif
+
+static int
+mergestates(int v)
+{      State *a, *b;
+       int m, cnt=0;
+
+       if (tl_verbose)
+               return 0;
+
+       do {
+               m = 0; cnt++;
+               for (a = never; a; a = a->nxt)
+               {       if (v && !a->reachable) continue;
+
+                       if (a->redundant) continue; /* 3.3.10 */
+
+                       for (b = a->nxt; b; b = b->nxt)
+                       {       if (v && !b->reachable) continue;
+
+                               if (b->redundant) continue; /* 3.3.10 */
+
+                               if (all_trans_match(a, b))
+                               {       m++;
+                                       if (tl_verbose)
+                                       {       printf("%d: state %s equals state %s\n",
+                                               cnt, a->name->name, b->name->name);
+                                               showtrans(a);
+                                               printf("==\n");
+                                               showtrans(b);
+                                       }
+                                       retarget(a->name->name, b->name->name);
+                                       if (!strncmp(a->name->name, "accept", 6)
+                                       &&  Max_Red == 0)
+                                       {       char buf[64];
+                                               sprintf(buf, "T0%s", &(a->name->name[6]));
+                                               retarget(buf, b->name->name);
+                                       }
+                                       break;
+                               }
+#if 0
+                               else if (tl_verbose)
+                               {       printf("\n%d: state %s differs from state %s [%d,%d]\n",
+                                               cnt, a->name->name, b->name->name,
+                                               a->accepting, b->accepting);
+                                       showtrans(a);
+                                       printf("==\n");
+                                       showtrans(b);
+                                       printf("\n");
+                               }
+#endif
+               }       }
+       } while (m && cnt < 10);
+       return cnt-1;
+}
+
+static int tcnt;
+
+static void
+rev_trans(Transition *t) /* print transitions  in reverse order... */
+{
+       if (!t) return;
+       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);
+       tcnt++;
+}
+
+static void
+printstate(State *b)
+{
+       if (!b || (!tl_verbose && !b->reachable)) return;
+
+       b->reachable = 0;       /* print only once */
+       fprintf(tl_out, "%s:\n", b->name->name);
+
+       if (tl_verbose)
+       {       fprintf(tl_out, "       /* ");
+               dump(b->colors->Other);
+               fprintf(tl_out, " */\n");
+       }
+
+       if (strncmp(b->name->name, "accept", 6) == 0
+       &&  Max_Red == 0)
+               fprintf(tl_out, "T0%s:\n", &(b->name->name[6]));
+
+       fprintf(tl_out, "\tif\n");
+       tcnt = 0;
+       rev_trans(b->trans);
+       if (!tcnt) fprintf(tl_out, "\t:: false\n");
+       fprintf(tl_out, "\tfi;\n");
+       Total++;
+}
+
+void
+addtrans(Graph *col, char *from, Node *op, char *to)
+{      State *b;
+       Transition *t;
+
+       t = (Transition *) tl_emalloc(sizeof(Transition));
+       t->name = tl_lookup(to);
+       t->cond = Prune(dupnode(op));
+
+       if (tl_verbose)
+       {       printf("\n%s <<\t", from); dump(op);
+               printf("\n\t"); dump(t->cond);
+               printf(">> %s\n", t->name->name);
+       }
+       if (t->cond) t->cond = rewrite(t->cond);
+
+       for (b = never; b; b = b->nxt)
+               if (!strcmp(b->name->name, from))
+               {       t->nxt = b->trans;
+                       b->trans = t;
+                       return;
+               }
+       b = (State *) tl_emalloc(sizeof(State));
+       b->name   = tl_lookup(from);
+       b->colors = col;
+       b->trans  = t;
+       if (!strncmp(from, "accept", 6))
+               b->accepting = 1;
+       b->nxt = never;
+       never  = b;
+}
+
+static void
+clr_reach(void)
+{      State *p;
+       for (p = never; p; p = p->nxt)
+               p->reachable = 0;
+       hitsall = 0;
+}
+
+void
+fsm_print(void)
+{      State *b; int cnt1, cnt2=0;
+       extern void put_uform(void);
+
+       if (tl_clutter) clutter();
+
+       b = findstate("T0_init");
+       if (b && (Max_Red == 0))
+               b->accepting = 1;
+
+       mergestates(0); 
+       b = findstate("T0_init");
+
+       fprintf(tl_out, "never {    /* ");
+               put_uform();
+       fprintf(tl_out, " */\n");
+
+       do {
+               clr_reach();
+               Dfs(b);
+               cnt1 = mergetrans();
+               cnt2 = mergestates(1);
+               if (tl_verbose)
+                       printf("/* >>%d,%d<< */\n", cnt1, cnt2);
+       } while (cnt2 > 0);
+
+#ifdef BUCKY
+       buckyballs();
+       clr_reach();
+       Dfs(b);
+#endif
+       if (b && b->accepting)
+               fprintf(tl_out, "accept_init:\n");
+
+       if (!b && !never)
+       {       fprintf(tl_out, "       0 /* false */;\n");
+       } else
+       {       printstate(b);  /* init state must be first */
+               for (b = never; b; b = b->nxt)
+                       printstate(b);
+       }
+       if (hitsall)
+       fprintf(tl_out, "accept_all:\n  skip\n");
+       fprintf(tl_out, "}\n");
+}
diff --git a/trunk/verif/Spin/Src5.1.6/tl_cache.c b/trunk/verif/Spin/Src5.1.6/tl_cache.c
new file mode 100755 (executable)
index 0000000..fc902dc
--- /dev/null
@@ -0,0 +1,328 @@
+/***** 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            */
+
+/* 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 {
+       Node *before;
+       Node *after;
+       int same;
+       struct Cache *nxt;
+} Cache;
+
+static Cache   *stored = (Cache *) 0;
+static unsigned long   Caches, CacheHits;
+
+static int     ismatch(Node *, Node *);
+extern void fatal(char *, char *);
+int    sameform(Node *, Node *);
+
+#if 0
+void
+cache_dump(void)
+{      Cache *d; int nr=0;
+
+       printf("\nCACHE DUMP:\n");
+       for (d = stored; d; d = d->nxt, nr++)
+       {       if (d->same) continue;
+               printf("B%3d: ", nr); dump(d->before); printf("\n");
+               printf("A%3d: ", nr); dump(d->after); printf("\n");
+       }
+       printf("============\n");
+}
+#endif
+
+Node *
+in_cache(Node *n)
+{      Cache *d; int nr=0;
+
+       for (d = stored; d; d = d->nxt, nr++)
+               if (isequal(d->before, n))
+               {       CacheHits++;
+                       if (d->same && ismatch(n, d->before)) return n;
+                       return dupnode(d->after);
+               }
+       return ZN;
+}
+
+Node *
+cached(Node *n)
+{      Cache *d;
+       Node *m;
+
+       if (!n) return n;
+       if ((m = in_cache(n)) != ZN)
+               return m;
+
+       Caches++;
+       d = (Cache *) tl_emalloc(sizeof(Cache));
+       d->before = dupnode(n);
+       d->after  = Canonical(n); /* n is released */
+
+       if (ismatch(d->before, d->after))
+       {       d->same = 1;
+               releasenode(1, d->after);
+               d->after = d->before;
+       }
+       d->nxt = stored;
+       stored = d;
+       return dupnode(d->after);
+}
+
+void
+cache_stats(void)
+{
+       printf("cache stores     : %9ld\n", Caches);
+       printf("cache hits       : %9ld\n", CacheHits);
+}
+
+void
+releasenode(int all_levels, Node *n)
+{
+       if (!n) return;
+
+       if (all_levels)
+       {       releasenode(1, n->lft);
+               n->lft = ZN;
+               releasenode(1, n->rgt);
+               n->rgt = ZN;
+       }
+       tfree((void *) n);
+}
+
+Node *
+tl_nn(int t, Node *ll, Node *rl)
+{      Node *n = (Node *) tl_emalloc(sizeof(Node));
+
+       n->ntyp = (short) t;
+       n->lft  = ll;
+       n->rgt  = rl;
+
+       return n;
+}
+
+Node *
+getnode(Node *p)
+{      Node *n;
+
+       if (!p) return p;
+
+       n =  (Node *) tl_emalloc(sizeof(Node));
+       n->ntyp = p->ntyp;
+       n->sym  = p->sym; /* same name */
+       n->lft  = p->lft;
+       n->rgt  = p->rgt;
+
+       return n;
+}
+
+Node *
+dupnode(Node *n)
+{      Node *d;
+
+       if (!n) return n;
+       d = getnode(n);
+       d->lft = dupnode(n->lft);
+       d->rgt = dupnode(n->rgt);
+       return d;
+}
+
+int
+one_lft(int ntyp, Node *x, Node *in)
+{
+       if (!x)  return 1;
+       if (!in) return 0;
+
+       if (sameform(x, in))
+               return 1;
+
+       if (in->ntyp != ntyp)
+               return 0;
+
+       if (one_lft(ntyp, x, in->lft))
+               return 1;
+
+       return one_lft(ntyp, x, in->rgt);
+}
+
+int
+all_lfts(int ntyp, Node *from, Node *in)
+{
+       if (!from) return 1;
+
+       if (from->ntyp != ntyp)
+               return one_lft(ntyp, from, in);
+
+       if (!one_lft(ntyp, from->lft, in))
+               return 0;
+
+       return all_lfts(ntyp, from->rgt, in);
+}
+
+int
+sametrees(int ntyp, Node *a, Node *b)
+{      /* toplevel is an AND or OR */
+       /* both trees are right-linked, but the leafs */
+       /* can be in different places in the two trees */
+
+       if (!all_lfts(ntyp, a, b))
+               return 0;
+
+       return all_lfts(ntyp, b, a);
+}
+
+int    /* a better isequal() */
+sameform(Node *a, Node *b)
+{
+       if (!a && !b) return 1;
+       if (!a || !b) return 0;
+       if (a->ntyp != b->ntyp) return 0;
+
+       if (a->sym
+       &&  b->sym
+       &&  strcmp(a->sym->name, b->sym->name) != 0)
+               return 0;
+
+       switch (a->ntyp) {
+       case TRUE:
+       case FALSE:
+               return 1;
+       case PREDICATE:
+               if (!a->sym || !b->sym) fatal("sameform...", (char *) 0);
+               return !strcmp(a->sym->name, b->sym->name);
+
+       case NOT:
+#ifdef NXT
+       case NEXT:
+#endif
+               return sameform(a->lft, b->lft);
+       case U_OPER:
+       case V_OPER:
+               if (!sameform(a->lft, b->lft))
+                       return 0;
+               if (!sameform(a->rgt, b->rgt))
+                       return 0;
+               return 1;
+
+       case AND:
+       case OR:        /* the hard case */
+               return sametrees(a->ntyp, a, b);
+
+       default:
+               printf("type: %d\n", a->ntyp);
+               fatal("cannot happen, sameform", (char *) 0);
+       }
+
+       return 0;
+}
+
+int
+isequal(Node *a, Node *b)
+{
+       if (!a && !b)
+               return 1;
+
+       if (!a || !b)
+       {       if (!a)
+               {       if (b->ntyp == TRUE)
+                               return 1;
+               } else
+               {       if (a->ntyp == TRUE)
+                               return 1;
+               }
+               return 0;
+       }
+       if (a->ntyp != b->ntyp)
+               return 0;
+
+       if (a->sym
+       &&  b->sym
+       &&  strcmp(a->sym->name, b->sym->name) != 0)
+               return 0;
+
+       if (isequal(a->lft, b->lft)
+       &&  isequal(a->rgt, b->rgt))
+               return 1;
+
+       return sameform(a, b);
+}
+
+static int
+ismatch(Node *a, Node *b)
+{
+       if (!a && !b) return 1;
+       if (!a || !b) return 0;
+       if (a->ntyp != b->ntyp) return 0;
+
+       if (a->sym
+       &&  b->sym
+       &&  strcmp(a->sym->name, b->sym->name) != 0)
+               return 0;
+
+       if (ismatch(a->lft, b->lft)
+       &&  ismatch(a->rgt, b->rgt))
+               return 1;
+
+       return 0;
+}
+
+int
+any_term(Node *srch, Node *in)
+{
+       if (!in) return 0;
+
+       if (in->ntyp == AND)
+               return  any_term(srch, in->lft) ||
+                       any_term(srch, in->rgt);
+
+       return isequal(in, srch);
+}
+
+int
+any_and(Node *srch, Node *in)
+{
+       if (!in) return 0;
+
+       if (srch->ntyp == AND)
+               return  any_and(srch->lft, in) &&
+                       any_and(srch->rgt, in);
+
+       return any_term(srch, in);
+}
+
+int
+any_lor(Node *srch, Node *in)
+{
+       if (!in) return 0;
+
+       if (in->ntyp == OR)
+               return  any_lor(srch, in->lft) ||
+                       any_lor(srch, in->rgt);
+
+       return isequal(in, srch);
+}
+
+int
+anywhere(int tok, Node *srch, Node *in)
+{
+       if (!in) return 0;
+
+       switch (tok) {
+       case AND:       return any_and(srch, in);
+       case  OR:       return any_lor(srch, in);
+       case   0:       return any_term(srch, in);
+       }
+       fatal("cannot happen, anywhere", (char *) 0);
+       return 0;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/tl_lex.c b/trunk/verif/Spin/Src5.1.6/tl_lex.c
new file mode 100755 (executable)
index 0000000..110e06e
--- /dev/null
@@ -0,0 +1,148 @@
+/***** 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            */
+
+/* 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"
+
+static Symbol  *symtab[Nhash+1];
+static int     tl_lex(void);
+
+extern YYSTYPE tl_yylval;
+extern char    yytext[];
+
+#define Token(y)        tl_yylval = tl_nn(y,ZN,ZN); return y
+
+static void
+tl_getword(int first, int (*tst)(int))
+{      int i=0; char c;
+
+       yytext[i++] = (char ) first;
+       while (tst(c = tl_Getchar()))
+               yytext[i++] = c;
+       yytext[i] = '\0';
+       tl_UnGetchar();
+}
+
+static int
+tl_follow(int tok, int ifyes, int ifno)
+{      int c;
+       char buf[32];
+       extern int tl_yychar;
+
+       if ((c = tl_Getchar()) == tok)
+               return ifyes;
+       tl_UnGetchar();
+       tl_yychar = c;
+       sprintf(buf, "expected '%c'", tok);
+       tl_yyerror(buf);        /* no return from here */
+       return ifno;
+}
+
+int
+tl_yylex(void)
+{      int c = tl_lex();
+#if 0
+       printf("c = %d\n", c);
+#endif
+       return c;
+}
+
+static int
+tl_lex(void)
+{      int c;
+
+       do {
+               c = tl_Getchar();
+               yytext[0] = (char ) c;
+               yytext[1] = '\0';
+
+               if (c <= 0)
+               {       Token(';');
+               }
+
+       } while (c == ' ');     /* '\t' is removed in tl_main.c */
+
+       if (islower(c))
+       {       tl_getword(c, isalnum_);
+               if (strcmp("true", yytext) == 0)
+               {       Token(TRUE);
+               }
+               if (strcmp("false", yytext) == 0)
+               {       Token(FALSE);
+               }
+               tl_yylval = tl_nn(PREDICATE,ZN,ZN);
+               tl_yylval->sym = tl_lookup(yytext);
+               return PREDICATE;
+       }
+       if (c == '<')
+       {       c = tl_Getchar();
+               if (c == '>')
+               {       Token(EVENTUALLY);
+               }
+               if (c != '-')
+               {       tl_UnGetchar();
+                       tl_yyerror("expected '<>' or '<->'");
+               }
+               c = tl_Getchar();
+               if (c == '>')
+               {       Token(EQUIV);
+               }
+               tl_UnGetchar();
+               tl_yyerror("expected '<->'");
+       }
+
+       switch (c) {
+       case '/' : c = tl_follow('\\', AND, '/'); break;
+       case '\\': c = tl_follow('/', OR, '\\'); break;
+       case '&' : c = tl_follow('&', AND, '&'); break;
+       case '|' : c = tl_follow('|', OR, '|'); break;
+       case '[' : c = tl_follow(']', ALWAYS, '['); break;
+       case '-' : c = tl_follow('>', IMPLIES, '-'); break;
+       case '!' : c = NOT; break;
+       case 'U' : c = U_OPER; break;
+       case 'V' : c = V_OPER; break;
+#ifdef NXT
+       case 'X' : c = NEXT; break;
+#endif
+       default  : break;
+       }
+       Token(c);
+}
+
+Symbol *
+tl_lookup(char *s)
+{      Symbol *sp;
+       int h = hash(s);
+
+       for (sp = symtab[h]; sp; sp = sp->next)
+               if (strcmp(sp->name, s) == 0)
+                       return sp;
+
+       sp = (Symbol *) tl_emalloc(sizeof(Symbol));
+       sp->name = (char *) tl_emalloc((int) strlen(s) + 1);
+       strcpy(sp->name, s);
+       sp->next = symtab[h];
+       symtab[h] = sp;
+
+       return sp;
+}
+
+Symbol *
+getsym(Symbol *s)
+{      Symbol *n = (Symbol *) tl_emalloc(sizeof(Symbol));
+
+       n->name = s->name;
+       return n;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/tl_main.c b/trunk/verif/Spin/Src5.1.6/tl_main.c
new file mode 100755 (executable)
index 0000000..10ab0e9
--- /dev/null
@@ -0,0 +1,234 @@
+/***** 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            */
+
+/* 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;
+
+int    newstates  = 0; /* debugging only */
+int    tl_errs    = 0;
+int    tl_verbose = 0;
+int    tl_terse   = 0;
+int    tl_clutter = 0;
+unsigned long  All_Mem = 0;
+
+static char    uform[4096];
+static int     hasuform=0, cnt=0;
+
+extern void cache_stats(void);
+extern void a_stats(void);
+
+int
+tl_Getchar(void)
+{
+       if (cnt < hasuform)
+               return uform[cnt++];
+       cnt++;
+       return -1;
+}
+
+void
+tl_balanced(void)
+{      int i;
+       int k = 0;
+
+       for (i = 0; i < hasuform; i++)
+       {       if (uform[i] == '(')
+               {       k++;
+               } else if (uform[i] == ')')
+               {       k--;
+       }       }
+       if (k != 0)
+       {       tl_errs++;
+               tl_yyerror("parentheses not balanced");
+       }
+}
+
+void
+put_uform(void)
+{
+       fprintf(tl_out, "%s", uform);
+}
+
+void
+tl_UnGetchar(void)
+{
+       if (cnt > 0) cnt--;
+}
+
+static void
+tl_stats(void)
+{      extern int Stack_mx;
+       printf("total memory used: %9ld\n", All_Mem);
+       printf("largest stack sze: %9d\n", Stack_mx);
+       cache_stats();
+       a_stats();
+}
+
+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 */
+
+       while (argc > 1 && argv[1][0] == '-')
+       {       switch (argv[1][1]) {
+               case 'd':       newstates = 1;  /* debugging mode */
+                               break;
+               case 'f':       argc--; argv++;
+                               for (i = 0; i < argv[1][i]; i++)
+                               {       if (argv[1][i] == '\t'
+                                       ||  argv[1][i] == '\"'
+                                       ||  argv[1][i] == '\n')
+                                               argv[1][i] = ' ';
+                               }
+                               strcpy(uform, argv[1]);
+                               hasuform = (int) strlen(uform);
+                               break;
+               case 'v':       tl_verbose++;
+                               break;
+               case 'n':       tl_terse = 1;
+                               break;
+               default :       printf("spin -f: saw '-%c'\n", argv[1][1]);
+                               goto nogood;
+               }
+               argc--; argv++;
+       }
+       if (hasuform == 0)
+       {
+nogood:                printf("usage:\tspin [-v] [-n] -f formula\n");
+               printf("        -v verbose translation\n");
+               printf("        -n normalize tl formula and exit\n");
+               exit(1);
+       }
+       tl_balanced();
+
+       if (tl_errs == 0)
+               tl_parse();
+
+       if (tl_verbose) tl_stats();
+       return tl_errs;
+}
+
+#define Binop(a)               \
+               fprintf(tl_out, "(");   \
+               dump(n->lft);           \
+               fprintf(tl_out, a);     \
+               dump(n->rgt);           \
+               fprintf(tl_out, ")")
+
+void
+dump(Node *n)
+{
+       if (!n) return;
+
+       switch(n->ntyp) {
+       case OR:        Binop(" || "); break;
+       case AND:       Binop(" && "); break;
+       case U_OPER:    Binop(" U ");  break;
+       case V_OPER:    Binop(" V ");  break;
+#ifdef NXT
+       case NEXT:
+               fprintf(tl_out, "X");
+               fprintf(tl_out, " (");
+               dump(n->lft);
+               fprintf(tl_out, ")");
+               break;
+#endif
+       case NOT:
+               fprintf(tl_out, "!");
+               fprintf(tl_out, " (");
+               dump(n->lft);
+               fprintf(tl_out, ")");
+               break;
+       case FALSE:
+               fprintf(tl_out, "false");
+               break;
+       case TRUE:
+               fprintf(tl_out, "true");
+               break;
+       case PREDICATE:
+               fprintf(tl_out, "(%s)", n->sym->name);
+               break;
+       case -1:
+               fprintf(tl_out, " D ");
+               break;
+       default:
+               printf("Unknown token: ");
+               tl_explain(n->ntyp);
+               break;
+       }
+}
+
+void
+tl_explain(int n)
+{
+       switch (n) {
+       case ALWAYS:    printf("[]"); break;
+       case EVENTUALLY: printf("<>"); break;
+       case IMPLIES:   printf("->"); break;
+       case EQUIV:     printf("<->"); break;
+       case PREDICATE: printf("predicate"); break;
+       case OR:        printf("||"); break;
+       case AND:       printf("&&"); break;
+       case NOT:       printf("!"); break;
+       case U_OPER:    printf("U"); break;
+       case V_OPER:    printf("V"); break;
+#ifdef NXT
+       case NEXT:      printf("X"); break;
+#endif
+       case TRUE:      printf("true"); break;
+       case FALSE:     printf("false"); break;
+       case ';':       printf("end of formula"); break;
+       default:        printf("%c", n); break;
+       }
+}
+
+static void
+tl_non_fatal(char *s1, char *s2)
+{      extern int tl_yychar;
+       int i;
+
+       printf("tl_spin: ");
+       if (s2)
+               printf(s1, s2);
+       else
+               printf(s1);
+       if (tl_yychar != -1 && tl_yychar != 0)
+       {       printf(", saw '");
+               tl_explain(tl_yychar);
+               printf("'");
+       }
+       printf("\ntl_spin: %s\n---------", uform);
+       for (i = 0; i < cnt; i++)
+               printf("-");
+       printf("^\n");
+       fflush(stdout);
+       tl_errs++;
+}
+
+void
+tl_yyerror(char *s1)
+{
+       Fatal(s1, (char *) 0);
+}
+
+void
+Fatal(char *s1, char *s2)
+{
+       tl_non_fatal(s1, s2);
+       /* tl_stats(); */
+       exit(1);
+}
diff --git a/trunk/verif/Spin/Src5.1.6/tl_mem.c b/trunk/verif/Spin/Src5.1.6/tl_mem.c
new file mode 100755 (executable)
index 0000000..52021e4
--- /dev/null
@@ -0,0 +1,120 @@
+/***** 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.   */
+
+#include "tl.h"
+
+#if 1
+#define log(e, u, d)   event[e][(int) u] += (long) d;
+#else
+#define log(e, u, d)
+#endif
+
+#define A_LARGE                80
+#define A_USER         0x55000000
+#define NOTOOBIG       32768
+
+#define POOL           0
+#define ALLOC          1
+#define FREE           2
+#define NREVENT                3
+
+extern unsigned long All_Mem;
+extern int tl_verbose;
+
+union M {
+       long size;
+       union M *link;
+};
+
+static union M *freelist[A_LARGE];
+static long    req[A_LARGE];
+static long    event[NREVENT][A_LARGE];
+
+void *
+tl_emalloc(int U)
+{      union M *m;
+       long r, u;
+       void *rp;
+
+       u = (long) ((U-1)/sizeof(union M) + 2);
+
+       if (u >= A_LARGE)
+       {       log(ALLOC, 0, 1);
+               if (tl_verbose)
+               printf("tl_spin: memalloc %ld bytes\n", u);
+               m = (union M *) emalloc((int) u*sizeof(union M));
+               All_Mem += (unsigned long) u*sizeof(union M);
+       } else
+       {       if (!freelist[u])
+               {       r = req[u] += req[u] ? req[u] : 1;
+                       if (r >= NOTOOBIG)
+                               r = req[u] = NOTOOBIG;
+                       log(POOL, u, r);
+                       freelist[u] = (union M *)
+                               emalloc((int) r*u*sizeof(union M));
+                       All_Mem += (unsigned long) r*u*sizeof(union M);
+                       m = freelist[u] + (r-2)*u;
+                       for ( ; m >= freelist[u]; m -= u)
+                               m->link = m+u;
+               }
+               log(ALLOC, u, 1);
+               m = freelist[u];
+               freelist[u] = m->link;
+       }
+       m->size = (u|A_USER);
+
+       for (r = 1; r < u; )
+               (&m->size)[r++] = 0;
+
+       rp = (void *) (m+1);
+       memset(rp, 0, U);
+       return rp;
+}
+
+void
+tfree(void *v)
+{      union M *m = (union M *) v;
+       long u;
+
+       --m;
+       if ((m->size&0xFF000000) != A_USER)
+               Fatal("releasing a free block", (char *)0);
+
+       u = (m->size &= 0xFFFFFF);
+       if (u >= A_LARGE)
+       {       log(FREE, 0, 1);
+               /* free(m); */
+       } else
+       {       log(FREE, u, 1);
+               m->link = freelist[u];
+               freelist[u] = m;
+       }
+}
+
+void
+a_stats(void)
+{      long    p, a, f;
+       int     i;
+
+       printf(" size\t  pool\tallocs\t frees\n");
+       for (i = 0; i < A_LARGE; i++)
+       {       p = event[POOL][i];
+               a = event[ALLOC][i];
+               f = event[FREE][i];
+
+               if(p|a|f)
+               printf("%5d\t%6ld\t%6ld\t%6ld\n",
+                       i, p, a, f);
+       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/tl_parse.c b/trunk/verif/Spin/Src5.1.6/tl_parse.c
new file mode 100755 (executable)
index 0000000..6206a0d
--- /dev/null
@@ -0,0 +1,400 @@
+/***** 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            */
+
+/* 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);
+extern int     tl_verbose, tl_errs;
+
+int    tl_yychar = 0;
+YYSTYPE        tl_yylval;
+
+static Node    *tl_formula(void);
+static Node    *tl_factor(void);
+static Node    *tl_level(int);
+
+static int     prec[2][4] = {
+       { U_OPER,  V_OPER, 0, 0 },      /* left associative */
+       { OR, AND, IMPLIES, EQUIV, },   /* left associative */
+};
+
+static Node *
+tl_factor(void)
+{      Node *ptr = ZN;
+
+       switch (tl_yychar) {
+       case '(':
+               ptr = tl_formula();
+               if (tl_yychar != ')')
+                       tl_yyerror("expected ')'");
+               tl_yychar = tl_yylex();
+               break;
+       case NOT:
+               ptr = tl_yylval;
+               tl_yychar = tl_yylex();
+               ptr->lft = tl_factor();
+               ptr = push_negation(ptr);
+               break;
+       case ALWAYS:
+               tl_yychar = tl_yylex();
+
+               ptr = tl_factor();
+#ifndef NO_OPT
+               if (ptr->ntyp == FALSE
+               ||  ptr->ntyp == TRUE)
+                       break;  /* [] false == false */
+
+               if (ptr->ntyp == V_OPER)
+               {       if (ptr->lft->ntyp == FALSE)
+                               break;  /* [][]p = []p */
+
+                       ptr = ptr->rgt; /* [] (p V q) = [] q */
+               }
+#endif
+               ptr = tl_nn(V_OPER, False, ptr);
+               break;
+#ifdef NXT
+       case NEXT:
+               tl_yychar = tl_yylex();
+               ptr = tl_factor();
+               if (ptr->ntyp == TRUE)
+                       break;  /* X true = true */
+               ptr = tl_nn(NEXT, ptr, ZN);
+               break;
+#endif
+       case EVENTUALLY:
+               tl_yychar = tl_yylex();
+
+               ptr = tl_factor();
+#ifndef NO_OPT
+               if (ptr->ntyp == TRUE
+               ||  ptr->ntyp == FALSE)
+                       break;  /* <> true == true */
+
+               if (ptr->ntyp == U_OPER
+               &&  ptr->lft->ntyp == TRUE)
+                       break;  /* <><>p = <>p */
+
+               if (ptr->ntyp == U_OPER)
+               {       /* <> (p U q) = <> q */
+                       ptr = ptr->rgt;
+                       /* fall thru */
+               }
+#endif
+               ptr = tl_nn(U_OPER, True, ptr);
+
+               break;
+       case PREDICATE:
+               ptr = tl_yylval;
+               tl_yychar = tl_yylex();
+               break;
+       case TRUE:
+       case FALSE:
+               ptr = tl_yylval;
+               tl_yychar = tl_yylex();
+               break;
+       }
+       if (!ptr) tl_yyerror("expected predicate");
+#if 0
+       printf("factor: ");
+       tl_explain(ptr->ntyp);
+       printf("\n");
+#endif
+       return ptr;
+}
+
+static Node *
+bin_simpler(Node *ptr)
+{      Node *a, *b;
+
+       if (ptr)
+       switch (ptr->ntyp) {
+       case U_OPER:
+#ifndef NO_OPT
+               if (ptr->rgt->ntyp == TRUE
+               ||  ptr->rgt->ntyp == FALSE
+               ||  ptr->lft->ntyp == FALSE)
+               {       ptr = ptr->rgt;
+                       break;
+               }
+               if (isequal(ptr->lft, ptr->rgt))
+               {       /* p U p = p */ 
+                       ptr = ptr->rgt;
+                       break;
+               }
+               if (ptr->lft->ntyp == U_OPER
+               &&  isequal(ptr->lft->lft, ptr->rgt))
+               {       /* (p U q) U p = (q U p) */
+                       ptr->lft = ptr->lft->rgt;
+                       break;
+               }
+               if (ptr->rgt->ntyp == U_OPER
+               &&  ptr->rgt->lft->ntyp == TRUE)
+               {       /* p U (T U q)  = (T U q) */
+                       ptr = ptr->rgt;
+                       break;
+               }
+#ifdef NXT
+               /* X p U X q == X (p U q) */
+               if (ptr->rgt->ntyp == NEXT
+               &&  ptr->lft->ntyp == NEXT)
+               {       ptr = tl_nn(NEXT,
+                               tl_nn(U_OPER,
+                                       ptr->lft->lft,
+                                       ptr->rgt->lft), ZN);
+               }
+#endif
+#endif
+               break;
+       case V_OPER:
+#ifndef NO_OPT
+               if (ptr->rgt->ntyp == FALSE
+               ||  ptr->rgt->ntyp == TRUE
+               ||  ptr->lft->ntyp == TRUE)
+               {       ptr = ptr->rgt;
+                       break;
+               }
+               if (isequal(ptr->lft, ptr->rgt))
+               {       /* p V p = p */ 
+                       ptr = ptr->rgt;
+                       break;
+               }
+               /* F V (p V q) == F V q */
+               if (ptr->lft->ntyp == FALSE
+               &&  ptr->rgt->ntyp == V_OPER)
+               {       ptr->rgt = ptr->rgt->rgt;
+                       break;
+               }
+               /* p V (F V q) == F V q */
+               if (ptr->rgt->ntyp == V_OPER
+               &&  ptr->rgt->lft->ntyp == FALSE)
+               {       ptr->lft = False;
+                       ptr->rgt = ptr->rgt->rgt;
+                       break;
+               }
+#endif
+               break;
+       case IMPLIES:
+#ifndef NO_OPT
+               if (isequal(ptr->lft, ptr->rgt))
+               {       ptr = True;
+                       break;
+               }
+#endif
+               ptr = tl_nn(OR, Not(ptr->lft), ptr->rgt);
+               ptr = rewrite(ptr);
+               break;
+       case EQUIV:
+#ifndef NO_OPT
+               if (isequal(ptr->lft, ptr->rgt))
+               {       ptr = True;
+                       break;
+               }
+#endif
+               a = rewrite(tl_nn(AND,
+                       dupnode(ptr->lft),
+                       dupnode(ptr->rgt)));
+               b = rewrite(tl_nn(AND,
+                       Not(ptr->lft),
+                       Not(ptr->rgt)));
+               ptr = tl_nn(OR, a, b);
+               ptr = rewrite(ptr);
+               break;
+       case AND:
+#ifndef NO_OPT
+               /* p && (q U p) = p */
+               if (ptr->rgt->ntyp == U_OPER
+               &&  isequal(ptr->rgt->rgt, ptr->lft))
+               {       ptr = ptr->lft;
+                       break;
+               }
+               if (ptr->lft->ntyp == U_OPER
+               &&  isequal(ptr->lft->rgt, ptr->rgt))
+               {       ptr = ptr->rgt;
+                       break;
+               }
+
+               /* p && (q V p) == q V p */
+               if (ptr->rgt->ntyp == V_OPER
+               &&  isequal(ptr->rgt->rgt, ptr->lft))
+               {       ptr = ptr->rgt;
+                       break;
+               }
+               if (ptr->lft->ntyp == V_OPER
+               &&  isequal(ptr->lft->rgt, ptr->rgt))
+               {       ptr = ptr->lft;
+                       break;
+               }
+
+               /* (p U q) && (r U q) = (p && r) U q*/
+               if (ptr->rgt->ntyp == U_OPER
+               &&  ptr->lft->ntyp == U_OPER
+               &&  isequal(ptr->rgt->rgt, ptr->lft->rgt))
+               {       ptr = tl_nn(U_OPER,
+                               tl_nn(AND, ptr->lft->lft, ptr->rgt->lft),
+                               ptr->lft->rgt);
+                       break;
+               }
+
+               /* (p V q) && (p V r) = p V (q && r) */
+               if (ptr->rgt->ntyp == V_OPER
+               &&  ptr->lft->ntyp == V_OPER
+               &&  isequal(ptr->rgt->lft, ptr->lft->lft))
+               {       ptr = tl_nn(V_OPER,
+                               ptr->rgt->lft,
+                               tl_nn(AND, ptr->lft->rgt, ptr->rgt->rgt));
+                       break;
+               }
+#ifdef NXT
+               /* X p && X q == X (p && q) */
+               if (ptr->rgt->ntyp == NEXT
+               &&  ptr->lft->ntyp == NEXT)
+               {       ptr = tl_nn(NEXT,
+                               tl_nn(AND,
+                                       ptr->rgt->lft,
+                                       ptr->lft->lft), ZN);
+                       break;
+               }
+#endif
+
+               if (isequal(ptr->lft, ptr->rgt) /* (p && p) == p */
+               ||  ptr->rgt->ntyp == FALSE     /* (p && F) == F */
+               ||  ptr->lft->ntyp == TRUE)     /* (T && p) == p */
+               {       ptr = ptr->rgt;
+                       break;
+               }       
+               if (ptr->rgt->ntyp == TRUE      /* (p && T) == p */
+               ||  ptr->lft->ntyp == FALSE)    /* (F && p) == F */
+               {       ptr = ptr->lft;
+                       break;
+               }
+
+               /* (p V q) && (r U q) == p V q */
+               if (ptr->rgt->ntyp == U_OPER
+               &&  ptr->lft->ntyp == V_OPER
+               &&  isequal(ptr->lft->rgt, ptr->rgt->rgt))
+               {       ptr = ptr->lft;
+                       break;
+               }
+#endif
+               break;
+
+       case OR:
+#ifndef NO_OPT
+               /* p || (q U p) == q U p */
+               if (ptr->rgt->ntyp == U_OPER
+               &&  isequal(ptr->rgt->rgt, ptr->lft))
+               {       ptr = ptr->rgt;
+                       break;
+               }
+
+               /* p || (q V p) == p */
+               if (ptr->rgt->ntyp == V_OPER
+               &&  isequal(ptr->rgt->rgt, ptr->lft))
+               {       ptr = ptr->lft;
+                       break;
+               }
+
+               /* (p U q) || (p U r) = p U (q || r) */
+               if (ptr->rgt->ntyp == U_OPER
+               &&  ptr->lft->ntyp == U_OPER
+               &&  isequal(ptr->rgt->lft, ptr->lft->lft))
+               {       ptr = tl_nn(U_OPER,
+                               ptr->rgt->lft,
+                               tl_nn(OR, ptr->lft->rgt, ptr->rgt->rgt));
+                       break;
+               }
+
+               if (isequal(ptr->lft, ptr->rgt) /* (p || p) == p */
+               ||  ptr->rgt->ntyp == FALSE     /* (p || F) == p */
+               ||  ptr->lft->ntyp == TRUE)     /* (T || p) == T */
+               {       ptr = ptr->lft;
+                       break;
+               }       
+               if (ptr->rgt->ntyp == TRUE      /* (p || T) == T */
+               ||  ptr->lft->ntyp == FALSE)    /* (F || p) == p */
+               {       ptr = ptr->rgt;
+                       break;
+               }
+
+               /* (p V q) || (r V q) = (p || r) V q */
+               if (ptr->rgt->ntyp == V_OPER
+               &&  ptr->lft->ntyp == V_OPER
+               &&  isequal(ptr->lft->rgt, ptr->rgt->rgt))
+               {       ptr = tl_nn(V_OPER,
+                               tl_nn(OR, ptr->lft->lft, ptr->rgt->lft),
+                               ptr->rgt->rgt);
+                       break;
+               }
+
+               /* (p V q) || (r U q) == r U q */
+               if (ptr->rgt->ntyp == U_OPER
+               &&  ptr->lft->ntyp == V_OPER
+               &&  isequal(ptr->lft->rgt, ptr->rgt->rgt))
+               {       ptr = ptr->rgt;
+                       break;
+               }               
+#endif
+               break;
+       }
+       return ptr;
+}
+
+static Node *
+tl_level(int nr)
+{      int i; Node *ptr = ZN;
+
+       if (nr < 0)
+               return tl_factor();
+
+       ptr = tl_level(nr-1);
+again:
+       for (i = 0; i < 4; i++)
+               if (tl_yychar == prec[nr][i])
+               {       tl_yychar = tl_yylex();
+                       ptr = tl_nn(prec[nr][i],
+                               ptr, tl_level(nr-1));
+                       ptr = bin_simpler(ptr);
+                       goto again;
+               }
+       if (!ptr) tl_yyerror("syntax error");
+#if 0
+       printf("level %d:       ", nr);
+       tl_explain(ptr->ntyp);
+       printf("\n");
+#endif
+       return ptr;
+}
+
+static Node *
+tl_formula(void)
+{      tl_yychar = tl_yylex();
+       return tl_level(1);     /* 2 precedence levels, 1 and 0 */      
+}
+
+void
+tl_parse(void)
+{      Node *n = tl_formula();
+       if (tl_verbose)
+       {       printf("formula: ");
+               dump(n);
+               printf("\n");
+       }
+       if (tl_Getchar() != -1)
+       {       tl_yyerror("syntax error");
+               tl_errs++;
+               return;
+       }
+       trans(n);
+}
diff --git a/trunk/verif/Spin/Src5.1.6/tl_rewrt.c b/trunk/verif/Spin/Src5.1.6/tl_rewrt.c
new file mode 100755 (executable)
index 0000000..8a70b48
--- /dev/null
@@ -0,0 +1,304 @@
+/***** 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            */
+
+/* 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;
+
+static Node    *can = ZN;
+
+Node *
+right_linked(Node *n)
+{
+       if (!n) return n;
+
+       if (n->ntyp == AND || n->ntyp == OR)
+               while (n->lft && n->lft->ntyp == n->ntyp)
+               {       Node *tmp = n->lft;
+                       n->lft = tmp->rgt;
+                       tmp->rgt = n;
+                       n = tmp;
+               }
+
+       n->lft = right_linked(n->lft);
+       n->rgt = right_linked(n->rgt);
+
+       return n;
+}
+
+Node *
+canonical(Node *n)
+{      Node *m;        /* assumes input is right_linked */
+
+       if (!n) return n;
+       if ((m = in_cache(n)) != ZN)
+               return m;
+
+       n->rgt = canonical(n->rgt);
+       n->lft = canonical(n->lft);
+
+       return cached(n);
+}
+
+Node *
+push_negation(Node *n)
+{      Node *m;
+
+       Assert(n->ntyp == NOT, n->ntyp);
+
+       switch (n->lft->ntyp) {
+       case TRUE:
+               Debug("!true => false\n");
+               releasenode(0, n->lft);
+               n->lft = ZN;
+               n->ntyp = FALSE;
+               break;
+       case FALSE:
+               Debug("!false => true\n");
+               releasenode(0, n->lft);
+               n->lft = ZN;
+               n->ntyp = TRUE;
+               break;
+       case NOT:
+               Debug("!!p => p\n");
+               m = n->lft->lft;
+               releasenode(0, n->lft);
+               n->lft = ZN;
+               releasenode(0, n);
+               n = m;
+               break;
+       case V_OPER:
+               Debug("!(p V q) => (!p U !q)\n");
+               n->ntyp = U_OPER;
+               goto same;
+       case U_OPER:
+               Debug("!(p U q) => (!p V !q)\n");
+               n->ntyp = V_OPER;
+               goto same;
+#ifdef NXT
+       case NEXT:
+               Debug("!X -> X!\n");
+               n->ntyp = NEXT;
+               n->lft->ntyp = NOT;
+               n->lft = push_negation(n->lft);
+               break;
+#endif
+       case  AND:
+               Debug("!(p && q) => !p || !q\n"); 
+               n->ntyp = OR;
+               goto same;
+       case  OR:
+               Debug("!(p || q) => !p && !q\n");
+               n->ntyp = AND;
+
+same:          m = n->lft->rgt;
+               n->lft->rgt = ZN;
+
+               n->rgt = Not(m);
+               n->lft->ntyp = NOT;
+               m = n->lft;
+               n->lft = push_negation(m);
+               break;
+       }
+
+       return rewrite(n);
+}
+
+static void
+addcan(int tok, Node *n)
+{      Node    *m, *prev = ZN;
+       Node    **ptr;
+       Node    *N;
+       Symbol  *s, *t; int cmp;
+
+       if (!n) return;
+
+       if (n->ntyp == tok)
+       {       addcan(tok, n->rgt);
+               addcan(tok, n->lft);
+               return;
+       }
+
+       N = dupnode(n);
+       if (!can)       
+       {       can = N;
+               return;
+       }
+
+       s = DoDump(N);
+       if (can->ntyp != tok)   /* only one element in list so far */
+       {       ptr = &can;
+               goto insert;
+       }
+
+       /* there are at least 2 elements in list */
+       prev = ZN;
+       for (m = can; m->ntyp == tok && m->rgt; prev = m, m = m->rgt)
+       {       t = DoDump(m->lft);
+               if (t != ZS)
+                       cmp = strcmp(s->name, t->name);
+               else
+                       cmp = 0;
+               if (cmp == 0)   /* duplicate */
+                       return;
+               if (cmp < 0)
+               {       if (!prev)
+                       {       can = tl_nn(tok, N, can);
+                               return;
+                       } else
+                       {       ptr = &(prev->rgt);
+                               goto insert;
+       }       }       }
+
+       /* new entry goes at the end of the list */
+       ptr = &(prev->rgt);
+insert:
+       t = DoDump(*ptr);
+       cmp = strcmp(s->name, t->name);
+       if (cmp == 0)   /* duplicate */
+               return;
+       if (cmp < 0)
+               *ptr = tl_nn(tok, N, *ptr);
+       else
+               *ptr = tl_nn(tok, *ptr, N);
+}
+
+static void
+marknode(int tok, Node *m)
+{
+       if (m->ntyp != tok)
+       {       releasenode(0, m->rgt);
+               m->rgt = ZN;
+       }
+       m->ntyp = -1;
+}
+
+Node *
+Canonical(Node *n)
+{      Node *m, *p, *k1, *k2, *prev, *dflt = ZN;
+       int tok;
+
+       if (!n) return n;
+
+       tok = n->ntyp;
+       if (tok != AND && tok != OR)
+               return n;
+
+       can = ZN;
+       addcan(tok, n);
+#if 0
+       Debug("\nA0: "); Dump(can); 
+       Debug("\nA1: "); Dump(n); Debug("\n");
+#endif
+       releasenode(1, n);
+
+       /* mark redundant nodes */
+       if (tok == AND)
+       {       for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN)
+               {       k1 = (m->ntyp == AND) ? m->lft : m;
+                       if (k1->ntyp == TRUE)
+                       {       marknode(AND, m);
+                               dflt = True;
+                               continue;
+                       }
+                       if (k1->ntyp == FALSE)
+                       {       releasenode(1, can);
+                               can = False;
+                               goto out;
+               }       }
+               for (m = can; m; m = (m->ntyp == AND) ? m->rgt : ZN)
+               for (p = can; p; p = (p->ntyp == AND) ? p->rgt : ZN)
+               {       if (p == m
+                       ||  p->ntyp == -1
+                       ||  m->ntyp == -1)
+                               continue;
+                       k1 = (m->ntyp == AND) ? m->lft : m;
+                       k2 = (p->ntyp == AND) ? p->lft : p;
+
+                       if (isequal(k1, k2))
+                       {       marknode(AND, p);
+                               continue;
+                       }
+                       if (anywhere(OR, k1, k2))
+                       {       marknode(AND, p);
+                               continue;
+                       }
+       }       }
+       if (tok == OR)
+       {       for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
+               {       k1 = (m->ntyp == OR) ? m->lft : m;
+                       if (k1->ntyp == FALSE)
+                       {       marknode(OR, m);
+                               dflt = False;
+                               continue;
+                       }
+                       if (k1->ntyp == TRUE)
+                       {       releasenode(1, can);
+                               can = True;
+                               goto out;
+               }       }
+               for (m = can; m; m = (m->ntyp == OR) ? m->rgt : ZN)
+               for (p = can; p; p = (p->ntyp == OR) ? p->rgt : ZN)
+               {       if (p == m
+                       ||  p->ntyp == -1
+                       ||  m->ntyp == -1)
+                               continue;
+                       k1 = (m->ntyp == OR) ? m->lft : m;
+                       k2 = (p->ntyp == OR) ? p->lft : p;
+
+                       if (isequal(k1, k2))
+                       {       marknode(OR, p);
+                               continue;
+                       }
+                       if (anywhere(AND, k1, k2))
+                       {       marknode(OR, p);
+                               continue;
+                       }
+       }       }
+       for (m = can, prev = ZN; m; )   /* remove marked nodes */
+       {       if (m->ntyp == -1)
+               {       k2 = m->rgt;
+                       releasenode(0, m);
+                       if (!prev)
+                       {       m = can = can->rgt;
+                       } else
+                       {       m = prev->rgt = k2;
+                               /* if deleted the last node in a chain */
+                               if (!prev->rgt && prev->lft
+                               &&  (prev->ntyp == AND || prev->ntyp == OR))
+                               {       k1 = prev->lft;
+                                       prev->ntyp = prev->lft->ntyp;
+                                       prev->sym = prev->lft->sym;
+                                       prev->rgt = prev->lft->rgt;
+                                       prev->lft = prev->lft->lft;
+                                       releasenode(0, k1);
+                               }
+                       }
+                       continue;
+               }
+               prev = m;
+               m = m->rgt;
+       }
+out:
+#if 0
+       Debug("A2: "); Dump(can); Debug("\n");
+#endif
+       if (!can)
+       {       if (!dflt)
+                       fatal("cannot happen, Canonical", (char *) 0);
+               return dflt;
+       }
+
+       return can;
+}
diff --git a/trunk/verif/Spin/Src5.1.6/tl_trans.c b/trunk/verif/Spin/Src5.1.6/tl_trans.c
new file mode 100755 (executable)
index 0000000..c3992a2
--- /dev/null
@@ -0,0 +1,878 @@
+/***** 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            */
+
+/* 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;
+
+int    Stack_mx=0, Max_Red=0, Total=0;
+
+static Mapping *Mapped = (Mapping *) 0;
+static Graph   *Nodes_Set = (Graph *) 0;
+static Graph   *Nodes_Stack = (Graph *) 0;
+
+static char    dumpbuf[2048];
+static int     Red_cnt  = 0;
+static int     Lab_cnt  = 0;
+static int     Base     = 0;
+static int     Stack_sz = 0;
+
+static Graph   *findgraph(char *);
+static Graph   *pop_stack(void);
+static Node    *Duplicate(Node *);
+static Node    *flatten(Node *);
+static Symbol  *catSlist(Symbol *, Symbol *);
+static Symbol  *dupSlist(Symbol *);
+static char    *newname(void);
+static int     choueka(Graph *, int);
+static int     not_new(Graph *);
+static int     set_prefix(char *, int, Graph *);
+static void    Addout(char *, char *);
+static void    fsm_trans(Graph *, int, char *);
+static void    mkbuchi(void);
+static void    expand_g(Graph *);
+static void    fixinit(Node *);
+static void    liveness(Node *);
+static void    mk_grn(Node *);
+static void    mk_red(Node *);
+static void    ng(Symbol *, Symbol *, Node *, Node *, Node *);
+static void    push_stack(Graph *);
+static void    sdump(Node *);
+
+static void
+dump_graph(Graph *g)
+{      Node *n1;
+
+       printf("\n\tnew:\t");
+       for (n1 = g->New; n1; n1 = n1->nxt)
+       { dump(n1); printf(", "); }
+       printf("\n\told:\t");
+       for (n1 = g->Old; n1; n1 = n1->nxt)
+       { dump(n1); printf(", "); }
+       printf("\n\tnxt:\t");
+       for (n1 = g->Next; n1; n1 = n1->nxt)
+       { dump(n1); printf(", "); }
+       printf("\n\tother:\t");
+       for (n1 = g->Other; n1; n1 = n1->nxt)
+       { dump(n1); printf(", "); }
+       printf("\n");
+}
+
+static void
+push_stack(Graph *g)
+{
+       if (!g) return;
+
+       g->nxt = Nodes_Stack;
+       Nodes_Stack = g;
+       if (tl_verbose)
+       {       Symbol *z;
+               printf("\nPush %s, from ", g->name->name);
+               for (z = g->incoming; z; z = z->next)
+                       printf("%s, ", z->name);
+               dump_graph(g);
+       }
+       Stack_sz++;
+       if (Stack_sz > Stack_mx) Stack_mx = Stack_sz;
+}
+
+static Graph *
+pop_stack(void)
+{      Graph *g = Nodes_Stack;
+
+       if (g) Nodes_Stack = g->nxt;
+
+       Stack_sz--;
+
+       return g;
+}
+
+static char *
+newname(void)
+{      static int cnt = 0;
+       static char buf[32];
+       sprintf(buf, "S%d", cnt++);
+       return buf;
+}
+
+static int
+has_clause(int tok, Graph *p, Node *n)
+{      Node *q, *qq;
+
+       switch (n->ntyp) {
+       case AND:
+               return  has_clause(tok, p, n->lft) &&
+                       has_clause(tok, p, n->rgt);
+       case OR:
+               return  has_clause(tok, p, n->lft) ||
+                       has_clause(tok, p, n->rgt);
+       }
+
+       for (q = p->Other; q; q = q->nxt)
+       {       qq = right_linked(q);
+               if (anywhere(tok, n, qq))
+                       return 1;
+       }
+       return 0;
+}
+
+static void
+mk_grn(Node *n)
+{      Graph *p;
+
+       n = right_linked(n);
+more:
+       for (p = Nodes_Set; p; p = p->nxt)
+               if (p->outgoing
+               &&  has_clause(AND, p, n))
+               {       p->isgrn[p->grncnt++] =
+                               (unsigned char) Red_cnt;
+                       Lab_cnt++;
+               }
+
+       if (n->ntyp == U_OPER)  /* 3.4.0 */
+       {       n = n->rgt;
+               goto more;
+       }
+}
+
+static void
+mk_red(Node *n)
+{      Graph *p;
+
+       n = right_linked(n);
+       for (p = Nodes_Set; p; p = p->nxt)
+       {       if (p->outgoing
+               &&  has_clause(0, p, n))
+               {       if (p->redcnt >= 63)
+                               Fatal("too many Untils", (char *)0);
+                       p->isred[p->redcnt++] =
+                               (unsigned char) Red_cnt;
+                       Lab_cnt++; Max_Red = Red_cnt;
+       }       }
+}
+
+static void
+liveness(Node *n)
+{
+       if (n)
+       switch (n->ntyp) {
+#ifdef NXT
+       case NEXT:
+               liveness(n->lft);
+               break;
+#endif
+       case U_OPER:
+               Red_cnt++;
+               mk_red(n);
+               mk_grn(n->rgt);
+               /* fall through */
+       case V_OPER:
+       case OR: case AND:
+               liveness(n->lft);
+               liveness(n->rgt);
+               break;
+       }
+}
+
+static Graph *
+findgraph(char *nm)
+{      Graph   *p;
+       Mapping *m;
+
+       for (p = Nodes_Set; p; p = p->nxt)
+               if (!strcmp(p->name->name, nm))
+                       return p;
+       for (m = Mapped; m; m = m->nxt)
+               if (strcmp(m->from, nm) == 0)
+                       return m->to;
+
+       printf("warning: node %s not found\n", nm);
+       return (Graph *) 0;
+}
+
+static void
+Addout(char *to, char *from)
+{      Graph   *p = findgraph(from);
+       Symbol  *s;
+
+       if (!p) return;
+       s = getsym(tl_lookup(to));
+       s->next = p->outgoing;
+       p->outgoing = s;
+}
+
+#ifdef NXT
+int
+only_nxt(Node *n)
+{
+       switch (n->ntyp) {
+       case NEXT:
+               return 1;
+       case OR:
+       case AND:
+               return only_nxt(n->rgt) && only_nxt(n->lft);
+       default:
+               return 0;
+       }
+}
+#endif
+
+int
+dump_cond(Node *pp, Node *r, int first)
+{      Node *q;
+       int frst = first;
+
+       if (!pp) return frst;
+
+       q = dupnode(pp);
+       q = rewrite(q);
+
+       if (q->ntyp == PREDICATE
+       ||  q->ntyp == NOT
+#ifndef NXT
+       ||  q->ntyp == OR
+#endif
+       ||  q->ntyp == FALSE)
+       {       if (!frst) fprintf(tl_out, " && ");
+               dump(q);
+               frst = 0;
+#ifdef NXT
+       } else if (q->ntyp == OR)
+       {       if (!frst) fprintf(tl_out, " && ");
+               fprintf(tl_out, "((");
+               frst = dump_cond(q->lft, r, 1);
+
+               if (!frst)
+                       fprintf(tl_out, ") || (");
+               else
+               {       if (only_nxt(q->lft))
+                       {       fprintf(tl_out, "1))");
+                               return 0;
+                       }
+               }
+
+               frst = dump_cond(q->rgt, r, 1);
+
+               if (frst)
+               {       if (only_nxt(q->rgt))
+                               fprintf(tl_out, "1");
+                       else
+                               fprintf(tl_out, "0");
+                       frst = 0;
+               }
+
+               fprintf(tl_out, "))");
+#endif
+       } else  if (q->ntyp == V_OPER
+               && !anywhere(AND, q->rgt, r))
+       {       frst = dump_cond(q->rgt, r, frst);
+       } else  if (q->ntyp == AND)
+       {
+               frst = dump_cond(q->lft, r, frst);
+               frst = dump_cond(q->rgt, r, frst);
+       }
+
+       return frst;
+}
+
+static int
+choueka(Graph *p, int count)
+{      int j, k, incr_cnt = 0;
+
+       for (j = count; j <= Max_Red; j++) /* for each acceptance class */
+       {       int delta = 0;
+
+               /* is state p labeled Grn-j OR not Red-j ? */
+
+               for (k = 0; k < (int) p->grncnt; k++)
+                       if (p->isgrn[k] == j)
+                       {       delta = 1;
+                               break;
+                       }
+               if (delta)
+               {       incr_cnt++;
+                       continue;
+               }
+               for (k = 0; k < (int) p->redcnt; k++)
+                       if (p->isred[k] == j)
+                       {       delta = 1;
+                               break;
+                       }
+
+               if (delta) break;
+
+               incr_cnt++;
+       }
+       return incr_cnt;
+}
+
+static int
+set_prefix(char *pref, int count, Graph *r2)
+{      int incr_cnt = 0;       /* acceptance class 'count' */
+
+       if (Lab_cnt == 0
+       ||  Max_Red == 0)
+               sprintf(pref, "accept");        /* new */
+       else if (count >= Max_Red)
+               sprintf(pref, "T0");            /* cycle */
+       else
+       {       incr_cnt = choueka(r2, count+1);
+               if (incr_cnt + count >= Max_Red)
+                       sprintf(pref, "accept"); /* last hop */
+               else
+                       sprintf(pref, "T%d", count+incr_cnt);
+       }
+       return incr_cnt;
+}
+
+static void
+fsm_trans(Graph *p, int count, char *curnm)
+{      Graph   *r;
+       Symbol  *s;
+       char    prefix[128], nwnm[256];
+
+       if (!p->outgoing)
+               addtrans(p, curnm, False, "accept_all");
+
+       for (s = p->outgoing; s; s = s->next)
+       {       r = findgraph(s->name);
+               if (!r) continue;
+               if (r->outgoing)
+               {       (void) set_prefix(prefix, count, r);
+                       sprintf(nwnm, "%s_%s", prefix, s->name);
+               } else
+                       strcpy(nwnm, "accept_all");
+
+               if (tl_verbose)
+               {       printf("maxred=%d, count=%d, curnm=%s, nwnm=%s ",
+                               Max_Red, count, curnm, nwnm);
+                       printf("(greencnt=%d,%d, redcnt=%d,%d)\n",
+                               r->grncnt, r->isgrn[0],
+                               r->redcnt, r->isred[0]);
+               }
+               addtrans(p, curnm, r->Old, nwnm);
+       }
+}
+
+static void
+mkbuchi(void)
+{      Graph   *p;
+       int     k;
+       char    curnm[64];
+
+       for (k = 0; k <= Max_Red; k++)
+       for (p = Nodes_Set; p; p = p->nxt)
+       {       if (!p->outgoing)
+                       continue;
+               if (k != 0
+               && !strcmp(p->name->name, "init")
+               &&  Max_Red != 0)
+                       continue;
+
+               if (k == Max_Red
+               &&  strcmp(p->name->name, "init") != 0)
+                       strcpy(curnm, "accept_");
+               else
+                       sprintf(curnm, "T%d_", k);
+
+               strcat(curnm, p->name->name);
+
+               fsm_trans(p, k, curnm);
+       }
+       fsm_print();
+}
+
+static Symbol *
+dupSlist(Symbol *s)
+{      Symbol *p1, *p2, *p3, *d = ZS;
+
+       for (p1 = s; p1; p1 = p1->next)
+       {       for (p3 = d; p3; p3 = p3->next)
+               {       if (!strcmp(p3->name, p1->name))
+                               break;
+               }
+               if (p3) continue;       /* a duplicate */
+
+               p2 = getsym(p1);
+               p2->next = d;
+               d = p2;
+       }
+       return d;
+}
+
+static Symbol *
+catSlist(Symbol *a, Symbol *b)
+{      Symbol *p1, *p2, *p3, *tmp;
+
+       /* remove duplicates from b */
+       for (p1 = a; p1; p1 = p1->next)
+       {       p3 = ZS;
+               for (p2 = b; p2; p2 = p2->next)
+               {       if (strcmp(p1->name, p2->name))
+                       {       p3 = p2;
+                               continue;
+                       }
+                       tmp = p2->next;
+                       tfree((void *) p2);
+                       if (p3)
+                               p3->next = tmp;
+                       else
+                               b = tmp;
+       }       }
+       if (!a) return b;
+       if (!b) return a;
+       if (!b->next)
+       {       b->next = a;
+               return b;
+       }
+       /* find end of list */
+       for (p1 = a; p1->next; p1 = p1->next)
+               ;
+       p1->next = b;
+       return a;
+}
+
+static void
+fixinit(Node *orig)
+{      Graph   *p1, *g;
+       Symbol  *q1, *q2 = ZS;
+
+       ng(tl_lookup("init"), ZS, ZN, ZN, ZN);
+       p1 = pop_stack();
+       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)
+               {       q2 = q1->next;
+                       Addout(g->name->name, q1->name);
+                       tfree((void *) q1);
+               }
+               g->incoming = ZS;
+       }
+}
+
+static Node *
+flatten(Node *p)
+{      Node *q, *r, *z = ZN;
+
+       for (q = p; q; q = q->nxt)
+       {       r = dupnode(q);
+               if (z)
+                       z = tl_nn(AND, r, z);
+               else
+                       z = r;
+       }
+       if (!z) return z;
+       z = rewrite(z);
+       return z;
+}
+
+static Node *
+Duplicate(Node *n)
+{      Node *n1, *n2, *lst = ZN, *d = ZN;
+
+       for (n1 = n; n1; n1 = n1->nxt)
+       {       n2 = dupnode(n1);
+               if (lst)
+               {       lst->nxt = n2;
+                       lst = n2;
+               } else
+                       d = lst = n2;
+       }
+       return d;
+}
+
+static void
+ng(Symbol *s, Symbol *in, Node *isnew, Node *isold, Node *next)
+{      Graph *g = (Graph *) tl_emalloc(sizeof(Graph));
+
+       if (s)     g->name = s;
+       else       g->name = tl_lookup(newname());
+
+       if (in)    g->incoming = dupSlist(in);
+       if (isnew) g->New  = flatten(isnew);
+       if (isold) g->Old  = Duplicate(isold);
+       if (next)  g->Next = flatten(next);
+
+       push_stack(g);
+}
+
+static void
+sdump(Node *n)
+{
+       switch (n->ntyp) {
+       case PREDICATE: strcat(dumpbuf, n->sym->name);
+                       break;
+       case U_OPER:    strcat(dumpbuf, "U");
+                       goto common2;
+       case V_OPER:    strcat(dumpbuf, "V");
+                       goto common2;
+       case OR:        strcat(dumpbuf, "|");
+                       goto common2;
+       case AND:       strcat(dumpbuf, "&");
+common2:               sdump(n->rgt);
+common1:               sdump(n->lft);
+                       break;
+#ifdef NXT
+       case NEXT:      strcat(dumpbuf, "X");
+                       goto common1;
+#endif
+       case NOT:       strcat(dumpbuf, "!");
+                       goto common1;
+       case TRUE:      strcat(dumpbuf, "T");
+                       break;
+       case FALSE:     strcat(dumpbuf, "F");
+                       break;
+       default:        strcat(dumpbuf, "?");
+                       break;
+       }
+}
+
+Symbol *
+DoDump(Node *n)
+{
+       if (!n) return ZS;
+
+       if (n->ntyp == PREDICATE)
+               return n->sym;
+
+       dumpbuf[0] = '\0';
+       sdump(n);
+       return tl_lookup(dumpbuf);
+}
+
+static int
+not_new(Graph *g)
+{      Graph   *q1; Node *tmp, *n1, *n2;
+       Mapping *map;
+
+       tmp = flatten(g->Old);  /* duplicate, collapse, normalize */
+       g->Other = g->Old;      /* non normalized full version */
+       g->Old = tmp;
+
+       g->oldstring = DoDump(g->Old);
+
+       tmp = flatten(g->Next);
+       g->nxtstring = DoDump(tmp);
+
+       if (tl_verbose) dump_graph(g);
+
+       Debug2("\tformula-old: [%s]\n", g->oldstring?g->oldstring->name:"true");
+       Debug2("\tformula-nxt: [%s]\n", g->nxtstring?g->nxtstring->name:"true");
+       for (q1 = Nodes_Set; q1; q1 = q1->nxt)
+       {       Debug2("        compare old to: %s", q1->name->name);
+               Debug2(" [%s]", q1->oldstring?q1->oldstring->name:"true");
+
+               Debug2("        compare nxt to: %s", q1->name->name);
+               Debug2(" [%s]", q1->nxtstring?q1->nxtstring->name:"true");
+
+               if (q1->oldstring != g->oldstring
+               ||  q1->nxtstring != g->nxtstring)
+               {       Debug(" => different\n");
+                       continue;
+               }
+               Debug(" => match\n");
+
+               if (g->incoming)
+                       q1->incoming = catSlist(g->incoming, q1->incoming);
+
+               /* check if there's anything in g->Other that needs
+                  adding to q1->Other
+               */
+               for (n2 = g->Other; n2; n2 = n2->nxt)
+               {       for (n1 = q1->Other; n1; n1 = n1->nxt)
+                               if (isequal(n1, n2))
+                                       break;
+                       if (!n1)
+                       {       Node *n3 = dupnode(n2);
+                               /* don't mess up n2->nxt */
+                               n3->nxt = q1->Other;
+                               q1->Other = n3;
+               }       }
+
+               map = (Mapping *) tl_emalloc(sizeof(Mapping));
+               map->from = g->name->name;
+               map->to   = q1;
+               map->nxt = Mapped;
+               Mapped = map;
+
+               for (n1 = g->Other; n1; n1 = n2)
+               {       n2 = n1->nxt;
+                       releasenode(1, n1);
+               }
+               for (n1 = g->Old; n1; n1 = n2)
+               {       n2 = n1->nxt;
+                       releasenode(1, n1);
+               }
+               for (n1 = g->Next; n1; n1 = n2)
+               {       n2 = n1->nxt;
+                       releasenode(1, n1);
+               }
+               return 1;
+       }
+
+       if (newstates) tl_verbose=1;
+       Debug2("        New Node %s [", g->name->name);
+       for (n1 = g->Old; n1; n1 = n1->nxt)
+       { Dump(n1); Debug(", "); }
+       Debug2("] nr %d\n", Base);
+       if (newstates) tl_verbose=0;
+
+       Base++;
+       g->nxt = Nodes_Set;
+       Nodes_Set = g;
+
+       return 0;
+}
+
+static void
+expand_g(Graph *g)
+{      Node *now, *n1, *n2, *nx;
+       int can_release;
+
+       if (!g->New)
+       {       Debug2("\nDone with %s", g->name->name);
+               if (tl_verbose) dump_graph(g);
+               if (not_new(g))
+               {       if (tl_verbose) printf("\tIs Not New\n");
+                       return;
+               }
+               if (g->Next)
+               {       Debug(" Has Next [");
+                       for (n1 = g->Next; n1; n1 = n1->nxt)
+                       { Dump(n1); Debug(", "); }
+                       Debug("]\n");
+
+                       ng(ZS, getsym(g->name), g->Next, ZN, ZN);
+               }
+               return;
+       }
+
+       if (tl_verbose)
+       {       Symbol *z;
+               printf("\nExpand %s, from ", g->name->name);
+               for (z = g->incoming; z; z = z->next)
+                       printf("%s, ", z->name);
+               printf("\n\thandle:\t"); Explain(g->New->ntyp);
+               dump_graph(g);
+       }
+
+       if (g->New->ntyp == AND)
+       {       if (g->New->nxt)
+               {       n2 = g->New->rgt;
+                       while (n2->nxt)
+                               n2 = n2->nxt;
+                       n2->nxt = g->New->nxt;
+               }
+               n1 = n2 = g->New->lft;
+               while (n2->nxt)
+                       n2 = n2->nxt;
+               n2->nxt = g->New->rgt;
+
+               releasenode(0, g->New);
+
+               g->New = n1;
+               push_stack(g);
+               return;
+       }
+
+       can_release = 0;        /* unless it need not go into Old */
+       now = g->New;
+       g->New = g->New->nxt;
+       now->nxt = ZN;
+
+       if (now->ntyp != TRUE)
+       {       if (g->Old)
+               {       for (n1 = g->Old; n1->nxt; n1 = n1->nxt)
+                               if (isequal(now, n1))
+                               {       can_release = 1;
+                                       goto out;
+                               }
+                       n1->nxt = now;
+               } else
+                       g->Old = now;
+       }
+out:
+       switch (now->ntyp) {
+       case FALSE:
+               push_stack(g);
+               break;
+       case TRUE:
+               releasenode(1, now);
+               push_stack(g);
+               break;
+       case PREDICATE:
+       case NOT:
+               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;
+               n1->nxt = g->New;
+
+               if (can_release)
+                       nx = now;
+               else
+                       nx = getnode(now); /* now also appears in Old */
+               nx->nxt = g->Next;
+
+               n2 = now->lft;
+               n2->nxt = getnode(now->rgt);
+               n2->nxt->nxt = g->New;
+               g->New = flatten(n2);
+               push_stack(g);
+               ng(ZS, g->incoming, n1, g->Old, nx);
+               break;
+
+       case U_OPER:
+               Assert(now->rgt->nxt == ZN, now->ntyp);
+               Assert(now->lft->nxt == ZN, now->ntyp);
+               n1 = now->lft;
+
+               if (can_release)
+                       nx = now;
+               else
+                       nx = getnode(now); /* now also appears in Old */
+               nx->nxt = g->Next;
+
+               n2 = now->rgt;
+               n2->nxt = g->New;
+
+               goto common;
+
+#ifdef NXT
+       case NEXT:
+               Assert(now->lft != ZN, now->ntyp);
+               nx = dupnode(now->lft);
+               nx->nxt = g->Next;
+               g->Next = nx;
+               if (can_release) releasenode(0, now);
+               push_stack(g);
+               break;
+#endif
+
+       case OR:
+               Assert(now->rgt->nxt == ZN, now->ntyp);
+               Assert(now->lft->nxt == ZN, now->ntyp);
+               n1 = now->lft;
+               nx = g->Next;
+
+               n2 = now->rgt;
+               n2->nxt = g->New;
+common:
+               n1->nxt = g->New;
+
+               ng(ZS, g->incoming, n1, g->Old, nx);
+               g->New = flatten(n2);
+
+               if (can_release) releasenode(1, now);
+
+               push_stack(g);
+               break;
+       }
+}
+
+Node *
+twocases(Node *p)
+{      Node *q;
+       /* 1: ([]p1 && []p2) == [](p1 && p2) */
+       /* 2: (<>p1 || <>p2) == <>(p1 || p2) */
+
+       if (!p) return p;
+
+       switch(p->ntyp) {
+       case AND:
+       case OR:
+       case U_OPER:
+       case V_OPER:
+               p->lft = twocases(p->lft);
+               p->rgt = twocases(p->rgt);
+               break;
+#ifdef NXT
+       case NEXT:
+#endif
+       case NOT:
+               p->lft = twocases(p->lft);
+               break;
+
+       default:
+               break;
+       }
+       if (p->ntyp == AND      /* 1 */
+       &&  p->lft->ntyp == V_OPER
+       &&  p->lft->lft->ntyp == FALSE
+       &&  p->rgt->ntyp == V_OPER
+       &&  p->rgt->lft->ntyp == FALSE)
+       {       q = tl_nn(V_OPER, False,
+                       tl_nn(AND, p->lft->rgt, p->rgt->rgt));
+       } else
+       if (p->ntyp == OR       /* 2 */
+       &&  p->lft->ntyp == U_OPER
+       &&  p->lft->lft->ntyp == TRUE
+       &&  p->rgt->ntyp == U_OPER
+       &&  p->rgt->lft->ntyp == TRUE)
+       {       q = tl_nn(U_OPER, True,
+                       tl_nn(OR, p->lft->rgt, p->rgt->rgt));
+       } else
+               q = p;
+       return q;
+}
+
+void
+trans(Node *p)
+{      Node    *op;
+       Graph   *g;
+
+       if (!p || tl_errs) return;
+
+       p = twocases(p);
+
+       if (tl_verbose || tl_terse)
+       {       fprintf(tl_out, "\t/* Normlzd: ");
+               dump(p);
+               fprintf(tl_out, " */\n");
+       }
+       if (tl_terse)
+               return;
+
+       op = dupnode(p);
+
+       ng(ZS, getsym(tl_lookup("init")), p, ZN, ZN);
+       while ((g = Nodes_Stack) != (Graph *) 0)
+       {       Nodes_Stack = g->nxt;
+               expand_g(g);
+       }
+       if (newstates)
+               return;
+
+       fixinit(p);
+       liveness(flatten(op));  /* was: liveness(op); */
+
+       mkbuchi();
+       if (tl_verbose)
+       {       printf("/*\n");
+               printf(" * %d states in Streett automaton\n", Base);
+               printf(" * %d Streett acceptance conditions\n", Max_Red);
+               printf(" * %d Buchi states\n", Total);
+               printf(" */\n");
+       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/vars.c b/trunk/verif/Spin/Src5.1.6/vars.c
new file mode 100755 (executable)
index 0000000..291983d
--- /dev/null
@@ -0,0 +1,357 @@
+/***** 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            */
+
+#include "spin.h"
+#include "y.tab.h"
+
+extern Ordered *all_names;
+extern RunList *X, *LastX;
+extern Symbol  *Fname;
+extern char    Buf[];
+extern int     lineno, depth, verbose, xspin, limited_vis;
+extern int     analyze, jumpsteps, nproc, nstop, columns;
+extern short   no_arrays, Have_claim;
+extern void    sr_mesg(FILE *, int, int);
+extern void    sr_buf(int, int);
+
+static int     getglobal(Lextok *);
+static int     setglobal(Lextok *, int);
+static int     maxcolnr = 1;
+
+int
+getval(Lextok *sn)
+{      Symbol *s = sn->sym;
+
+       if (strcmp(s->name, "_") == 0)
+       {       non_fatal("attempt to read value of '_'", 0);
+               return 0;
+       }
+       if (strcmp(s->name, "_last") == 0)
+               return (LastX)?LastX->pid:0;
+       if (strcmp(s->name, "_p") == 0)
+               return (X && X->pc)?X->pc->seqno:0;
+       if (strcmp(s->name, "_pid") == 0)
+       {       if (!X) return 0;
+               return X->pid - Have_claim;
+       }
+       if (strcmp(s->name, "_nr_pr") == 0)
+               return nproc-nstop;     /* new 3.3.10 */
+
+       if (s->context && s->type)
+               return getlocal(sn);
+
+       if (!s->type)   /* not declared locally */
+       {       s = lookup(s->name); /* try global */
+               sn->sym = s;    /* fix it */
+       }
+       return getglobal(sn);
+}
+
+int
+setval(Lextok *v, int n)
+{
+       if (v->sym->context && v->sym->type)
+               return setlocal(v, n);
+       if (!v->sym->type)
+               v->sym = lookup(v->sym->name);
+       return setglobal(v, n);
+}
+
+void
+rm_selfrefs(Symbol *s, Lextok *i)
+{
+       if (!i) return;
+
+       if (i->ntyp == NAME
+       &&  strcmp(i->sym->name, s->name) == 0
+       && (    (!i->sym->context && !s->context)
+          ||   ( i->sym->context &&  s->context
+               && strcmp(i->sym->context->name, s->context->name) == 0)))
+       {       lineno  = i->ln;
+               Fname   = i->fn;
+               non_fatal("self-reference initializing '%s'", s->name);
+               i->ntyp = CONST;
+               i->val  = 0;
+       } else
+       {       rm_selfrefs(s, i->lft);
+               rm_selfrefs(s, i->rgt);
+       }
+}
+
+int
+checkvar(Symbol *s, int n)
+{      int     i, oln = lineno;        /* calls on eval() change it */
+       Symbol  *ofnm = Fname;
+
+       if (!in_bound(s, n))
+               return 0;
+
+       if (s->type == 0)
+       {       non_fatal("undecl var %s (assuming int)", s->name);
+               s->type = INT;
+       }
+       /* not a STRUCT */
+       if (s->val == (int *) 0)        /* uninitialized */
+       {       s->val = (int *) emalloc(s->nel*sizeof(int));
+               for (i = 0; i < s->nel; i++)
+               {       if (s->type != CHAN)
+                       {       rm_selfrefs(s, s->ini);
+                               s->val[i] = eval(s->ini);
+                       } else if (!analyze)
+                               s->val[i] = qmake(s);
+       }       }
+       lineno = oln;
+       Fname  = ofnm;
+       return 1;
+}
+
+static int
+getglobal(Lextok *sn)
+{      Symbol *s = sn->sym;
+       int i, n = eval(sn->lft);
+
+       if (s->type == 0 && X && (i = find_lab(s, X->n, 0)))
+       {       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 */
+       if (checkvar(s, n))
+               return cast_val(s->type, s->val[n], s->nbits);
+       return 0;
+}
+
+int
+cast_val(int t, int v, int w)
+{      int i=0; short s=0; unsigned int u=0;
+
+       if (t == PREDEF || t == INT || t == CHAN) i = v;        /* predef means _ */
+       else if (t == SHORT) s = (short) v;
+       else if (t == BYTE || t == MTYPE)  u = (unsigned char)v;
+       else if (t == BIT)   u = (unsigned char)(v&1);
+       else if (t == UNSIGNED)
+       {       if (w == 0)
+                       fatal("cannot happen, cast_val", (char *)0);
+       /*      u = (unsigned)(v& ((1<<w)-1));          problem when w=32       */
+               u = (unsigned)(v& (~0u>>(8*sizeof(unsigned)-w)));       /* doug */
+       }
+
+       if (v != i+s+ (int) u)
+       {       char buf[64]; sprintf(buf, "%d->%d (%d)", v, i+s+u, t);
+               non_fatal("value (%s) truncated in assignment", buf);
+       }
+       return (int)(i+s+u);
+}
+
+static int
+setglobal(Lextok *v, int m)
+{
+       if (v->sym->type == STRUCT)
+               (void) Lval_struct(v, v->sym, 1, m);
+       else
+       {       int n = eval(v->lft);
+               if (checkvar(v->sym, n))
+               {       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;
+}
+
+void
+dumpclaims(FILE *fd, int pid, char *s)
+{      extern Lextok *Xu_List; extern int Pid;
+       extern short terse;
+       Lextok *m; int cnt = 0; int oPid = Pid;
+
+       for (m = Xu_List; m; m = m->rgt)
+               if (strcmp(m->sym->name, s) == 0)
+               {       cnt=1;
+                       break;
+               }
+       if (cnt == 0) return;
+
+       Pid = pid;
+       fprintf(fd, "#ifndef XUSAFE\n");
+       for (m = Xu_List; m; m = m->rgt)
+       {       if (strcmp(m->sym->name, s) != 0)
+                       continue;
+               no_arrays = 1;
+               putname(fd, "\t\tsetq_claim(", m->lft, 0, "");
+               no_arrays = 0;
+               fprintf(fd, ", %d, ", m->val);
+               terse = 1;
+               putname(fd, "\"", m->lft, 0, "\", h, ");
+               terse = 0;
+               fprintf(fd, "\"%s\");\n", s);
+       }
+       fprintf(fd, "#endif\n");
+       Pid = oPid;
+}
+
+void
+dumpglobals(void)
+{      Ordered *walk;
+       static Lextok *dummy = ZN;
+       Symbol *sp;
+       int j;
+
+       if (!dummy)
+               dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN);
+
+       for (walk = all_names; walk; walk = walk->next)
+       {       sp = walk->entry;
+               if (!sp->type || sp->context || sp->owner
+               ||  sp->type == PROCTYPE  || sp->type == PREDEF
+               ||  sp->type == CODE_FRAG || sp->type == CODE_DECL
+               ||  (sp->type == MTYPE && ismtype(sp->name)))
+                       continue;
+
+               if (sp->type == STRUCT)
+               {       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++)
+               {       int prefetch;
+                       if (sp->type == CHAN)
+                       {       doq(sp, j, 0);
+                               continue;
+                       }
+                       if ((verbose&4) && !(verbose&64)
+                       &&  (sp->setat < depth
+                       &&   jumpsteps != depth))
+                       {       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);
+                       printf(" = ");
+                       sr_mesg(stdout, prefetch,
+                               sp->type == MTYPE);
+                       printf("\n");
+                       if (limited_vis && (sp->hidden&2))
+                       {       int colpos;
+                               Buf[0] = '\0';
+                               if (!xspin)
+                               {       if (columns == 2)
+                                       sprintf(Buf, "~G%s = ", sp->name);
+                                       else
+                                       sprintf(Buf, "%s = ", sp->name);
+                               }
+                               sr_buf(prefetch, sp->type == MTYPE);
+                               if (sp->colnr == 0)
+                               {       sp->colnr = maxcolnr;
+                                       maxcolnr = 1+(maxcolnr%10);
+                               }
+                               colpos = nproc+sp->colnr-1;
+                               if (columns == 2)
+                               {       pstext(colpos, Buf);
+                                       continue;
+                               }
+                               if (!xspin)
+                               {       printf("\t\t%s\n", Buf);
+                                       continue;
+                               }
+                               printf("MSC: ~G %s %s\n", sp->name, Buf);
+                               printf("%3d:\tproc %3d (TRACK) line   1 \"var\" ",
+                                       depth, colpos);
+                               printf("(state 0)\t[printf('MSC: globvar\\\\n')]\n");
+                               printf("\t\t%s", sp->name);
+                               if (sp->nel > 1) printf("[%d]", j);
+                               printf(" = %s\n", Buf);
+       }       }       }
+}
+
+void
+dumplocal(RunList *r)
+{      static Lextok *dummy = ZN;
+       Symbol *z, *s;
+       int i;
+
+       if (!r) return;
+
+       s = r->symtab;
+
+       if (!dummy)
+               dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN);
+
+       for (z = s; z; z = z->next)
+       {       if (z->type == STRUCT)
+               {       dump_struct(z, z->name, r);
+                       continue;
+               }
+               for (i = 0; i < z->nel; i++)
+               {       if (z->type == CHAN)
+                       {       doq(z, i, r);
+                               continue;
+                       }
+                       if ((verbose&4) && !(verbose&64)
+                       &&  (z->setat < depth
+                       &&   jumpsteps != depth))
+                               continue;
+
+                       dummy->sym = z;
+                       dummy->lft->val = i;
+
+                       printf("\t\t%s(%d):%s",
+                               r->n->name, r->pid, z->name);
+                       if (z->nel > 1) printf("[%d]", i);
+                       printf(" = ");
+                       sr_mesg(stdout, getval(dummy), z->type == MTYPE);
+                       printf("\n");
+                       if (limited_vis && (z->hidden&2))
+                       {       int colpos;
+                               Buf[0] = '\0';
+                               if (!xspin)
+                               {       if (columns == 2)
+                                       sprintf(Buf, "~G%s(%d):%s = ",
+                                       r->n->name, r->pid, z->name);
+                                       else
+                                       sprintf(Buf, "%s(%d):%s = ",
+                                       r->n->name, r->pid, z->name);
+                               }
+                               sr_buf(getval(dummy), z->type==MTYPE);
+                               if (z->colnr == 0)
+                               {       z->colnr = maxcolnr;
+                                       maxcolnr = 1+(maxcolnr%10);
+                               }
+                               colpos = nproc+z->colnr-1;
+                               if (columns == 2)
+                               {       pstext(colpos, Buf);
+                                       continue;
+                               }
+                               if (!xspin)
+                               {       printf("\t\t%s\n", Buf);
+                                       continue;
+                               }
+                               printf("MSC: ~G %s(%d):%s %s\n",
+                                       r->n->name, r->pid, z->name, Buf);
+
+                               printf("%3d:\tproc %3d (TRACK) line   1 \"var\" ",
+                                       depth, colpos);
+                               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);
+                               printf(" = %s\n", Buf);
+       }       }       }
+}
diff --git a/trunk/verif/Spin/Src5.1.6/version.h b/trunk/verif/Spin/Src5.1.6/version.h
new file mode 100755 (executable)
index 0000000..23eb6a5
--- /dev/null
@@ -0,0 +1 @@
+#define SpinVersion    "Spin Version 5.1.6 -- 9 May 2008"
diff --git a/trunk/verif/Spin/Src5.1.6/y.output b/trunk/verif/Spin/Src5.1.6/y.output
new file mode 100644 (file)
index 0000000..9c7ce68
--- /dev/null
@@ -0,0 +1,6714 @@
+Terminals which are not used
+
+   MTYPE
+   LABEL
+   NON_ATOMIC
+
+
+Grammar
+
+    0 $accept: program $end
+
+    1 program: units
+
+    2 units: unit
+    3      | units unit
+
+    4 unit: proc
+    5     | init
+    6     | claim
+    7     | events
+    8     | one_decl
+    9     | utype
+   10     | c_fcts
+   11     | ns
+   12     | SEMI
+   13     | error
+
+   14 @1: /* empty */
+
+   15 @2: /* empty */
+
+   16 proc: inst proctype NAME @1 '(' decl ')' @2 Opt_priority Opt_enabler body
+
+   17 proctype: PROCTYPE
+   18         | D_PROCTYPE
+
+   19 inst: /* empty */
+   20     | ACTIVE
+   21     | ACTIVE '[' CONST ']'
+   22     | ACTIVE '[' NAME ']'
+
+   23 @3: /* empty */
+
+   24 init: INIT @3 Opt_priority body
+
+   25 @4: /* empty */
+
+   26 claim: CLAIM @4 body
+
+   27 @5: /* empty */
+
+   28 events: TRACE @5 body
+
+   29 @6: /* empty */
+
+   30 utype: TYPEDEF NAME @6 '{' decl_lst '}'
+
+   31 nm: NAME
+   32   | INAME
+
+   33 @7: /* empty */
+
+   34 ns: INLINE nm '(' @7 args ')'
+
+   35 c_fcts: ccode
+   36       | cstate
+
+   37 cstate: C_STATE STRING STRING
+   38       | C_TRACK STRING STRING
+   39       | C_STATE STRING STRING STRING
+   40       | C_TRACK STRING STRING STRING
+
+   41 ccode: C_CODE
+   42      | C_DECL
+
+   43 cexpr: C_EXPR
+
+   44 @8: /* empty */
+
+   45 @9: /* empty */
+
+   46 body: '{' @8 sequence OS @9 '}'
+
+   47 sequence: step
+   48         | sequence MS step
+
+   49 step: one_decl
+   50     | XU vref_lst
+   51     | NAME ':' one_decl
+   52     | NAME ':' XU
+   53     | stmnt
+   54     | stmnt UNLESS stmnt
+
+   55 vis: /* empty */
+   56    | HIDDEN
+   57    | SHOW
+   58    | ISLOCAL
+
+   59 asgn: /* empty */
+   60     | ASGN
+
+   61 one_decl: vis TYPE var_list
+   62         | vis UNAME var_list
+   63         | vis TYPE asgn '{' nlst '}'
+
+   64 decl_lst: one_decl
+   65         | one_decl SEMI decl_lst
+
+   66 decl: /* empty */
+   67     | decl_lst
+
+   68 vref_lst: varref
+   69         | varref ',' vref_lst
+
+   70 var_list: ivar
+   71         | ivar ',' var_list
+
+   72 ivar: vardcl
+   73     | vardcl ASGN expr
+   74     | vardcl ASGN ch_init
+
+   75 ch_init: '[' CONST ']' OF '{' typ_list '}'
+
+   76 vardcl: NAME
+   77       | NAME ':' CONST
+   78       | NAME '[' CONST ']'
+
+   79 varref: cmpnd
+
+   80 pfld: NAME
+
+   81 @10: /* empty */
+
+   82 pfld: NAME @10 '[' expr ']'
+
+   83 @11: /* empty */
+
+   84 cmpnd: pfld @11 sfld
+
+   85 sfld: /* empty */
+   86     | '.' cmpnd
+
+   87 stmnt: Special
+   88      | Stmnt
+
+   89 @12: /* empty */
+
+   90 Special: varref RCV @12 rargs
+
+   91 @13: /* empty */
+
+   92 Special: varref SND @13 margs
+   93        | IF options FI
+
+   94 @14: /* empty */
+
+   95 Special: DO @14 options OD
+   96        | BREAK
+   97        | GOTO NAME
+   98        | NAME ':' stmnt
+
+   99 Stmnt: varref ASGN expr
+  100      | varref INCR
+  101      | varref DECR
+
+  102 @15: /* empty */
+
+  103 Stmnt: PRINT '(' STRING @15 prargs ')'
+  104      | PRINTM '(' varref ')'
+  105      | PRINTM '(' CONST ')'
+  106      | ASSERT full_expr
+  107      | ccode
+
+  108 @16: /* empty */
+
+  109 Stmnt: varref R_RCV @16 rargs
+
+  110 @17: /* empty */
+
+  111 Stmnt: varref RCV @17 LT rargs GT
+
+  112 @18: /* empty */
+
+  113 Stmnt: varref R_RCV @18 LT rargs GT
+
+  114 @19: /* empty */
+
+  115 Stmnt: varref O_SND @19 margs
+  116      | full_expr
+  117      | ELSE
+
+  118 @20: /* empty */
+
+  119 Stmnt: ATOMIC '{' @20 sequence OS '}'
+
+  120 @21: /* empty */
+
+  121 Stmnt: D_STEP '{' @21 sequence OS '}'
+
+  122 @22: /* empty */
+
+  123 Stmnt: '{' @22 sequence OS '}'
+
+  124 @23: /* empty */
+
+  125 @24: /* empty */
+
+  126 Stmnt: INAME @23 '(' args ')' @24 Stmnt
+
+  127 options: option
+  128        | option options
+
+  129 @25: /* empty */
+
+  130 option: SEP @25 sequence OS
+
+  131 OS: /* empty */
+  132   | SEMI
+
+  133 MS: SEMI
+  134   | MS SEMI
+
+  135 aname: NAME
+  136      | PNAME
+
+  137 expr: '(' expr ')'
+  138     | expr '+' expr
+  139     | expr '-' expr
+  140     | expr '*' expr
+  141     | expr '/' expr
+  142     | expr '%' expr
+  143     | expr '&' expr
+  144     | expr '^' expr
+  145     | expr '|' expr
+  146     | expr GT expr
+  147     | expr LT expr
+  148     | expr GE expr
+  149     | expr LE expr
+  150     | expr EQ expr
+  151     | expr NE expr
+  152     | expr AND expr
+  153     | expr OR expr
+  154     | expr LSHIFT expr
+  155     | expr RSHIFT expr
+  156     | '~' expr
+  157     | '-' expr
+  158     | SND expr
+  159     | '(' expr SEMI expr ':' expr ')'
+
+  160 @26: /* empty */
+
+  161 expr: RUN aname @26 '(' args ')' Opt_priority
+  162     | LEN '(' varref ')'
+  163     | ENABLED '(' expr ')'
+
+  164 @27: /* empty */
+
+  165 expr: varref RCV @27 '[' rargs ']'
+
+  166 @28: /* empty */
+
+  167 expr: varref R_RCV @28 '[' rargs ']'
+  168     | varref
+  169     | cexpr
+  170     | CONST
+  171     | TIMEOUT
+  172     | NONPROGRESS
+  173     | PC_VAL '(' expr ')'
+  174     | PNAME '[' expr ']' '@' NAME
+  175     | PNAME '[' expr ']' ':' pfld
+  176     | PNAME '@' NAME
+  177     | PNAME ':' pfld
+
+  178 Opt_priority: /* empty */
+  179             | PRIORITY CONST
+
+  180 full_expr: expr
+  181          | Expr
+
+  182 Opt_enabler: /* empty */
+  183            | PROVIDED '(' full_expr ')'
+  184            | PROVIDED error
+
+  185 Expr: Probe
+  186     | '(' Expr ')'
+  187     | Expr AND Expr
+  188     | Expr AND expr
+  189     | Expr OR Expr
+  190     | Expr OR expr
+  191     | expr AND Expr
+  192     | expr OR Expr
+
+  193 Probe: FULL '(' varref ')'
+  194      | NFULL '(' varref ')'
+  195      | EMPTY '(' varref ')'
+  196      | NEMPTY '(' varref ')'
+
+  197 basetype: TYPE
+  198         | UNAME
+  199         | error
+
+  200 typ_list: basetype
+  201         | basetype ',' typ_list
+
+  202 args: /* empty */
+  203     | arg
+
+  204 prargs: /* empty */
+  205       | ',' arg
+
+  206 margs: arg
+  207      | expr '(' arg ')'
+
+  208 arg: expr
+  209    | expr ',' arg
+
+  210 rarg: varref
+  211     | EVAL '(' expr ')'
+  212     | CONST
+  213     | '-' CONST
+
+  214 rargs: rarg
+  215      | rarg ',' rargs
+  216      | rarg '(' rargs ')'
+  217      | '(' rargs ')'
+
+  218 nlst: NAME
+  219     | nlst NAME
+  220     | nlst ','
+
+
+Terminals, with rules where they appear
+
+$end (0) 0
+'%' (37) 142
+'&' (38) 143
+'(' (40) 16 34 103 104 105 126 137 159 161 162 163 173 183 186 193
+    194 195 196 207 211 216 217
+')' (41) 16 34 103 104 105 126 137 159 161 162 163 173 183 186 193
+    194 195 196 207 211 216 217
+'*' (42) 140
+'+' (43) 138
+',' (44) 69 71 201 205 209 215 220
+'-' (45) 139 157 213
+'.' (46) 86
+'/' (47) 141
+':' (58) 51 52 77 98 159 175 177
+'@' (64) 174 176
+'[' (91) 21 22 75 78 82 165 167 174 175
+']' (93) 21 22 75 78 82 165 167 174 175
+'^' (94) 144
+'{' (123) 30 46 63 75 119 121 123
+'|' (124) 145
+'}' (125) 30 46 63 75 119 121 123
+'~' (126) 156
+error (256) 13 184 199
+ASSERT (258) 106
+PRINT (259) 103
+PRINTM (260) 104 105
+C_CODE (261) 41
+C_DECL (262) 42
+C_EXPR (263) 43
+C_STATE (264) 37 39
+C_TRACK (265) 38 40
+RUN (266) 161
+LEN (267) 162
+ENABLED (268) 163
+EVAL (269) 211
+PC_VAL (270) 173
+TYPEDEF (271) 30
+MTYPE (272)
+INLINE (273) 34
+LABEL (274)
+OF (275) 75
+GOTO (276) 97
+BREAK (277) 96
+ELSE (278) 117
+SEMI (279) 12 65 132 133 134 159
+IF (280) 93
+FI (281) 93
+DO (282) 95
+OD (283) 95
+SEP (284) 130
+ATOMIC (285) 119
+NON_ATOMIC (286)
+D_STEP (287) 121
+UNLESS (288) 54
+TIMEOUT (289) 171
+NONPROGRESS (290) 172
+ACTIVE (291) 20 21 22
+PROCTYPE (292) 17
+D_PROCTYPE (293) 18
+HIDDEN (294) 56
+SHOW (295) 57
+ISLOCAL (296) 58
+PRIORITY (297) 179
+PROVIDED (298) 183 184
+FULL (299) 193
+EMPTY (300) 195
+NFULL (301) 194
+NEMPTY (302) 196
+CONST (303) 21 75 77 78 105 170 179 212 213
+TYPE (304) 61 63 197
+XU (305) 50 52
+NAME (306) 16 22 30 31 51 52 76 77 78 80 82 97 98 135 174 176 218 219
+UNAME (307) 62 198
+PNAME (308) 136 174 175 176 177
+INAME (309) 32 126
+STRING (310) 37 38 39 40 103
+CLAIM (311) 26
+TRACE (312) 28
+INIT (313) 24
+ASGN (314) 60 73 74 99
+R_RCV (315) 109 113 167
+RCV (316) 90 111 165
+O_SND (317) 115
+SND (318) 92 158
+OR (319) 153 189 190 192
+AND (320) 152 187 188 191
+NE (321) 151
+EQ (322) 150
+LE (323) 149
+GE (324) 148
+LT (325) 111 113 147
+GT (326) 111 113 146
+RSHIFT (327) 155
+LSHIFT (328) 154
+DECR (329) 101
+INCR (330) 100
+NEG (331)
+UMIN (332)
+DOT (333)
+
+
+Nonterminals, with rules where they appear
+
+$accept (98)
+    on left: 0
+program (99)
+    on left: 1, on right: 0
+units (100)
+    on left: 2 3, on right: 1 3
+unit (101)
+    on left: 4 5 6 7 8 9 10 11 12 13, on right: 2 3
+proc (102)
+    on left: 16, on right: 4
+@1 (103)
+    on left: 14, on right: 16
+@2 (104)
+    on left: 15, on right: 16
+proctype (105)
+    on left: 17 18, on right: 16
+inst (106)
+    on left: 19 20 21 22, on right: 16
+init (107)
+    on left: 24, on right: 5
+@3 (108)
+    on left: 23, on right: 24
+claim (109)
+    on left: 26, on right: 6
+@4 (110)
+    on left: 25, on right: 26
+events (111)
+    on left: 28, on right: 7
+@5 (112)
+    on left: 27, on right: 28
+utype (113)
+    on left: 30, on right: 9
+@6 (114)
+    on left: 29, on right: 30
+nm (115)
+    on left: 31 32, on right: 34
+ns (116)
+    on left: 34, on right: 11
+@7 (117)
+    on left: 33, on right: 34
+c_fcts (118)
+    on left: 35 36, on right: 10
+cstate (119)
+    on left: 37 38 39 40, on right: 36
+ccode (120)
+    on left: 41 42, on right: 35 107
+cexpr (121)
+    on left: 43, on right: 169
+body (122)
+    on left: 46, on right: 16 24 26 28
+@8 (123)
+    on left: 44, on right: 46
+@9 (124)
+    on left: 45, on right: 46
+sequence (125)
+    on left: 47 48, on right: 46 48 119 121 123 130
+step (126)
+    on left: 49 50 51 52 53 54, on right: 47 48
+vis (127)
+    on left: 55 56 57 58, on right: 61 62 63
+asgn (128)
+    on left: 59 60, on right: 63
+one_decl (129)
+    on left: 61 62 63, on right: 8 49 51 64 65
+decl_lst (130)
+    on left: 64 65, on right: 30 65 67
+decl (131)
+    on left: 66 67, on right: 16
+vref_lst (132)
+    on left: 68 69, on right: 50 69
+var_list (133)
+    on left: 70 71, on right: 61 62 71
+ivar (134)
+    on left: 72 73 74, on right: 70 71
+ch_init (135)
+    on left: 75, on right: 74
+vardcl (136)
+    on left: 76 77 78, on right: 72 73 74
+varref (137)
+    on left: 79, on right: 68 69 90 92 99 100 101 104 109 111 113 115
+    162 165 167 168 193 194 195 196 210
+pfld (138)
+    on left: 80 82, on right: 84 175 177
+@10 (139)
+    on left: 81, on right: 82
+cmpnd (140)
+    on left: 84, on right: 79 86
+@11 (141)
+    on left: 83, on right: 84
+sfld (142)
+    on left: 85 86, on right: 84
+stmnt (143)
+    on left: 87 88, on right: 53 54 98
+Special (144)
+    on left: 90 92 93 95 96 97 98, on right: 87
+@12 (145)
+    on left: 89, on right: 90
+@13 (146)
+    on left: 91, on right: 92
+@14 (147)
+    on left: 94, on right: 95
+Stmnt (148)
+    on left: 99 100 101 103 104 105 106 107 109 111 113 115 116 117
+    119 121 123 126, on right: 88 126
+@15 (149)
+    on left: 102, on right: 103
+@16 (150)
+    on left: 108, on right: 109
+@17 (151)
+    on left: 110, on right: 111
+@18 (152)
+    on left: 112, on right: 113
+@19 (153)
+    on left: 114, on right: 115
+@20 (154)
+    on left: 118, on right: 119
+@21 (155)
+    on left: 120, on right: 121
+@22 (156)
+    on left: 122, on right: 123
+@23 (157)
+    on left: 124, on right: 126
+@24 (158)
+    on left: 125, on right: 126
+options (159)
+    on left: 127 128, on right: 93 95 128
+option (160)
+    on left: 130, on right: 127 128
+@25 (161)
+    on left: 129, on right: 130
+OS (162)
+    on left: 131 132, on right: 46 119 121 123 130
+MS (163)
+    on left: 133 134, on right: 48 134
+aname (164)
+    on left: 135 136, on right: 161
+expr (165)
+    on left: 137 138 139 140 141 142 143 144 145 146 147 148 149 150
+    151 152 153 154 155 156 157 158 159 161 162 163 165 167 168 169
+    170 171 172 173 174 175 176 177, on right: 73 82 99 137 138 139
+    140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
+    156 157 158 159 163 173 174 175 180 188 190 191 192 207 208 209
+    211
+@26 (166)
+    on left: 160, on right: 161
+@27 (167)
+    on left: 164, on right: 165
+@28 (168)
+    on left: 166, on right: 167
+Opt_priority (169)
+    on left: 178 179, on right: 16 24 161
+full_expr (170)
+    on left: 180 181, on right: 106 116 183
+Opt_enabler (171)
+    on left: 182 183 184, on right: 16
+Expr (172)
+    on left: 185 186 187 188 189 190 191 192, on right: 181 186 187
+    188 189 190 191 192
+Probe (173)
+    on left: 193 194 195 196, on right: 185
+basetype (174)
+    on left: 197 198 199, on right: 200 201
+typ_list (175)
+    on left: 200 201, on right: 75 201
+args (176)
+    on left: 202 203, on right: 34 126 161
+prargs (177)
+    on left: 204 205, on right: 103
+margs (178)
+    on left: 206 207, on right: 92 115
+arg (179)
+    on left: 208 209, on right: 203 205 206 207 209
+rarg (180)
+    on left: 210 211 212 213, on right: 214 215 216
+rargs (181)
+    on left: 214 215 216 217, on right: 90 109 111 113 165 167 215
+    216 217
+nlst (182)
+    on left: 218 219 220, on right: 63 219 220
+
+
+state 0
+
+    0 $accept: . program $end
+
+    error    shift, and go to state 1
+    C_CODE   shift, and go to state 2
+    C_DECL   shift, and go to state 3
+    C_STATE  shift, and go to state 4
+    C_TRACK  shift, and go to state 5
+    TYPEDEF  shift, and go to state 6
+    INLINE   shift, and go to state 7
+    SEMI     shift, and go to state 8
+    ACTIVE   shift, and go to state 9
+    HIDDEN   shift, and go to state 10
+    SHOW     shift, and go to state 11
+    ISLOCAL  shift, and go to state 12
+    CLAIM    shift, and go to state 13
+    TRACE    shift, and go to state 14
+    INIT     shift, and go to state 15
+
+    PROCTYPE    reduce using rule 19 (inst)
+    D_PROCTYPE  reduce using rule 19 (inst)
+    TYPE        reduce using rule 55 (vis)
+    UNAME       reduce using rule 55 (vis)
+
+    program   go to state 16
+    units     go to state 17
+    unit      go to state 18
+    proc      go to state 19
+    inst      go to state 20
+    init      go to state 21
+    claim     go to state 22
+    events    go to state 23
+    utype     go to state 24
+    ns        go to state 25
+    c_fcts    go to state 26
+    cstate    go to state 27
+    ccode     go to state 28
+    vis       go to state 29
+    one_decl  go to state 30
+
+
+state 1
+
+   13 unit: error .
+
+    $default  reduce using rule 13 (unit)
+
+
+state 2
+
+   41 ccode: C_CODE .
+
+    $default  reduce using rule 41 (ccode)
+
+
+state 3
+
+   42 ccode: C_DECL .
+
+    $default  reduce using rule 42 (ccode)
+
+
+state 4
+
+   37 cstate: C_STATE . STRING STRING
+   39       | C_STATE . STRING STRING STRING
+
+    STRING  shift, and go to state 31
+
+
+state 5
+
+   38 cstate: C_TRACK . STRING STRING
+   40       | C_TRACK . STRING STRING STRING
+
+    STRING  shift, and go to state 32
+
+
+state 6
+
+   30 utype: TYPEDEF . NAME @6 '{' decl_lst '}'
+
+    NAME  shift, and go to state 33
+
+
+state 7
+
+   34 ns: INLINE . nm '(' @7 args ')'
+
+    NAME   shift, and go to state 34
+    INAME  shift, and go to state 35
+
+    nm  go to state 36
+
+
+state 8
+
+   12 unit: SEMI .
+
+    $default  reduce using rule 12 (unit)
+
+
+state 9
+
+   20 inst: ACTIVE .
+   21     | ACTIVE . '[' CONST ']'
+   22     | ACTIVE . '[' NAME ']'
+
+    '['  shift, and go to state 37
+
+    $default  reduce using rule 20 (inst)
+
+
+state 10
+
+   56 vis: HIDDEN .
+
+    $default  reduce using rule 56 (vis)
+
+
+state 11
+
+   57 vis: SHOW .
+
+    $default  reduce using rule 57 (vis)
+
+
+state 12
+
+   58 vis: ISLOCAL .
+
+    $default  reduce using rule 58 (vis)
+
+
+state 13
+
+   26 claim: CLAIM . @4 body
+
+    $default  reduce using rule 25 (@4)
+
+    @4  go to state 38
+
+
+state 14
+
+   28 events: TRACE . @5 body
+
+    $default  reduce using rule 27 (@5)
+
+    @5  go to state 39
+
+
+state 15
+
+   24 init: INIT . @3 Opt_priority body
+
+    $default  reduce using rule 23 (@3)
+
+    @3  go to state 40
+
+
+state 16
+
+    0 $accept: program . $end
+
+    $end  shift, and go to state 41
+
+
+state 17
+
+    1 program: units .
+    3 units: units . unit
+
+    error    shift, and go to state 1
+    C_CODE   shift, and go to state 2
+    C_DECL   shift, and go to state 3
+    C_STATE  shift, and go to state 4
+    C_TRACK  shift, and go to state 5
+    TYPEDEF  shift, and go to state 6
+    INLINE   shift, and go to state 7
+    SEMI     shift, and go to state 8
+    ACTIVE   shift, and go to state 9
+    HIDDEN   shift, and go to state 10
+    SHOW     shift, and go to state 11
+    ISLOCAL  shift, and go to state 12
+    CLAIM    shift, and go to state 13
+    TRACE    shift, and go to state 14
+    INIT     shift, and go to state 15
+
+    $end        reduce using rule 1 (program)
+    PROCTYPE    reduce using rule 19 (inst)
+    D_PROCTYPE  reduce using rule 19 (inst)
+    TYPE        reduce using rule 55 (vis)
+    UNAME       reduce using rule 55 (vis)
+
+    unit      go to state 42
+    proc      go to state 19
+    inst      go to state 20
+    init      go to state 21
+    claim     go to state 22
+    events    go to state 23
+    utype     go to state 24
+    ns        go to state 25
+    c_fcts    go to state 26
+    cstate    go to state 27
+    ccode     go to state 28
+    vis       go to state 29
+    one_decl  go to state 30
+
+
+state 18
+
+    2 units: unit .
+
+    $default  reduce using rule 2 (units)
+
+
+state 19
+
+    4 unit: proc .
+
+    $default  reduce using rule 4 (unit)
+
+
+state 20
+
+   16 proc: inst . proctype NAME @1 '(' decl ')' @2 Opt_priority Opt_enabler body
+
+    PROCTYPE    shift, and go to state 43
+    D_PROCTYPE  shift, and go to state 44
+
+    proctype  go to state 45
+
+
+state 21
+
+    5 unit: init .
+
+    $default  reduce using rule 5 (unit)
+
+
+state 22
+
+    6 unit: claim .
+
+    $default  reduce using rule 6 (unit)
+
+
+state 23
+
+    7 unit: events .
+
+    $default  reduce using rule 7 (unit)
+
+
+state 24
+
+    9 unit: utype .
+
+    $default  reduce using rule 9 (unit)
+
+
+state 25
+
+   11 unit: ns .
+
+    $default  reduce using rule 11 (unit)
+
+
+state 26
+
+   10 unit: c_fcts .
+
+    $default  reduce using rule 10 (unit)
+
+
+state 27
+
+   36 c_fcts: cstate .
+
+    $default  reduce using rule 36 (c_fcts)
+
+
+state 28
+
+   35 c_fcts: ccode .
+
+    $default  reduce using rule 35 (c_fcts)
+
+
+state 29
+
+   61 one_decl: vis . TYPE var_list
+   62         | vis . UNAME var_list
+   63         | vis . TYPE asgn '{' nlst '}'
+
+    TYPE   shift, and go to state 46
+    UNAME  shift, and go to state 47
+
+
+state 30
+
+    8 unit: one_decl .
+
+    $default  reduce using rule 8 (unit)
+
+
+state 31
+
+   37 cstate: C_STATE STRING . STRING
+   39       | C_STATE STRING . STRING STRING
+
+    STRING  shift, and go to state 48
+
+
+state 32
+
+   38 cstate: C_TRACK STRING . STRING
+   40       | C_TRACK STRING . STRING STRING
+
+    STRING  shift, and go to state 49
+
+
+state 33
+
+   30 utype: TYPEDEF NAME . @6 '{' decl_lst '}'
+
+    $default  reduce using rule 29 (@6)
+
+    @6  go to state 50
+
+
+state 34
+
+   31 nm: NAME .
+
+    $default  reduce using rule 31 (nm)
+
+
+state 35
+
+   32 nm: INAME .
+
+    $default  reduce using rule 32 (nm)
+
+
+state 36
+
+   34 ns: INLINE nm . '(' @7 args ')'
+
+    '('  shift, and go to state 51
+
+
+state 37
+
+   21 inst: ACTIVE '[' . CONST ']'
+   22     | ACTIVE '[' . NAME ']'
+
+    CONST  shift, and go to state 52
+    NAME   shift, and go to state 53
+
+
+state 38
+
+   26 claim: CLAIM @4 . body
+
+    '{'  shift, and go to state 54
+
+    body  go to state 55
+
+
+state 39
+
+   28 events: TRACE @5 . body
+
+    '{'  shift, and go to state 54
+
+    body  go to state 56
+
+
+state 40
+
+   24 init: INIT @3 . Opt_priority body
+
+    PRIORITY  shift, and go to state 57
+
+    $default  reduce using rule 178 (Opt_priority)
+
+    Opt_priority  go to state 58
+
+
+state 41
+
+    0 $accept: program $end .
+
+    $default  accept
+
+
+state 42
+
+    3 units: units unit .
+
+    $default  reduce using rule 3 (units)
+
+
+state 43
+
+   17 proctype: PROCTYPE .
+
+    $default  reduce using rule 17 (proctype)
+
+
+state 44
+
+   18 proctype: D_PROCTYPE .
+
+    $default  reduce using rule 18 (proctype)
+
+
+state 45
+
+   16 proc: inst proctype . NAME @1 '(' decl ')' @2 Opt_priority Opt_enabler body
+
+    NAME  shift, and go to state 59
+
+
+state 46
+
+   61 one_decl: vis TYPE . var_list
+   63         | vis TYPE . asgn '{' nlst '}'
+
+    NAME  shift, and go to state 60
+    ASGN  shift, and go to state 61
+
+    $default  reduce using rule 59 (asgn)
+
+    asgn      go to state 62
+    var_list  go to state 63
+    ivar      go to state 64
+    vardcl    go to state 65
+
+
+state 47
+
+   62 one_decl: vis UNAME . var_list
+
+    NAME  shift, and go to state 60
+
+    var_list  go to state 66
+    ivar      go to state 64
+    vardcl    go to state 65
+
+
+state 48
+
+   37 cstate: C_STATE STRING STRING .
+   39       | C_STATE STRING STRING . STRING
+
+    STRING  shift, and go to state 67
+
+    $default  reduce using rule 37 (cstate)
+
+
+state 49
+
+   38 cstate: C_TRACK STRING STRING .
+   40       | C_TRACK STRING STRING . STRING
+
+    STRING  shift, and go to state 68
+
+    $default  reduce using rule 38 (cstate)
+
+
+state 50
+
+   30 utype: TYPEDEF NAME @6 . '{' decl_lst '}'
+
+    '{'  shift, and go to state 69
+
+
+state 51
+
+   34 ns: INLINE nm '(' . @7 args ')'
+
+    $default  reduce using rule 33 (@7)
+
+    @7  go to state 70
+
+
+state 52
+
+   21 inst: ACTIVE '[' CONST . ']'
+
+    ']'  shift, and go to state 71
+
+
+state 53
+
+   22 inst: ACTIVE '[' NAME . ']'
+
+    ']'  shift, and go to state 72
+
+
+state 54
+
+   46 body: '{' . @8 sequence OS @9 '}'
+
+    $default  reduce using rule 44 (@8)
+
+    @8  go to state 73
+
+
+state 55
+
+   26 claim: CLAIM @4 body .
+
+    $default  reduce using rule 26 (claim)
+
+
+state 56
+
+   28 events: TRACE @5 body .
+
+    $default  reduce using rule 28 (events)
+
+
+state 57
+
+  179 Opt_priority: PRIORITY . CONST
+
+    CONST  shift, and go to state 74
+
+
+state 58
+
+   24 init: INIT @3 Opt_priority . body
+
+    '{'  shift, and go to state 54
+
+    body  go to state 75
+
+
+state 59
+
+   16 proc: inst proctype NAME . @1 '(' decl ')' @2 Opt_priority Opt_enabler body
+
+    $default  reduce using rule 14 (@1)
+
+    @1  go to state 76
+
+
+state 60
+
+   76 vardcl: NAME .
+   77       | NAME . ':' CONST
+   78       | NAME . '[' CONST ']'
+
+    '['  shift, and go to state 77
+    ':'  shift, and go to state 78
+
+    $default  reduce using rule 76 (vardcl)
+
+
+state 61
+
+   60 asgn: ASGN .
+
+    $default  reduce using rule 60 (asgn)
+
+
+state 62
+
+   63 one_decl: vis TYPE asgn . '{' nlst '}'
+
+    '{'  shift, and go to state 79
+
+
+state 63
+
+   61 one_decl: vis TYPE var_list .
+
+    $default  reduce using rule 61 (one_decl)
+
+
+state 64
+
+   70 var_list: ivar .
+   71         | ivar . ',' var_list
+
+    ','  shift, and go to state 80
+
+    $default  reduce using rule 70 (var_list)
+
+
+state 65
+
+   72 ivar: vardcl .
+   73     | vardcl . ASGN expr
+   74     | vardcl . ASGN ch_init
+
+    ASGN  shift, and go to state 81
+
+    $default  reduce using rule 72 (ivar)
+
+
+state 66
+
+   62 one_decl: vis UNAME var_list .
+
+    $default  reduce using rule 62 (one_decl)
+
+
+state 67
+
+   39 cstate: C_STATE STRING STRING STRING .
+
+    $default  reduce using rule 39 (cstate)
+
+
+state 68
+
+   40 cstate: C_TRACK STRING STRING STRING .
+
+    $default  reduce using rule 40 (cstate)
+
+
+state 69
+
+   30 utype: TYPEDEF NAME @6 '{' . decl_lst '}'
+
+    HIDDEN   shift, and go to state 10
+    SHOW     shift, and go to state 11
+    ISLOCAL  shift, and go to state 12
+
+    $default  reduce using rule 55 (vis)
+
+    vis       go to state 29
+    one_decl  go to state 82
+    decl_lst  go to state 83
+
+
+state 70
+
+   34 ns: INLINE nm '(' @7 . args ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    $default  reduce using rule 202 (args)
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 102
+    args    go to state 103
+    arg     go to state 104
+
+
+state 71
+
+   21 inst: ACTIVE '[' CONST ']' .
+
+    $default  reduce using rule 21 (inst)
+
+
+state 72
+
+   22 inst: ACTIVE '[' NAME ']' .
+
+    $default  reduce using rule 22 (inst)
+
+
+state 73
+
+   46 body: '{' @8 . sequence OS @9 '}'
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    HIDDEN       shift, and go to state 10
+    SHOW         shift, and go to state 11
+    ISLOCAL      shift, and go to state 12
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    XU           shift, and go to state 119
+    NAME         shift, and go to state 120
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    $default  reduce using rule 55 (vis)
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    sequence   go to state 125
+    step       go to state 126
+    vis        go to state 29
+    one_decl   go to state 127
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 129
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 74
+
+  179 Opt_priority: PRIORITY CONST .
+
+    $default  reduce using rule 179 (Opt_priority)
+
+
+state 75
+
+   24 init: INIT @3 Opt_priority body .
+
+    $default  reduce using rule 24 (init)
+
+
+state 76
+
+   16 proc: inst proctype NAME @1 . '(' decl ')' @2 Opt_priority Opt_enabler body
+
+    '('  shift, and go to state 136
+
+
+state 77
+
+   78 vardcl: NAME '[' . CONST ']'
+
+    CONST  shift, and go to state 137
+
+
+state 78
+
+   77 vardcl: NAME ':' . CONST
+
+    CONST  shift, and go to state 138
+
+
+state 79
+
+   63 one_decl: vis TYPE asgn '{' . nlst '}'
+
+    NAME  shift, and go to state 139
+
+    nlst  go to state 140
+
+
+state 80
+
+   71 var_list: ivar ',' . var_list
+
+    NAME  shift, and go to state 60
+
+    var_list  go to state 141
+    ivar      go to state 64
+    vardcl    go to state 65
+
+
+state 81
+
+   73 ivar: vardcl ASGN . expr
+   74     | vardcl ASGN . ch_init
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+    '['          shift, and go to state 142
+
+    cexpr    go to state 98
+    ch_init  go to state 143
+    varref   go to state 99
+    pfld     go to state 100
+    cmpnd    go to state 101
+    expr     go to state 144
+
+
+state 82
+
+   64 decl_lst: one_decl .
+   65         | one_decl . SEMI decl_lst
+
+    SEMI  shift, and go to state 145
+
+    $default  reduce using rule 64 (decl_lst)
+
+
+state 83
+
+   30 utype: TYPEDEF NAME @6 '{' decl_lst . '}'
+
+    '}'  shift, and go to state 146
+
+
+state 84
+
+   43 cexpr: C_EXPR .
+
+    $default  reduce using rule 43 (cexpr)
+
+
+state 85
+
+  161 expr: RUN . aname @26 '(' args ')' Opt_priority
+
+    NAME   shift, and go to state 147
+    PNAME  shift, and go to state 148
+
+    aname  go to state 149
+
+
+state 86
+
+  162 expr: LEN . '(' varref ')'
+
+    '('  shift, and go to state 150
+
+
+state 87
+
+  163 expr: ENABLED . '(' expr ')'
+
+    '('  shift, and go to state 151
+
+
+state 88
+
+  173 expr: PC_VAL . '(' expr ')'
+
+    '('  shift, and go to state 152
+
+
+state 89
+
+  171 expr: TIMEOUT .
+
+    $default  reduce using rule 171 (expr)
+
+
+state 90
+
+  172 expr: NONPROGRESS .
+
+    $default  reduce using rule 172 (expr)
+
+
+state 91
+
+  170 expr: CONST .
+
+    $default  reduce using rule 170 (expr)
+
+
+state 92
+
+   80 pfld: NAME .
+   82     | NAME . @10 '[' expr ']'
+
+    '['       reduce using rule 81 (@10)
+    $default  reduce using rule 80 (pfld)
+
+    @10  go to state 153
+
+
+state 93
+
+  174 expr: PNAME . '[' expr ']' '@' NAME
+  175     | PNAME . '[' expr ']' ':' pfld
+  176     | PNAME . '@' NAME
+  177     | PNAME . ':' pfld
+
+    '['  shift, and go to state 154
+    ':'  shift, and go to state 155
+    '@'  shift, and go to state 156
+
+
+state 94
+
+  158 expr: SND . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 157
+
+
+state 95
+
+  157 expr: '-' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 158
+
+
+state 96
+
+  156 expr: '~' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 159
+
+
+state 97
+
+  137 expr: '(' . expr ')'
+  159     | '(' . expr SEMI expr ':' expr ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 160
+
+
+state 98
+
+  169 expr: cexpr .
+
+    $default  reduce using rule 169 (expr)
+
+
+state 99
+
+  165 expr: varref . RCV @27 '[' rargs ']'
+  167     | varref . R_RCV @28 '[' rargs ']'
+  168     | varref .
+
+    R_RCV  shift, and go to state 161
+    RCV    shift, and go to state 162
+
+    $default  reduce using rule 168 (expr)
+
+
+state 100
+
+   84 cmpnd: pfld . @11 sfld
+
+    $default  reduce using rule 83 (@11)
+
+    @11  go to state 163
+
+
+state 101
+
+   79 varref: cmpnd .
+
+    $default  reduce using rule 79 (varref)
+
+
+state 102
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  208 arg: expr .
+  209    | expr . ',' arg
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ','     shift, and go to state 182
+
+    $default  reduce using rule 208 (arg)
+
+
+state 103
+
+   34 ns: INLINE nm '(' @7 args . ')'
+
+    ')'  shift, and go to state 183
+
+
+state 104
+
+  203 args: arg .
+
+    $default  reduce using rule 203 (args)
+
+
+state 105
+
+  106 Stmnt: ASSERT . full_expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+
+    cexpr      go to state 98
+    varref     go to state 99
+    pfld       go to state 100
+    cmpnd      go to state 101
+    expr       go to state 132
+    full_expr  go to state 184
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 106
+
+  103 Stmnt: PRINT . '(' STRING @15 prargs ')'
+
+    '('  shift, and go to state 185
+
+
+state 107
+
+  104 Stmnt: PRINTM . '(' varref ')'
+  105      | PRINTM . '(' CONST ')'
+
+    '('  shift, and go to state 186
+
+
+state 108
+
+   97 Special: GOTO . NAME
+
+    NAME  shift, and go to state 187
+
+
+state 109
+
+   96 Special: BREAK .
+
+    $default  reduce using rule 96 (Special)
+
+
+state 110
+
+  117 Stmnt: ELSE .
+
+    $default  reduce using rule 117 (Stmnt)
+
+
+state 111
+
+   93 Special: IF . options FI
+
+    SEP  shift, and go to state 188
+
+    options  go to state 189
+    option   go to state 190
+
+
+state 112
+
+   95 Special: DO . @14 options OD
+
+    $default  reduce using rule 94 (@14)
+
+    @14  go to state 191
+
+
+state 113
+
+  119 Stmnt: ATOMIC . '{' @20 sequence OS '}'
+
+    '{'  shift, and go to state 192
+
+
+state 114
+
+  121 Stmnt: D_STEP . '{' @21 sequence OS '}'
+
+    '{'  shift, and go to state 193
+
+
+state 115
+
+  193 Probe: FULL . '(' varref ')'
+
+    '('  shift, and go to state 194
+
+
+state 116
+
+  195 Probe: EMPTY . '(' varref ')'
+
+    '('  shift, and go to state 195
+
+
+state 117
+
+  194 Probe: NFULL . '(' varref ')'
+
+    '('  shift, and go to state 196
+
+
+state 118
+
+  196 Probe: NEMPTY . '(' varref ')'
+
+    '('  shift, and go to state 197
+
+
+state 119
+
+   50 step: XU . vref_lst
+
+    NAME  shift, and go to state 92
+
+    vref_lst  go to state 198
+    varref    go to state 199
+    pfld      go to state 100
+    cmpnd     go to state 101
+
+
+state 120
+
+   51 step: NAME . ':' one_decl
+   52     | NAME . ':' XU
+   80 pfld: NAME .
+   82     | NAME . @10 '[' expr ']'
+   98 Special: NAME . ':' stmnt
+
+    ':'  shift, and go to state 200
+
+    '['       reduce using rule 81 (@10)
+    $default  reduce using rule 80 (pfld)
+
+    @10  go to state 153
+
+
+state 121
+
+  126 Stmnt: INAME . @23 '(' args ')' @24 Stmnt
+
+    $default  reduce using rule 124 (@23)
+
+    @23  go to state 201
+
+
+state 122
+
+  137 expr: '(' . expr ')'
+  159     | '(' . expr SEMI expr ':' expr ')'
+  186 Expr: '(' . Expr ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 202
+    Expr    go to state 203
+    Probe   go to state 135
+
+
+state 123
+
+  123 Stmnt: '{' . @22 sequence OS '}'
+
+    $default  reduce using rule 122 (@22)
+
+    @22  go to state 204
+
+
+state 124
+
+  107 Stmnt: ccode .
+
+    $default  reduce using rule 107 (Stmnt)
+
+
+state 125
+
+   46 body: '{' @8 sequence . OS @9 '}'
+   48 sequence: sequence . MS step
+
+    SEMI  shift, and go to state 205
+
+    $default  reduce using rule 131 (OS)
+
+    OS  go to state 206
+    MS  go to state 207
+
+
+state 126
+
+   47 sequence: step .
+
+    $default  reduce using rule 47 (sequence)
+
+
+state 127
+
+   49 step: one_decl .
+
+    $default  reduce using rule 49 (step)
+
+
+state 128
+
+   90 Special: varref . RCV @12 rargs
+   92        | varref . SND @13 margs
+   99 Stmnt: varref . ASGN expr
+  100      | varref . INCR
+  101      | varref . DECR
+  109      | varref . R_RCV @16 rargs
+  111      | varref . RCV @17 LT rargs GT
+  113      | varref . R_RCV @18 LT rargs GT
+  115      | varref . O_SND @19 margs
+  165 expr: varref . RCV @27 '[' rargs ']'
+  167     | varref . R_RCV @28 '[' rargs ']'
+  168     | varref .
+
+    ASGN   shift, and go to state 208
+    R_RCV  shift, and go to state 209
+    RCV    shift, and go to state 210
+    O_SND  shift, and go to state 211
+    SND    shift, and go to state 212
+    DECR   shift, and go to state 213
+    INCR   shift, and go to state 214
+
+    $default  reduce using rule 168 (expr)
+
+
+state 129
+
+   53 step: stmnt .
+   54     | stmnt . UNLESS stmnt
+
+    UNLESS  shift, and go to state 215
+
+    $default  reduce using rule 53 (step)
+
+
+state 130
+
+   87 stmnt: Special .
+
+    $default  reduce using rule 87 (stmnt)
+
+
+state 131
+
+   88 stmnt: Stmnt .
+
+    $default  reduce using rule 88 (stmnt)
+
+
+state 132
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  180 full_expr: expr .
+  191 Expr: expr . AND Expr
+  192     | expr . OR Expr
+
+    OR      shift, and go to state 216
+    AND     shift, and go to state 217
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 180 (full_expr)
+
+
+state 133
+
+  116 Stmnt: full_expr .
+
+    $default  reduce using rule 116 (Stmnt)
+
+
+state 134
+
+  181 full_expr: Expr .
+  187 Expr: Expr . AND Expr
+  188     | Expr . AND expr
+  189     | Expr . OR Expr
+  190     | Expr . OR expr
+
+    OR   shift, and go to state 218
+    AND  shift, and go to state 219
+
+    $default  reduce using rule 181 (full_expr)
+
+
+state 135
+
+  185 Expr: Probe .
+
+    $default  reduce using rule 185 (Expr)
+
+
+state 136
+
+   16 proc: inst proctype NAME @1 '(' . decl ')' @2 Opt_priority Opt_enabler body
+
+    HIDDEN   shift, and go to state 10
+    SHOW     shift, and go to state 11
+    ISLOCAL  shift, and go to state 12
+
+    ')'       reduce using rule 66 (decl)
+    $default  reduce using rule 55 (vis)
+
+    vis       go to state 29
+    one_decl  go to state 82
+    decl_lst  go to state 220
+    decl      go to state 221
+
+
+state 137
+
+   78 vardcl: NAME '[' CONST . ']'
+
+    ']'  shift, and go to state 222
+
+
+state 138
+
+   77 vardcl: NAME ':' CONST .
+
+    $default  reduce using rule 77 (vardcl)
+
+
+state 139
+
+  218 nlst: NAME .
+
+    $default  reduce using rule 218 (nlst)
+
+
+state 140
+
+   63 one_decl: vis TYPE asgn '{' nlst . '}'
+  219 nlst: nlst . NAME
+  220     | nlst . ','
+
+    NAME  shift, and go to state 223
+    '}'   shift, and go to state 224
+    ','   shift, and go to state 225
+
+
+state 141
+
+   71 var_list: ivar ',' var_list .
+
+    $default  reduce using rule 71 (var_list)
+
+
+state 142
+
+   75 ch_init: '[' . CONST ']' OF '{' typ_list '}'
+
+    CONST  shift, and go to state 226
+
+
+state 143
+
+   74 ivar: vardcl ASGN ch_init .
+
+    $default  reduce using rule 74 (ivar)
+
+
+state 144
+
+   73 ivar: vardcl ASGN expr .
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 73 (ivar)
+
+
+state 145
+
+   65 decl_lst: one_decl SEMI . decl_lst
+
+    HIDDEN   shift, and go to state 10
+    SHOW     shift, and go to state 11
+    ISLOCAL  shift, and go to state 12
+
+    $default  reduce using rule 55 (vis)
+
+    vis       go to state 29
+    one_decl  go to state 82
+    decl_lst  go to state 227
+
+
+state 146
+
+   30 utype: TYPEDEF NAME @6 '{' decl_lst '}' .
+
+    $default  reduce using rule 30 (utype)
+
+
+state 147
+
+  135 aname: NAME .
+
+    $default  reduce using rule 135 (aname)
+
+
+state 148
+
+  136 aname: PNAME .
+
+    $default  reduce using rule 136 (aname)
+
+
+state 149
+
+  161 expr: RUN aname . @26 '(' args ')' Opt_priority
+
+    $default  reduce using rule 160 (@26)
+
+    @26  go to state 228
+
+
+state 150
+
+  162 expr: LEN '(' . varref ')'
+
+    NAME  shift, and go to state 92
+
+    varref  go to state 229
+    pfld    go to state 100
+    cmpnd   go to state 101
+
+
+state 151
+
+  163 expr: ENABLED '(' . expr ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 230
+
+
+state 152
+
+  173 expr: PC_VAL '(' . expr ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 231
+
+
+state 153
+
+   82 pfld: NAME @10 . '[' expr ']'
+
+    '['  shift, and go to state 232
+
+
+state 154
+
+  174 expr: PNAME '[' . expr ']' '@' NAME
+  175     | PNAME '[' . expr ']' ':' pfld
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 233
+
+
+state 155
+
+  177 expr: PNAME ':' . pfld
+
+    NAME  shift, and go to state 92
+
+    pfld  go to state 234
+
+
+state 156
+
+  176 expr: PNAME '@' . NAME
+
+    NAME  shift, and go to state 235
+
+
+state 157
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  158     | SND expr .
+
+    $default  reduce using rule 158 (expr)
+
+
+state 158
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  157     | '-' expr .
+
+    $default  reduce using rule 157 (expr)
+
+
+state 159
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  156     | '~' expr .
+
+    $default  reduce using rule 156 (expr)
+
+
+state 160
+
+  137 expr: '(' expr . ')'
+  138     | expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  159     | '(' expr . SEMI expr ':' expr ')'
+
+    SEMI    shift, and go to state 236
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ')'     shift, and go to state 237
+
+
+state 161
+
+  167 expr: varref R_RCV . @28 '[' rargs ']'
+
+    $default  reduce using rule 166 (@28)
+
+    @28  go to state 238
+
+
+state 162
+
+  165 expr: varref RCV . @27 '[' rargs ']'
+
+    $default  reduce using rule 164 (@27)
+
+    @27  go to state 239
+
+
+state 163
+
+   84 cmpnd: pfld @11 . sfld
+
+    '.'  shift, and go to state 240
+
+    $default  reduce using rule 85 (sfld)
+
+    sfld  go to state 241
+
+
+state 164
+
+  153 expr: expr OR . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 242
+
+
+state 165
+
+  152 expr: expr AND . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 243
+
+
+state 166
+
+  145 expr: expr '|' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 244
+
+
+state 167
+
+  144 expr: expr '^' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 245
+
+
+state 168
+
+  143 expr: expr '&' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 246
+
+
+state 169
+
+  151 expr: expr NE . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 247
+
+
+state 170
+
+  150 expr: expr EQ . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 248
+
+
+state 171
+
+  149 expr: expr LE . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 249
+
+
+state 172
+
+  148 expr: expr GE . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 250
+
+
+state 173
+
+  147 expr: expr LT . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 251
+
+
+state 174
+
+  146 expr: expr GT . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 252
+
+
+state 175
+
+  155 expr: expr RSHIFT . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 253
+
+
+state 176
+
+  154 expr: expr LSHIFT . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 254
+
+
+state 177
+
+  138 expr: expr '+' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 255
+
+
+state 178
+
+  139 expr: expr '-' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 256
+
+
+state 179
+
+  140 expr: expr '*' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 257
+
+
+state 180
+
+  141 expr: expr '/' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 258
+
+
+state 181
+
+  142 expr: expr '%' . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 259
+
+
+state 182
+
+  209 arg: expr ',' . arg
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 102
+    arg     go to state 260
+
+
+state 183
+
+   34 ns: INLINE nm '(' @7 args ')' .
+
+    $default  reduce using rule 34 (ns)
+
+
+state 184
+
+  106 Stmnt: ASSERT full_expr .
+
+    $default  reduce using rule 106 (Stmnt)
+
+
+state 185
+
+  103 Stmnt: PRINT '(' . STRING @15 prargs ')'
+
+    STRING  shift, and go to state 261
+
+
+state 186
+
+  104 Stmnt: PRINTM '(' . varref ')'
+  105      | PRINTM '(' . CONST ')'
+
+    CONST  shift, and go to state 262
+    NAME   shift, and go to state 92
+
+    varref  go to state 263
+    pfld    go to state 100
+    cmpnd   go to state 101
+
+
+state 187
+
+   97 Special: GOTO NAME .
+
+    $default  reduce using rule 97 (Special)
+
+
+state 188
+
+  130 option: SEP . @25 sequence OS
+
+    $default  reduce using rule 129 (@25)
+
+    @25  go to state 264
+
+
+state 189
+
+   93 Special: IF options . FI
+
+    FI  shift, and go to state 265
+
+
+state 190
+
+  127 options: option .
+  128        | option . options
+
+    SEP  shift, and go to state 188
+
+    $default  reduce using rule 127 (options)
+
+    options  go to state 266
+    option   go to state 190
+
+
+state 191
+
+   95 Special: DO @14 . options OD
+
+    SEP  shift, and go to state 188
+
+    options  go to state 267
+    option   go to state 190
+
+
+state 192
+
+  119 Stmnt: ATOMIC '{' . @20 sequence OS '}'
+
+    $default  reduce using rule 118 (@20)
+
+    @20  go to state 268
+
+
+state 193
+
+  121 Stmnt: D_STEP '{' . @21 sequence OS '}'
+
+    $default  reduce using rule 120 (@21)
+
+    @21  go to state 269
+
+
+state 194
+
+  193 Probe: FULL '(' . varref ')'
+
+    NAME  shift, and go to state 92
+
+    varref  go to state 270
+    pfld    go to state 100
+    cmpnd   go to state 101
+
+
+state 195
+
+  195 Probe: EMPTY '(' . varref ')'
+
+    NAME  shift, and go to state 92
+
+    varref  go to state 271
+    pfld    go to state 100
+    cmpnd   go to state 101
+
+
+state 196
+
+  194 Probe: NFULL '(' . varref ')'
+
+    NAME  shift, and go to state 92
+
+    varref  go to state 272
+    pfld    go to state 100
+    cmpnd   go to state 101
+
+
+state 197
+
+  196 Probe: NEMPTY '(' . varref ')'
+
+    NAME  shift, and go to state 92
+
+    varref  go to state 273
+    pfld    go to state 100
+    cmpnd   go to state 101
+
+
+state 198
+
+   50 step: XU vref_lst .
+
+    $default  reduce using rule 50 (step)
+
+
+state 199
+
+   68 vref_lst: varref .
+   69         | varref . ',' vref_lst
+
+    ','  shift, and go to state 274
+
+    $default  reduce using rule 68 (vref_lst)
+
+
+state 200
+
+   51 step: NAME ':' . one_decl
+   52     | NAME ':' . XU
+   98 Special: NAME ':' . stmnt
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    HIDDEN       shift, and go to state 10
+    SHOW         shift, and go to state 11
+    ISLOCAL      shift, and go to state 12
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    XU           shift, and go to state 275
+    NAME         shift, and go to state 276
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    $default  reduce using rule 55 (vis)
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    vis        go to state 29
+    one_decl   go to state 277
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 278
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 201
+
+  126 Stmnt: INAME @23 . '(' args ')' @24 Stmnt
+
+    '('  shift, and go to state 279
+
+
+state 202
+
+  137 expr: '(' expr . ')'
+  138     | expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  159     | '(' expr . SEMI expr ':' expr ')'
+  191 Expr: expr . AND Expr
+  192     | expr . OR Expr
+
+    SEMI    shift, and go to state 236
+    OR      shift, and go to state 216
+    AND     shift, and go to state 217
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ')'     shift, and go to state 237
+
+
+state 203
+
+  186 Expr: '(' Expr . ')'
+  187     | Expr . AND Expr
+  188     | Expr . AND expr
+  189     | Expr . OR Expr
+  190     | Expr . OR expr
+
+    OR   shift, and go to state 218
+    AND  shift, and go to state 219
+    ')'  shift, and go to state 280
+
+
+state 204
+
+  123 Stmnt: '{' @22 . sequence OS '}'
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    HIDDEN       shift, and go to state 10
+    SHOW         shift, and go to state 11
+    ISLOCAL      shift, and go to state 12
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    XU           shift, and go to state 119
+    NAME         shift, and go to state 120
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    $default  reduce using rule 55 (vis)
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    sequence   go to state 281
+    step       go to state 126
+    vis        go to state 29
+    one_decl   go to state 127
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 129
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 205
+
+  132 OS: SEMI .
+  133 MS: SEMI .
+
+    FI        reduce using rule 132 (OS)
+    OD        reduce using rule 132 (OS)
+    SEP       reduce using rule 132 (OS)
+    '}'       reduce using rule 132 (OS)
+    $default  reduce using rule 133 (MS)
+
+
+state 206
+
+   46 body: '{' @8 sequence OS . @9 '}'
+
+    $default  reduce using rule 45 (@9)
+
+    @9  go to state 282
+
+
+state 207
+
+   48 sequence: sequence MS . step
+  134 MS: MS . SEMI
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    SEMI         shift, and go to state 283
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    HIDDEN       shift, and go to state 10
+    SHOW         shift, and go to state 11
+    ISLOCAL      shift, and go to state 12
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    XU           shift, and go to state 119
+    NAME         shift, and go to state 120
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    $default  reduce using rule 55 (vis)
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    step       go to state 284
+    vis        go to state 29
+    one_decl   go to state 127
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 129
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 208
+
+   99 Stmnt: varref ASGN . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 285
+
+
+state 209
+
+  109 Stmnt: varref R_RCV . @16 rargs
+  113      | varref R_RCV . @18 LT rargs GT
+  167 expr: varref R_RCV . @28 '[' rargs ']'
+
+    LT        reduce using rule 112 (@18)
+    '['       reduce using rule 166 (@28)
+    $default  reduce using rule 108 (@16)
+
+    @16  go to state 286
+    @18  go to state 287
+    @28  go to state 238
+
+
+state 210
+
+   90 Special: varref RCV . @12 rargs
+  111 Stmnt: varref RCV . @17 LT rargs GT
+  165 expr: varref RCV . @27 '[' rargs ']'
+
+    LT        reduce using rule 110 (@17)
+    '['       reduce using rule 164 (@27)
+    $default  reduce using rule 89 (@12)
+
+    @12  go to state 288
+    @17  go to state 289
+    @27  go to state 239
+
+
+state 211
+
+  115 Stmnt: varref O_SND . @19 margs
+
+    $default  reduce using rule 114 (@19)
+
+    @19  go to state 290
+
+
+state 212
+
+   92 Special: varref SND . @13 margs
+
+    $default  reduce using rule 91 (@13)
+
+    @13  go to state 291
+
+
+state 213
+
+  101 Stmnt: varref DECR .
+
+    $default  reduce using rule 101 (Stmnt)
+
+
+state 214
+
+  100 Stmnt: varref INCR .
+
+    $default  reduce using rule 100 (Stmnt)
+
+
+state 215
+
+   54 step: stmnt UNLESS . stmnt
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 276
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 292
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 216
+
+  153 expr: expr OR . expr
+  192 Expr: expr OR . Expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 293
+    Expr    go to state 294
+    Probe   go to state 135
+
+
+state 217
+
+  152 expr: expr AND . expr
+  191 Expr: expr AND . Expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 295
+    Expr    go to state 296
+    Probe   go to state 135
+
+
+state 218
+
+  189 Expr: Expr OR . Expr
+  190     | Expr OR . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 297
+    Expr    go to state 298
+    Probe   go to state 135
+
+
+state 219
+
+  187 Expr: Expr AND . Expr
+  188     | Expr AND . expr
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 299
+    Expr    go to state 300
+    Probe   go to state 135
+
+
+state 220
+
+   67 decl: decl_lst .
+
+    $default  reduce using rule 67 (decl)
+
+
+state 221
+
+   16 proc: inst proctype NAME @1 '(' decl . ')' @2 Opt_priority Opt_enabler body
+
+    ')'  shift, and go to state 301
+
+
+state 222
+
+   78 vardcl: NAME '[' CONST ']' .
+
+    $default  reduce using rule 78 (vardcl)
+
+
+state 223
+
+  219 nlst: nlst NAME .
+
+    $default  reduce using rule 219 (nlst)
+
+
+state 224
+
+   63 one_decl: vis TYPE asgn '{' nlst '}' .
+
+    $default  reduce using rule 63 (one_decl)
+
+
+state 225
+
+  220 nlst: nlst ',' .
+
+    $default  reduce using rule 220 (nlst)
+
+
+state 226
+
+   75 ch_init: '[' CONST . ']' OF '{' typ_list '}'
+
+    ']'  shift, and go to state 302
+
+
+state 227
+
+   65 decl_lst: one_decl SEMI decl_lst .
+
+    $default  reduce using rule 65 (decl_lst)
+
+
+state 228
+
+  161 expr: RUN aname @26 . '(' args ')' Opt_priority
+
+    '('  shift, and go to state 303
+
+
+state 229
+
+  162 expr: LEN '(' varref . ')'
+
+    ')'  shift, and go to state 304
+
+
+state 230
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  163     | ENABLED '(' expr . ')'
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ')'     shift, and go to state 305
+
+
+state 231
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  173     | PC_VAL '(' expr . ')'
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ')'     shift, and go to state 306
+
+
+state 232
+
+   82 pfld: NAME @10 '[' . expr ']'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 307
+
+
+state 233
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  174     | PNAME '[' expr . ']' '@' NAME
+  175     | PNAME '[' expr . ']' ':' pfld
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ']'     shift, and go to state 308
+
+
+state 234
+
+  177 expr: PNAME ':' pfld .
+
+    $default  reduce using rule 177 (expr)
+
+
+state 235
+
+  176 expr: PNAME '@' NAME .
+
+    $default  reduce using rule 176 (expr)
+
+
+state 236
+
+  159 expr: '(' expr SEMI . expr ':' expr ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 309
+
+
+state 237
+
+  137 expr: '(' expr ')' .
+
+    $default  reduce using rule 137 (expr)
+
+
+state 238
+
+  167 expr: varref R_RCV @28 . '[' rargs ']'
+
+    '['  shift, and go to state 310
+
+
+state 239
+
+  165 expr: varref RCV @27 . '[' rargs ']'
+
+    '['  shift, and go to state 311
+
+
+state 240
+
+   86 sfld: '.' . cmpnd
+
+    NAME  shift, and go to state 92
+
+    pfld   go to state 100
+    cmpnd  go to state 312
+
+
+state 241
+
+   84 cmpnd: pfld @11 sfld .
+
+    $default  reduce using rule 84 (cmpnd)
+
+
+state 242
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  153     | expr OR expr .
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 153 (expr)
+
+
+state 243
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  152     | expr AND expr .
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 152 (expr)
+
+
+state 244
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  145     | expr '|' expr .
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 145 (expr)
+
+
+state 245
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  144     | expr '^' expr .
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 144 (expr)
+
+
+state 246
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  143     | expr '&' expr .
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 143 (expr)
+
+
+state 247
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  151     | expr NE expr .
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 151 (expr)
+
+
+state 248
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  150     | expr EQ expr .
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 150 (expr)
+
+
+state 249
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  149     | expr LE expr .
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 149 (expr)
+
+
+state 250
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  148     | expr GE expr .
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 148 (expr)
+
+
+state 251
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  147     | expr LT expr .
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 147 (expr)
+
+
+state 252
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  146     | expr GT expr .
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 146 (expr)
+
+
+state 253
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  155     | expr RSHIFT expr .
+
+    '+'  shift, and go to state 177
+    '-'  shift, and go to state 178
+    '*'  shift, and go to state 179
+    '/'  shift, and go to state 180
+    '%'  shift, and go to state 181
+
+    $default  reduce using rule 155 (expr)
+
+
+state 254
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  154     | expr LSHIFT expr .
+  155     | expr . RSHIFT expr
+
+    '+'  shift, and go to state 177
+    '-'  shift, and go to state 178
+    '*'  shift, and go to state 179
+    '/'  shift, and go to state 180
+    '%'  shift, and go to state 181
+
+    $default  reduce using rule 154 (expr)
+
+
+state 255
+
+  138 expr: expr . '+' expr
+  138     | expr '+' expr .
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    '*'  shift, and go to state 179
+    '/'  shift, and go to state 180
+    '%'  shift, and go to state 181
+
+    $default  reduce using rule 138 (expr)
+
+
+state 256
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  139     | expr '-' expr .
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    '*'  shift, and go to state 179
+    '/'  shift, and go to state 180
+    '%'  shift, and go to state 181
+
+    $default  reduce using rule 139 (expr)
+
+
+state 257
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  140     | expr '*' expr .
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    $default  reduce using rule 140 (expr)
+
+
+state 258
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  141     | expr '/' expr .
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    $default  reduce using rule 141 (expr)
+
+
+state 259
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  142     | expr '%' expr .
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    $default  reduce using rule 142 (expr)
+
+
+state 260
+
+  209 arg: expr ',' arg .
+
+    $default  reduce using rule 209 (arg)
+
+
+state 261
+
+  103 Stmnt: PRINT '(' STRING . @15 prargs ')'
+
+    $default  reduce using rule 102 (@15)
+
+    @15  go to state 313
+
+
+state 262
+
+  105 Stmnt: PRINTM '(' CONST . ')'
+
+    ')'  shift, and go to state 314
+
+
+state 263
+
+  104 Stmnt: PRINTM '(' varref . ')'
+
+    ')'  shift, and go to state 315
+
+
+state 264
+
+  130 option: SEP @25 . sequence OS
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    HIDDEN       shift, and go to state 10
+    SHOW         shift, and go to state 11
+    ISLOCAL      shift, and go to state 12
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    XU           shift, and go to state 119
+    NAME         shift, and go to state 120
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    $default  reduce using rule 55 (vis)
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    sequence   go to state 316
+    step       go to state 126
+    vis        go to state 29
+    one_decl   go to state 127
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 129
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 265
+
+   93 Special: IF options FI .
+
+    $default  reduce using rule 93 (Special)
+
+
+state 266
+
+  128 options: option options .
+
+    $default  reduce using rule 128 (options)
+
+
+state 267
+
+   95 Special: DO @14 options . OD
+
+    OD  shift, and go to state 317
+
+
+state 268
+
+  119 Stmnt: ATOMIC '{' @20 . sequence OS '}'
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    HIDDEN       shift, and go to state 10
+    SHOW         shift, and go to state 11
+    ISLOCAL      shift, and go to state 12
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    XU           shift, and go to state 119
+    NAME         shift, and go to state 120
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    $default  reduce using rule 55 (vis)
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    sequence   go to state 318
+    step       go to state 126
+    vis        go to state 29
+    one_decl   go to state 127
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 129
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 269
+
+  121 Stmnt: D_STEP '{' @21 . sequence OS '}'
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    HIDDEN       shift, and go to state 10
+    SHOW         shift, and go to state 11
+    ISLOCAL      shift, and go to state 12
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    XU           shift, and go to state 119
+    NAME         shift, and go to state 120
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    $default  reduce using rule 55 (vis)
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    sequence   go to state 319
+    step       go to state 126
+    vis        go to state 29
+    one_decl   go to state 127
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 129
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 270
+
+  193 Probe: FULL '(' varref . ')'
+
+    ')'  shift, and go to state 320
+
+
+state 271
+
+  195 Probe: EMPTY '(' varref . ')'
+
+    ')'  shift, and go to state 321
+
+
+state 272
+
+  194 Probe: NFULL '(' varref . ')'
+
+    ')'  shift, and go to state 322
+
+
+state 273
+
+  196 Probe: NEMPTY '(' varref . ')'
+
+    ')'  shift, and go to state 323
+
+
+state 274
+
+   69 vref_lst: varref ',' . vref_lst
+
+    NAME  shift, and go to state 92
+
+    vref_lst  go to state 324
+    varref    go to state 199
+    pfld      go to state 100
+    cmpnd     go to state 101
+
+
+state 275
+
+   52 step: NAME ':' XU .
+
+    $default  reduce using rule 52 (step)
+
+
+state 276
+
+   80 pfld: NAME .
+   82     | NAME . @10 '[' expr ']'
+   98 Special: NAME . ':' stmnt
+
+    ':'  shift, and go to state 325
+
+    '['       reduce using rule 81 (@10)
+    $default  reduce using rule 80 (pfld)
+
+    @10  go to state 153
+
+
+state 277
+
+   51 step: NAME ':' one_decl .
+
+    $default  reduce using rule 51 (step)
+
+
+state 278
+
+   98 Special: NAME ':' stmnt .
+
+    $default  reduce using rule 98 (Special)
+
+
+state 279
+
+  126 Stmnt: INAME @23 '(' . args ')' @24 Stmnt
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    $default  reduce using rule 202 (args)
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 102
+    args    go to state 326
+    arg     go to state 104
+
+
+state 280
+
+  186 Expr: '(' Expr ')' .
+
+    $default  reduce using rule 186 (Expr)
+
+
+state 281
+
+   48 sequence: sequence . MS step
+  123 Stmnt: '{' @22 sequence . OS '}'
+
+    SEMI  shift, and go to state 205
+
+    $default  reduce using rule 131 (OS)
+
+    OS  go to state 327
+    MS  go to state 207
+
+
+state 282
+
+   46 body: '{' @8 sequence OS @9 . '}'
+
+    '}'  shift, and go to state 328
+
+
+state 283
+
+  134 MS: MS SEMI .
+
+    $default  reduce using rule 134 (MS)
+
+
+state 284
+
+   48 sequence: sequence MS step .
+
+    $default  reduce using rule 48 (sequence)
+
+
+state 285
+
+   99 Stmnt: varref ASGN expr .
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 99 (Stmnt)
+
+
+state 286
+
+  109 Stmnt: varref R_RCV @16 . rargs
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 335
+
+
+state 287
+
+  113 Stmnt: varref R_RCV @18 . LT rargs GT
+
+    LT  shift, and go to state 336
+
+
+state 288
+
+   90 Special: varref RCV @12 . rargs
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 337
+
+
+state 289
+
+  111 Stmnt: varref RCV @17 . LT rargs GT
+
+    LT  shift, and go to state 338
+
+
+state 290
+
+  115 Stmnt: varref O_SND @19 . margs
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 339
+    margs   go to state 340
+    arg     go to state 341
+
+
+state 291
+
+   92 Special: varref SND @13 . margs
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 339
+    margs   go to state 342
+    arg     go to state 341
+
+
+state 292
+
+   54 step: stmnt UNLESS stmnt .
+
+    $default  reduce using rule 54 (step)
+
+
+state 293
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  153     | expr OR expr .
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  191 Expr: expr . AND Expr
+  192     | expr . OR Expr
+
+    AND     shift, and go to state 217
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 153 (expr)
+
+
+state 294
+
+  187 Expr: Expr . AND Expr
+  188     | Expr . AND expr
+  189     | Expr . OR Expr
+  190     | Expr . OR expr
+  192     | expr OR Expr .
+
+    AND  shift, and go to state 219
+
+    $default  reduce using rule 192 (Expr)
+
+
+state 295
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  152     | expr AND expr .
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  191 Expr: expr . AND Expr
+  192     | expr . OR Expr
+
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 152 (expr)
+
+
+state 296
+
+  187 Expr: Expr . AND Expr
+  188     | Expr . AND expr
+  189     | Expr . OR Expr
+  190     | Expr . OR expr
+  191     | expr AND Expr .
+
+    $default  reduce using rule 191 (Expr)
+
+
+state 297
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  190 Expr: Expr OR expr .
+  191     | expr . AND Expr
+  192     | expr . OR Expr
+
+    AND     shift, and go to state 217
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 190 (Expr)
+
+
+state 298
+
+  187 Expr: Expr . AND Expr
+  188     | Expr . AND expr
+  189     | Expr . OR Expr
+  189     | Expr OR Expr .
+  190     | Expr . OR expr
+
+    AND  shift, and go to state 219
+
+    $default  reduce using rule 189 (Expr)
+
+
+state 299
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  188 Expr: Expr AND expr .
+  191     | expr . AND Expr
+  192     | expr . OR Expr
+
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+
+    $default  reduce using rule 188 (Expr)
+
+
+state 300
+
+  187 Expr: Expr . AND Expr
+  187     | Expr AND Expr .
+  188     | Expr . AND expr
+  189     | Expr . OR Expr
+  190     | Expr . OR expr
+
+    $default  reduce using rule 187 (Expr)
+
+
+state 301
+
+   16 proc: inst proctype NAME @1 '(' decl ')' . @2 Opt_priority Opt_enabler body
+
+    $default  reduce using rule 15 (@2)
+
+    @2  go to state 343
+
+
+state 302
+
+   75 ch_init: '[' CONST ']' . OF '{' typ_list '}'
+
+    OF  shift, and go to state 344
+
+
+state 303
+
+  161 expr: RUN aname @26 '(' . args ')' Opt_priority
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    $default  reduce using rule 202 (args)
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 102
+    args    go to state 345
+    arg     go to state 104
+
+
+state 304
+
+  162 expr: LEN '(' varref ')' .
+
+    $default  reduce using rule 162 (expr)
+
+
+state 305
+
+  163 expr: ENABLED '(' expr ')' .
+
+    $default  reduce using rule 163 (expr)
+
+
+state 306
+
+  173 expr: PC_VAL '(' expr ')' .
+
+    $default  reduce using rule 173 (expr)
+
+
+state 307
+
+   82 pfld: NAME @10 '[' expr . ']'
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ']'     shift, and go to state 346
+
+
+state 308
+
+  174 expr: PNAME '[' expr ']' . '@' NAME
+  175     | PNAME '[' expr ']' . ':' pfld
+
+    ':'  shift, and go to state 347
+    '@'  shift, and go to state 348
+
+
+state 309
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  159     | '(' expr SEMI expr . ':' expr ')'
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ':'     shift, and go to state 349
+
+
+state 310
+
+  167 expr: varref R_RCV @28 '[' . rargs ']'
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 350
+
+
+state 311
+
+  165 expr: varref RCV @27 '[' . rargs ']'
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 351
+
+
+state 312
+
+   86 sfld: '.' cmpnd .
+
+    $default  reduce using rule 86 (sfld)
+
+
+state 313
+
+  103 Stmnt: PRINT '(' STRING @15 . prargs ')'
+
+    ','  shift, and go to state 352
+
+    $default  reduce using rule 204 (prargs)
+
+    prargs  go to state 353
+
+
+state 314
+
+  105 Stmnt: PRINTM '(' CONST ')' .
+
+    $default  reduce using rule 105 (Stmnt)
+
+
+state 315
+
+  104 Stmnt: PRINTM '(' varref ')' .
+
+    $default  reduce using rule 104 (Stmnt)
+
+
+state 316
+
+   48 sequence: sequence . MS step
+  130 option: SEP @25 sequence . OS
+
+    SEMI  shift, and go to state 205
+
+    $default  reduce using rule 131 (OS)
+
+    OS  go to state 354
+    MS  go to state 207
+
+
+state 317
+
+   95 Special: DO @14 options OD .
+
+    $default  reduce using rule 95 (Special)
+
+
+state 318
+
+   48 sequence: sequence . MS step
+  119 Stmnt: ATOMIC '{' @20 sequence . OS '}'
+
+    SEMI  shift, and go to state 205
+
+    $default  reduce using rule 131 (OS)
+
+    OS  go to state 355
+    MS  go to state 207
+
+
+state 319
+
+   48 sequence: sequence . MS step
+  121 Stmnt: D_STEP '{' @21 sequence . OS '}'
+
+    SEMI  shift, and go to state 205
+
+    $default  reduce using rule 131 (OS)
+
+    OS  go to state 356
+    MS  go to state 207
+
+
+state 320
+
+  193 Probe: FULL '(' varref ')' .
+
+    $default  reduce using rule 193 (Probe)
+
+
+state 321
+
+  195 Probe: EMPTY '(' varref ')' .
+
+    $default  reduce using rule 195 (Probe)
+
+
+state 322
+
+  194 Probe: NFULL '(' varref ')' .
+
+    $default  reduce using rule 194 (Probe)
+
+
+state 323
+
+  196 Probe: NEMPTY '(' varref ')' .
+
+    $default  reduce using rule 196 (Probe)
+
+
+state 324
+
+   69 vref_lst: varref ',' vref_lst .
+
+    $default  reduce using rule 69 (vref_lst)
+
+
+state 325
+
+   98 Special: NAME ':' . stmnt
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    GOTO         shift, and go to state 108
+    BREAK        shift, and go to state 109
+    ELSE         shift, and go to state 110
+    IF           shift, and go to state 111
+    DO           shift, and go to state 112
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 276
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    varref     go to state 128
+    pfld       go to state 100
+    cmpnd      go to state 101
+    stmnt      go to state 278
+    Special    go to state 130
+    Stmnt      go to state 131
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 326
+
+  126 Stmnt: INAME @23 '(' args . ')' @24 Stmnt
+
+    ')'  shift, and go to state 357
+
+
+state 327
+
+  123 Stmnt: '{' @22 sequence OS . '}'
+
+    '}'  shift, and go to state 358
+
+
+state 328
+
+   46 body: '{' @8 sequence OS @9 '}' .
+
+    $default  reduce using rule 46 (body)
+
+
+state 329
+
+  211 rarg: EVAL . '(' expr ')'
+
+    '('  shift, and go to state 359
+
+
+state 330
+
+  212 rarg: CONST .
+
+    $default  reduce using rule 212 (rarg)
+
+
+state 331
+
+  213 rarg: '-' . CONST
+
+    CONST  shift, and go to state 360
+
+
+state 332
+
+  217 rargs: '(' . rargs ')'
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 361
+
+
+state 333
+
+  210 rarg: varref .
+
+    $default  reduce using rule 210 (rarg)
+
+
+state 334
+
+  214 rargs: rarg .
+  215      | rarg . ',' rargs
+  216      | rarg . '(' rargs ')'
+
+    '('  shift, and go to state 362
+    ','  shift, and go to state 363
+
+    $default  reduce using rule 214 (rargs)
+
+
+state 335
+
+  109 Stmnt: varref R_RCV @16 rargs .
+
+    $default  reduce using rule 109 (Stmnt)
+
+
+state 336
+
+  113 Stmnt: varref R_RCV @18 LT . rargs GT
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 364
+
+
+state 337
+
+   90 Special: varref RCV @12 rargs .
+
+    $default  reduce using rule 90 (Special)
+
+
+state 338
+
+  111 Stmnt: varref RCV @17 LT . rargs GT
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 365
+
+
+state 339
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  207 margs: expr . '(' arg ')'
+  208 arg: expr .
+  209    | expr . ',' arg
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    '('     shift, and go to state 366
+    ','     shift, and go to state 182
+
+    $default  reduce using rule 208 (arg)
+
+
+state 340
+
+  115 Stmnt: varref O_SND @19 margs .
+
+    $default  reduce using rule 115 (Stmnt)
+
+
+state 341
+
+  206 margs: arg .
+
+    $default  reduce using rule 206 (margs)
+
+
+state 342
+
+   92 Special: varref SND @13 margs .
+
+    $default  reduce using rule 92 (Special)
+
+
+state 343
+
+   16 proc: inst proctype NAME @1 '(' decl ')' @2 . Opt_priority Opt_enabler body
+
+    PRIORITY  shift, and go to state 57
+
+    $default  reduce using rule 178 (Opt_priority)
+
+    Opt_priority  go to state 367
+
+
+state 344
+
+   75 ch_init: '[' CONST ']' OF . '{' typ_list '}'
+
+    '{'  shift, and go to state 368
+
+
+state 345
+
+  161 expr: RUN aname @26 '(' args . ')' Opt_priority
+
+    ')'  shift, and go to state 369
+
+
+state 346
+
+   82 pfld: NAME @10 '[' expr ']' .
+
+    $default  reduce using rule 82 (pfld)
+
+
+state 347
+
+  175 expr: PNAME '[' expr ']' ':' . pfld
+
+    NAME  shift, and go to state 92
+
+    pfld  go to state 370
+
+
+state 348
+
+  174 expr: PNAME '[' expr ']' '@' . NAME
+
+    NAME  shift, and go to state 371
+
+
+state 349
+
+  159 expr: '(' expr SEMI expr ':' . expr ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 372
+
+
+state 350
+
+  167 expr: varref R_RCV @28 '[' rargs . ']'
+
+    ']'  shift, and go to state 373
+
+
+state 351
+
+  165 expr: varref RCV @27 '[' rargs . ']'
+
+    ']'  shift, and go to state 374
+
+
+state 352
+
+  205 prargs: ',' . arg
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 102
+    arg     go to state 375
+
+
+state 353
+
+  103 Stmnt: PRINT '(' STRING @15 prargs . ')'
+
+    ')'  shift, and go to state 376
+
+
+state 354
+
+  130 option: SEP @25 sequence OS .
+
+    $default  reduce using rule 130 (option)
+
+
+state 355
+
+  119 Stmnt: ATOMIC '{' @20 sequence OS . '}'
+
+    '}'  shift, and go to state 377
+
+
+state 356
+
+  121 Stmnt: D_STEP '{' @21 sequence OS . '}'
+
+    '}'  shift, and go to state 378
+
+
+state 357
+
+  126 Stmnt: INAME @23 '(' args ')' . @24 Stmnt
+
+    $default  reduce using rule 125 (@24)
+
+    @24  go to state 379
+
+
+state 358
+
+  123 Stmnt: '{' @22 sequence OS '}' .
+
+    $default  reduce using rule 123 (Stmnt)
+
+
+state 359
+
+  211 rarg: EVAL '(' . expr ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 380
+
+
+state 360
+
+  213 rarg: '-' CONST .
+
+    $default  reduce using rule 213 (rarg)
+
+
+state 361
+
+  217 rargs: '(' rargs . ')'
+
+    ')'  shift, and go to state 381
+
+
+state 362
+
+  216 rargs: rarg '(' . rargs ')'
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 382
+
+
+state 363
+
+  215 rargs: rarg ',' . rargs
+
+    EVAL   shift, and go to state 329
+    CONST  shift, and go to state 330
+    NAME   shift, and go to state 92
+    '-'    shift, and go to state 331
+    '('    shift, and go to state 332
+
+    varref  go to state 333
+    pfld    go to state 100
+    cmpnd   go to state 101
+    rarg    go to state 334
+    rargs   go to state 383
+
+
+state 364
+
+  113 Stmnt: varref R_RCV @18 LT rargs . GT
+
+    GT  shift, and go to state 384
+
+
+state 365
+
+  111 Stmnt: varref RCV @17 LT rargs . GT
+
+    GT  shift, and go to state 385
+
+
+state 366
+
+  207 margs: expr '(' . arg ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 97
+
+    cexpr   go to state 98
+    varref  go to state 99
+    pfld    go to state 100
+    cmpnd   go to state 101
+    expr    go to state 102
+    arg     go to state 386
+
+
+state 367
+
+   16 proc: inst proctype NAME @1 '(' decl ')' @2 Opt_priority . Opt_enabler body
+
+    PROVIDED  shift, and go to state 387
+
+    $default  reduce using rule 182 (Opt_enabler)
+
+    Opt_enabler  go to state 388
+
+
+state 368
+
+   75 ch_init: '[' CONST ']' OF '{' . typ_list '}'
+
+    error  shift, and go to state 389
+    TYPE   shift, and go to state 390
+    UNAME  shift, and go to state 391
+
+    basetype  go to state 392
+    typ_list  go to state 393
+
+
+state 369
+
+  161 expr: RUN aname @26 '(' args ')' . Opt_priority
+
+    PRIORITY  shift, and go to state 57
+
+    $default  reduce using rule 178 (Opt_priority)
+
+    Opt_priority  go to state 394
+
+
+state 370
+
+  175 expr: PNAME '[' expr ']' ':' pfld .
+
+    $default  reduce using rule 175 (expr)
+
+
+state 371
+
+  174 expr: PNAME '[' expr ']' '@' NAME .
+
+    $default  reduce using rule 174 (expr)
+
+
+state 372
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  159     | '(' expr SEMI expr ':' expr . ')'
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ')'     shift, and go to state 395
+
+
+state 373
+
+  167 expr: varref R_RCV @28 '[' rargs ']' .
+
+    $default  reduce using rule 167 (expr)
+
+
+state 374
+
+  165 expr: varref RCV @27 '[' rargs ']' .
+
+    $default  reduce using rule 165 (expr)
+
+
+state 375
+
+  205 prargs: ',' arg .
+
+    $default  reduce using rule 205 (prargs)
+
+
+state 376
+
+  103 Stmnt: PRINT '(' STRING @15 prargs ')' .
+
+    $default  reduce using rule 103 (Stmnt)
+
+
+state 377
+
+  119 Stmnt: ATOMIC '{' @20 sequence OS '}' .
+
+    $default  reduce using rule 119 (Stmnt)
+
+
+state 378
+
+  121 Stmnt: D_STEP '{' @21 sequence OS '}' .
+
+    $default  reduce using rule 121 (Stmnt)
+
+
+state 379
+
+  126 Stmnt: INAME @23 '(' args ')' @24 . Stmnt
+
+    ASSERT       shift, and go to state 105
+    PRINT        shift, and go to state 106
+    PRINTM       shift, and go to state 107
+    C_CODE       shift, and go to state 2
+    C_DECL       shift, and go to state 3
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    ELSE         shift, and go to state 110
+    ATOMIC       shift, and go to state 113
+    D_STEP       shift, and go to state 114
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    INAME        shift, and go to state 121
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+    '{'          shift, and go to state 123
+
+    ccode      go to state 124
+    cexpr      go to state 98
+    varref     go to state 396
+    pfld       go to state 100
+    cmpnd      go to state 101
+    Stmnt      go to state 397
+    expr       go to state 132
+    full_expr  go to state 133
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 380
+
+  138 expr: expr . '+' expr
+  139     | expr . '-' expr
+  140     | expr . '*' expr
+  141     | expr . '/' expr
+  142     | expr . '%' expr
+  143     | expr . '&' expr
+  144     | expr . '^' expr
+  145     | expr . '|' expr
+  146     | expr . GT expr
+  147     | expr . LT expr
+  148     | expr . GE expr
+  149     | expr . LE expr
+  150     | expr . EQ expr
+  151     | expr . NE expr
+  152     | expr . AND expr
+  153     | expr . OR expr
+  154     | expr . LSHIFT expr
+  155     | expr . RSHIFT expr
+  211 rarg: EVAL '(' expr . ')'
+
+    OR      shift, and go to state 164
+    AND     shift, and go to state 165
+    '|'     shift, and go to state 166
+    '^'     shift, and go to state 167
+    '&'     shift, and go to state 168
+    NE      shift, and go to state 169
+    EQ      shift, and go to state 170
+    LE      shift, and go to state 171
+    GE      shift, and go to state 172
+    LT      shift, and go to state 173
+    GT      shift, and go to state 174
+    RSHIFT  shift, and go to state 175
+    LSHIFT  shift, and go to state 176
+    '+'     shift, and go to state 177
+    '-'     shift, and go to state 178
+    '*'     shift, and go to state 179
+    '/'     shift, and go to state 180
+    '%'     shift, and go to state 181
+    ')'     shift, and go to state 398
+
+
+state 381
+
+  217 rargs: '(' rargs ')' .
+
+    $default  reduce using rule 217 (rargs)
+
+
+state 382
+
+  216 rargs: rarg '(' rargs . ')'
+
+    ')'  shift, and go to state 399
+
+
+state 383
+
+  215 rargs: rarg ',' rargs .
+
+    $default  reduce using rule 215 (rargs)
+
+
+state 384
+
+  113 Stmnt: varref R_RCV @18 LT rargs GT .
+
+    $default  reduce using rule 113 (Stmnt)
+
+
+state 385
+
+  111 Stmnt: varref RCV @17 LT rargs GT .
+
+    $default  reduce using rule 111 (Stmnt)
+
+
+state 386
+
+  207 margs: expr '(' arg . ')'
+
+    ')'  shift, and go to state 400
+
+
+state 387
+
+  183 Opt_enabler: PROVIDED . '(' full_expr ')'
+  184            | PROVIDED . error
+
+    error  shift, and go to state 401
+    '('    shift, and go to state 402
+
+
+state 388
+
+   16 proc: inst proctype NAME @1 '(' decl ')' @2 Opt_priority Opt_enabler . body
+
+    '{'  shift, and go to state 54
+
+    body  go to state 403
+
+
+state 389
+
+  199 basetype: error .
+
+    $default  reduce using rule 199 (basetype)
+
+
+state 390
+
+  197 basetype: TYPE .
+
+    $default  reduce using rule 197 (basetype)
+
+
+state 391
+
+  198 basetype: UNAME .
+
+    $default  reduce using rule 198 (basetype)
+
+
+state 392
+
+  200 typ_list: basetype .
+  201         | basetype . ',' typ_list
+
+    ','  shift, and go to state 404
+
+    $default  reduce using rule 200 (typ_list)
+
+
+state 393
+
+   75 ch_init: '[' CONST ']' OF '{' typ_list . '}'
+
+    '}'  shift, and go to state 405
+
+
+state 394
+
+  161 expr: RUN aname @26 '(' args ')' Opt_priority .
+
+    $default  reduce using rule 161 (expr)
+
+
+state 395
+
+  159 expr: '(' expr SEMI expr ':' expr ')' .
+
+    $default  reduce using rule 159 (expr)
+
+
+state 396
+
+   99 Stmnt: varref . ASGN expr
+  100      | varref . INCR
+  101      | varref . DECR
+  109      | varref . R_RCV @16 rargs
+  111      | varref . RCV @17 LT rargs GT
+  113      | varref . R_RCV @18 LT rargs GT
+  115      | varref . O_SND @19 margs
+  165 expr: varref . RCV @27 '[' rargs ']'
+  167     | varref . R_RCV @28 '[' rargs ']'
+  168     | varref .
+
+    ASGN   shift, and go to state 208
+    R_RCV  shift, and go to state 209
+    RCV    shift, and go to state 406
+    O_SND  shift, and go to state 211
+    DECR   shift, and go to state 213
+    INCR   shift, and go to state 214
+
+    $default  reduce using rule 168 (expr)
+
+
+state 397
+
+  126 Stmnt: INAME @23 '(' args ')' @24 Stmnt .
+
+    $default  reduce using rule 126 (Stmnt)
+
+
+state 398
+
+  211 rarg: EVAL '(' expr ')' .
+
+    $default  reduce using rule 211 (rarg)
+
+
+state 399
+
+  216 rargs: rarg '(' rargs ')' .
+
+    $default  reduce using rule 216 (rargs)
+
+
+state 400
+
+  207 margs: expr '(' arg ')' .
+
+    $default  reduce using rule 207 (margs)
+
+
+state 401
+
+  184 Opt_enabler: PROVIDED error .
+
+    $default  reduce using rule 184 (Opt_enabler)
+
+
+state 402
+
+  183 Opt_enabler: PROVIDED '(' . full_expr ')'
+
+    C_EXPR       shift, and go to state 84
+    RUN          shift, and go to state 85
+    LEN          shift, and go to state 86
+    ENABLED      shift, and go to state 87
+    PC_VAL       shift, and go to state 88
+    TIMEOUT      shift, and go to state 89
+    NONPROGRESS  shift, and go to state 90
+    FULL         shift, and go to state 115
+    EMPTY        shift, and go to state 116
+    NFULL        shift, and go to state 117
+    NEMPTY       shift, and go to state 118
+    CONST        shift, and go to state 91
+    NAME         shift, and go to state 92
+    PNAME        shift, and go to state 93
+    SND          shift, and go to state 94
+    '-'          shift, and go to state 95
+    '~'          shift, and go to state 96
+    '('          shift, and go to state 122
+
+    cexpr      go to state 98
+    varref     go to state 99
+    pfld       go to state 100
+    cmpnd      go to state 101
+    expr       go to state 132
+    full_expr  go to state 407
+    Expr       go to state 134
+    Probe      go to state 135
+
+
+state 403
+
+   16 proc: inst proctype NAME @1 '(' decl ')' @2 Opt_priority Opt_enabler body .
+
+    $default  reduce using rule 16 (proc)
+
+
+state 404
+
+  201 typ_list: basetype ',' . typ_list
+
+    error  shift, and go to state 389
+    TYPE   shift, and go to state 390
+    UNAME  shift, and go to state 391
+
+    basetype  go to state 392
+    typ_list  go to state 408
+
+
+state 405
+
+   75 ch_init: '[' CONST ']' OF '{' typ_list '}' .
+
+    $default  reduce using rule 75 (ch_init)
+
+
+state 406
+
+  111 Stmnt: varref RCV . @17 LT rargs GT
+  165 expr: varref RCV . @27 '[' rargs ']'
+
+    '['       reduce using rule 164 (@27)
+    $default  reduce using rule 110 (@17)
+
+    @17  go to state 289
+    @27  go to state 239
+
+
+state 407
+
+  183 Opt_enabler: PROVIDED '(' full_expr . ')'
+
+    ')'  shift, and go to state 409
+
+
+state 408
+
+  201 typ_list: basetype ',' typ_list .
+
+    $default  reduce using rule 201 (typ_list)
+
+
+state 409
+
+  183 Opt_enabler: PROVIDED '(' full_expr ')' .
+
+    $default  reduce using rule 183 (Opt_enabler)
diff --git a/trunk/verif/Spin/Src5.1.6/y.tab.h b/trunk/verif/Spin/Src5.1.6/y.tab.h
new file mode 100644 (file)
index 0000000..2a96367
--- /dev/null
@@ -0,0 +1,209 @@
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
+
+/* Tokens.  */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+   /* Put the tokens into the symbol table, so that GDB and other debuggers
+      know about them.  */
+   enum yytokentype {
+     ASSERT = 258,
+     PRINT = 259,
+     PRINTM = 260,
+     C_CODE = 261,
+     C_DECL = 262,
+     C_EXPR = 263,
+     C_STATE = 264,
+     C_TRACK = 265,
+     RUN = 266,
+     LEN = 267,
+     ENABLED = 268,
+     EVAL = 269,
+     PC_VAL = 270,
+     TYPEDEF = 271,
+     MTYPE = 272,
+     INLINE = 273,
+     LABEL = 274,
+     OF = 275,
+     GOTO = 276,
+     BREAK = 277,
+     ELSE = 278,
+     SEMI = 279,
+     IF = 280,
+     FI = 281,
+     DO = 282,
+     OD = 283,
+     SEP = 284,
+     ATOMIC = 285,
+     NON_ATOMIC = 286,
+     D_STEP = 287,
+     UNLESS = 288,
+     TIMEOUT = 289,
+     NONPROGRESS = 290,
+     ACTIVE = 291,
+     PROCTYPE = 292,
+     D_PROCTYPE = 293,
+     HIDDEN = 294,
+     SHOW = 295,
+     ISLOCAL = 296,
+     PRIORITY = 297,
+     PROVIDED = 298,
+     FULL = 299,
+     EMPTY = 300,
+     NFULL = 301,
+     NEMPTY = 302,
+     CONST = 303,
+     TYPE = 304,
+     XU = 305,
+     NAME = 306,
+     UNAME = 307,
+     PNAME = 308,
+     INAME = 309,
+     STRING = 310,
+     CLAIM = 311,
+     TRACE = 312,
+     INIT = 313,
+     ASGN = 314,
+     R_RCV = 315,
+     RCV = 316,
+     O_SND = 317,
+     SND = 318,
+     OR = 319,
+     AND = 320,
+     NE = 321,
+     EQ = 322,
+     LE = 323,
+     GE = 324,
+     LT = 325,
+     GT = 326,
+     RSHIFT = 327,
+     LSHIFT = 328,
+     DECR = 329,
+     INCR = 330,
+     NEG = 331,
+     UMIN = 332,
+     DOT = 333
+   };
+#endif
+/* Tokens.  */
+#define ASSERT 258
+#define PRINT 259
+#define PRINTM 260
+#define C_CODE 261
+#define C_DECL 262
+#define C_EXPR 263
+#define C_STATE 264
+#define C_TRACK 265
+#define RUN 266
+#define LEN 267
+#define ENABLED 268
+#define EVAL 269
+#define PC_VAL 270
+#define TYPEDEF 271
+#define MTYPE 272
+#define INLINE 273
+#define LABEL 274
+#define OF 275
+#define GOTO 276
+#define BREAK 277
+#define ELSE 278
+#define SEMI 279
+#define IF 280
+#define FI 281
+#define DO 282
+#define OD 283
+#define SEP 284
+#define ATOMIC 285
+#define NON_ATOMIC 286
+#define D_STEP 287
+#define UNLESS 288
+#define TIMEOUT 289
+#define NONPROGRESS 290
+#define ACTIVE 291
+#define PROCTYPE 292
+#define D_PROCTYPE 293
+#define HIDDEN 294
+#define SHOW 295
+#define ISLOCAL 296
+#define PRIORITY 297
+#define PROVIDED 298
+#define FULL 299
+#define EMPTY 300
+#define NFULL 301
+#define NEMPTY 302
+#define CONST 303
+#define TYPE 304
+#define XU 305
+#define NAME 306
+#define UNAME 307
+#define PNAME 308
+#define INAME 309
+#define STRING 310
+#define CLAIM 311
+#define TRACE 312
+#define INIT 313
+#define ASGN 314
+#define R_RCV 315
+#define RCV 316
+#define O_SND 317
+#define SND 318
+#define OR 319
+#define AND 320
+#define NE 321
+#define EQ 322
+#define LE 323
+#define GE 324
+#define LT 325
+#define GT 326
+#define RSHIFT 327
+#define LSHIFT 328
+#define DECR 329
+#define INCR 330
+#define NEG 331
+#define UMIN 332
+#define DOT 333
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef int YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
diff --git a/trunk/verif/Spin/Test/README.tests b/trunk/verif/Spin/Test/README.tests
new file mode 100755 (executable)
index 0000000..f072ccd
--- /dev/null
@@ -0,0 +1,308 @@
+-- Updated for SPIN Version 5.0 --- October 2007 ---
+
+Perform tests test0 to test5 in the order listed, and
+make sure you get the same results.
+The next four tests are to assess the effect of
+partial order reductions.  In exhaustive mode, they
+may not all be executable within the bounds of your
+system - with reduction turned on, though, they should
+all run as specified.
+The last test checks the use of execution priorities
+during random simulations.
+
+The file called 'pathfinder' illustrates the use of
+'provided' clauses (using as inspiration the bug in
+the control software of the Mars pathfinder that
+spotted an otherwise perfect mission in July 1997)
+
+       You can always check valid options of spin
+       by typing (at command prompt $):
+               $ spin --
+
+       Similarly, you can check valid options of
+       the compiled verifiers by typing:
+               $ pan --
+
+test 0 check that spin exists, is executable, and is
+       the version that you expect
+
+       $ spin -V
+       Spin Version 5.0 -- 26 October 2007
+
+test 1 check that you can run a simulation
+
+       $ spin hello
+               passed first test!
+       1 process created
+
+       or without the default indenting of output:
+
+       $ spin -T hello
+       passed first test!
+       1 process created
+
+test 2 a basic reachability check (safety)
+
+       $ spin -a loops              # generate c-verifier
+       $ cc -DNOREDUCE -o pan pan.c # no reduction (test)
+       $ ./pan                        # default run
+       hint: this search is more efficient if pan.c is compiled -DSAFETY
+
+       (Spin Version 5.0 -- 26 October 2007)
+
+       Full statespace search for:
+               never-claim             - (none specified)
+               assertion violations    +
+               acceptance   cycles     - (not selected)
+               invalid endstates       +
+       
+       State-vector 12 byte, depth reached 11, errors: 0
+             15 states, stored
+              4 states, matched
+             19 transitions (= stored+matched)
+              0 atomic steps
+       hash conflicts: 0 (resolved)
+       
+       2.501     memory usage (Mbyte)
+
+       unreached in proctype loop
+               line 12, state 12, "-end-"
+               (1 of 12 states)
+
+       pan: elapsed time 0 seconds
+
+test 3 cycle detection check (liveness):
+
+       $ ./pan -a              # search for acceptance cycles
+       pan: acceptance cycle (at depth 0)
+       pan: wrote loops.trail
+       (Spin Version 5.0 -- 26 October 2007)
+       Warning: Search not completed
+       
+       Full statespace search for:
+               never-claim             - (none specified)
+               assertion violations    +
+>              acceptance   cycles     + (fairness disabled)
+               invalid endstates       +
+       
+       State-vector 12 byte, depth reached 11, errors: 1
+             13 states, stored (15 visited)
+              2 states, matched
+             17 transitions (= visited+matched)
+              0 atomic steps
+       hash conflicts: 0 (resolved)
+       
+       2.501     memory usage (Mbyte)
+
+       pan: elapsed time 0.015 seconds
+       pan: rate      1000 states/second
+
+test 4 guided simulation check (playback the error trail found in test 3)
+
+       $ spin -t -p loops      # guided simulation for the error-cycle
+       Starting loop with pid 0
+         <<<<<START OF CYCLE>>>>>
+         1:    proc  0 (loop) line   5 "loops" (state 1)       [a = ((a+1)%3)]
+         2:    proc  0 (loop) line   7 "loops" (state 2)       [b = (2*a)]
+         3:    proc  0 (loop) line   7 "loops" (state 3)       [(1)]
+         4:    proc  0 (loop) line  10 "loops" (state 8)       [b = (b-1)]
+         5:    proc  0 (loop) line   5 "loops" (state 1)       [a = ((a+1)%3)]
+         6:    proc  0 (loop) line   7 "loops" (state 2)       [b = (2*a)]
+         7:    proc  0 (loop) line   7 "loops" (state 3)       [(1)]
+         8:    proc  0 (loop) line  10 "loops" (state 8)       [b = (b-1)]
+         9:    proc  0 (loop) line   5 "loops" (state 1)       [a = ((a+1)%3)]
+        10:    proc  0 (loop) line   8 "loops" (state 4)       [b = (2*a)]
+        11:    proc  0 (loop) line   8 "loops" (state 5)       [(1)]
+       spin: line  10 "loops", Error: value (-1->255 (8)) truncated in assignment
+        12:    proc  0 (loop) line  10 "loops" (state 8)       [b = (b-1)]
+       spin: trail ends after 12 steps
+       #processes: 1
+        12:    proc  0 (loop) line   4 "loops" (state 9)
+       1 process created
+
+test 5 try to find a cycle that avoids the progress labels (there are none)
+
+       $ cc -DNP -DNOREDUCE -o pan pan.c # add support for non-progress
+       $ ./pan -l              # search for non-progress cycles
+
+       (Spin Version 5.0 -- 26 October 2007)
+       
+       Full statespace search for:
+               never claim             +
+               assertion violations    + (if within scope of claim)
+               non-progress cycles     + (fairness disabled)
+               invalid end states      - (disabled by never claim)
+       
+       State-vector 16 byte, depth reached 23, errors: 0
+              27 states, stored (39 visited)
+              28 states, matched
+              67 transitions (= visited+matched)
+               0 atomic steps
+       hash conflicts:         0 (resolved)
+       
+       2.501           memory usage (Mbyte)
+       
+       unreached in proctype loop
+               line 12, state 12, "-end-"
+               (1 of 12 states)
+       
+       pan: elapsed time 0 seconds
+
+test 6:        check partial order reduction algorithm -- first disable it
+
+       $ spin -a leader (or snoopy, pftp, sort)
+       $ cc -DSAFETY -DNOREDUCE -DNOCLAIM -o pan pan.c # safety only
+       $ ./pan -c0 -n                # exhaustive, -c0 = ignore errors
+       (Spin Version 5.0 -- 26 October 2007)
+
+       Full statespace search for:
+               never claim             - (not selected)
+               assertion violations    +
+               cycle checks            - (disabled by -DSAFETY)
+               invalid end states      +
+       
+       State-vector 196 byte, depth reached 108, errors: 0
+           15779 states, stored
+           42402 states, matched
+           58181 transitions (= stored+matched)
+              12 atomic steps
+       hash conflicts:       440 (resolved)
+       
+       Stats on memory usage (in Megabytes):
+       3.010           equivalent memory usage for states (stored*(State-vector + overhead))
+       2.731           actual memory usage for states (compression: 90.73%)
+                       state-vector as stored = 177 byte + 4 byte overhead
+       2.000           memory used for hash table (-w19)
+       0.267           memory used for DFS stack (-m10000)
+       0.094           memory lost to fragmentation
+       4.904           total actual memory usage
+       
+       pan: elapsed time 0.125 seconds
+       pan: rate    126232 states/second
+
+test 6b: now leave p.o. reduction enabled (i.e., do not disable it)
+
+       $ cc -DSAFETY -DNOCLAIM -o pan pan.c  # safety only, reduced search
+       $ ./pan -c0 -n                # -n = no dead code listing
+
+       (Spin Version 5.0 -- 26 October 2007)
+               + Partial Order Reduction
+       
+       Full statespace search for:
+               never claim             - (not selected)
+               assertion violations    +
+               cycle checks            - (disabled by -DSAFETY)
+               invalid end states      +
+       
+       State-vector 196 byte, depth reached 108, errors: 0
+              97 states, stored
+               0 states, matched
+              97 transitions (= stored+matched)
+              12 atomic steps
+       hash conflicts:         0 (resolved)
+       
+       2.501           memory usage (Mbyte)
+       
+       pan: elapsed time 0 seconds
+
+       If compiled as above, the results should match the results from the table below. 
+       The numbers in the first two columns of the table should match precisely.  
+       The numbers in the third column should match approximately (how well it matches
+       depends only on the properties of the C-compiler and the speed of the hardware
+       you use to run the tests.)
+       The first line for each test is for the exhaustive run, the second line is for
+       the default run using partial order reduction.
+       The times given are for a 2.4GHz dual-core Intel PC, with 2 GB of memory.
+
+       States Stored   Transitions     Memory Used     Time (s)
+leader
+       S=   15779      T=   58181      M= 4.904 Mb     t= 0.125
+       S=      97      T=      97      M= 2.501 Mb     t= <0.1
+
+snoopy
+       S=   61619      T=  211398      M= 8.03 Mb      t= 0.328
+       S=    9343      T=   12706      M= 3.38 Mb      t= 0.03
+
+pftp
+       S=  144813      T=  397948      M= 18.97 Mb     t= 0.79
+       S=   47356      T=   64970      M=  8.07 Mb     t= 0.14
+
+sort
+       S=  107713      T=  512419      M= 18.87 Mb     t= 1.08
+       S=     135      T=     135      M=  2.50 Mb     t= <0.1
+
+
+test 7 check random number generator
+
+       $ spin -p -g -u10000 priorities         # runs 10000 steps
+       ....
+       depth-limit (-u10000 steps) reached
+       #processes: 5
+                       a[0] = 0
+                       a[1] = 334
+                       a[2] = 677
+                       a[3] = 994
+                       a[4] = 1327
+       10000:  proc  4 (A) line  11 "priorities" (state 3)
+       10000:  proc  3 (A) line  12 "priorities" (state 2)
+       10000:  proc  2 (A) line  14 "priorities" (state 4)
+       10000:  proc  1 (A) line  11 "priorities" (state 3)
+       10000:  proc  0 (:init:) line  22 "priorities" (state 6) <valid end state>
+       5 processes created
+
+       The numbers in the array should tend to the ratio
+       1:2:3:4 if the random number generator works properly.
+       array index 0 remains unused (it's the pid of the init
+       process)
+
+test 8 test the generation of never claims from LTL formulae:
+
+       $ spin -f "[] ( p U ( <> q ))"
+
+       never {    /* [] ( p U ( <> q )) */
+       T0_init:
+               if
+               :: ((q)) -> goto accept_S9
+               :: (1) -> goto T0_init
+               fi;
+       accept_S9:
+               if
+               :: (1) -> goto T0_init
+               fi;
+       }
+
+test 9 read a never claim from a file
+
+       $ spin -a -N leader.ltl leader  # the claim is in file leader.ltl
+       $ cc -o pan pan.c               # the default compilation
+       $ ./pan -a                      # search for acceptance cycles
+       warning: for p.o. reduction to be valid the never claim must be stutter-invariant
+       (never claims generated from LTL formulae are stutter-invariant)
+       
+       (Spin Version 5.0 -- 26 October 2007)
+               + Partial Order Reduction
+       
+       Full statespace search for:
+               never claim             +
+               assertion violations    + (if within scope of claim)
+               acceptance   cycles     + (fairness disabled)
+               invalid end states      - (disabled by never claim)
+       
+       State-vector 204 byte, depth reached 205, errors: 0
+             181 states, stored (360 visited)
+             251 states, matched
+             611 transitions (= visited+matched)
+              24 atomic steps
+       hash conflicts:         0 (resolved)
+       
+       2.501           memory usage (Mbyte)
+       
+       unreached in proctype node
+               line 53, state 28, "out!two,nr"
+               (1 of 49 states)
+       unreached in proctype :init:
+               (0 of 11 states)
+       
+       pan: elapsed time 0 seconds
+
+end of tests
diff --git a/trunk/verif/Spin/Test/abp b/trunk/verif/Spin/Test/abp
new file mode 100755 (executable)
index 0000000..0b61890
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ *  a simple example of the use of inline's
+ *  (requires Spin version 3.2 or later)
+ *
+ */
+
+mtype = { msg0, msg1, ack0, ack1 };
+
+chan sender = [1] of { mtype };
+chan receiver = [1] of { mtype };
+
+inline phase(msg, good_ack, bad_ack)
+{
+       do
+       :: sender?good_ack -> break
+       :: sender?bad_ack
+       :: timeout -> 
+               if
+               :: receiver!msg;
+               :: skip /* lose message */
+               fi;
+       od
+}
+
+inline recv(cur_msg, cur_ack, lst_msg, lst_ack)
+{
+       do
+       :: receiver?cur_msg -> sender!cur_ack; break /* accept */
+       :: receiver?lst_msg -> sender!lst_ack
+       od;
+} 
+
+active proctype Sender()
+{
+       do
+       :: phase(msg1, ack1, ack0);
+          phase(msg0, ack0, ack1)
+       od
+}
+
+active proctype Receiver()
+{
+       do
+       :: recv(msg1, ack1, msg0, ack0);
+          recv(msg0, ack0, msg1, ack1)
+       od
+}
diff --git a/trunk/verif/Spin/Test/erathostenes b/trunk/verif/Spin/Test/erathostenes
new file mode 100755 (executable)
index 0000000..b14446c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+       The Sieve of Erathostenes
+       Prints all prime numbers up to PRIME_MAX
+*/
+#define PRIME_MAX      100
+
+chan count = [0] of { int };
+byte tries = 2;
+
+proctype sieve(chan c; int prime)
+{      int i, haschild;
+
+end:   do
+       :: c?i ->
+               if
+               :: (i%prime) ->
+                       if
+                       :: !haschild ->
+                               /* found a new prime */
+                               printf("MSC: %d\n", i);
+                               haschild++;
+                               chan child = [0] of { int };
+                               run sieve(child, i);
+                       :: else ->
+                               child!i
+                       fi;
+               :: else
+                       /* i is divisible by prime */
+               fi
+       od
+}
+
+init
+{
+       run sieve(count, 2);
+       do
+       :: (tries <  PRIME_MAX) -> count!tries; tries++
+       :: (tries >= PRIME_MAX) -> break
+       od
+}
diff --git a/trunk/verif/Spin/Test/eratosthenes b/trunk/verif/Spin/Test/eratosthenes
new file mode 100755 (executable)
index 0000000..36c4507
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+       The Sieve of Eratosthenes (c. 276-196 BC)
+       Prints all prime numbers up to MAX
+*/
+#define MAX    25
+
+mtype = { number, eof };
+
+chan root = [0] of { mtype, int };
+
+proctype sieve(chan c; int prime)
+{      chan child = [0] of { mtype, int };
+       bool haschild;
+       int n;
+
+       printf("MSC: %d is prime\n", prime);
+end:   do
+       :: c?number(n) ->
+               if
+               :: (n%prime) == 0 ->
+                       printf("MSC: %d = %d*%d\n", n, prime, n/prime)
+               :: else ->
+                       if
+                       :: !haschild -> /* new prime */
+                               haschild = true;
+                               run sieve(child, n);
+                       :: else ->
+                               child!number(n)
+                       fi;
+               fi
+       :: c?eof(0) ->
+               break
+       od;
+       if
+       :: haschild ->
+               child!eof(0)
+       :: else
+       fi
+}
+
+init
+{      int n = 2;
+
+       run sieve(root, n);
+       do
+       :: (n <  MAX) -> n++; root!number(n)
+       :: (n >= MAX) -> root!eof(0); break
+       od
+}
diff --git a/trunk/verif/Spin/Test/examples b/trunk/verif/Spin/Test/examples
new file mode 100755 (executable)
index 0000000..0edd887
--- /dev/null
@@ -0,0 +1,1171 @@
+# To unbundle, sh this file
+echo ex.readme 1>&2
+sed 's/.//' >ex.readme <<'//GO.SYSIN DD ex.readme'
+-The 12 files in this bundle are the PROMELA
+-files of all exercises and examples discussed
+-in the document Doc/Exercises.ps from the
+-SPIN distribution.
+//GO.SYSIN DD ex.readme
+echo ex.1a 1>&2
+sed 's/.//' >ex.1a <<'//GO.SYSIN DD ex.1a'
+-init {
+-      byte i = 0;
+-      do
+-      :: i = i+1
+-      od
+-}
+//GO.SYSIN DD ex.1a
+echo ex.1b 1>&2
+sed 's/.//' >ex.1b <<'//GO.SYSIN DD ex.1b'
+-init {
+-      chan dummy = [20] of { byte };
+-      do
+-      :: dummy!85
+-      :: dummy!170
+-      od
+-}
+//GO.SYSIN DD ex.1b
+echo ex.1c 1>&2
+sed 's/.//' >ex.1c <<'//GO.SYSIN DD ex.1c'
+-#define N     26
+-
+-int a;
+-byte b;
+-
+-init {
+-      do
+-      :: atomic { (b < N) ->
+-              if
+-              :: a = a + (1<<b)
+-              :: skip
+-              fi;
+-              b=b+1 }
+-      od
+-}
+//GO.SYSIN DD ex.1c
+echo ex.2 1>&2
+sed 's/.//' >ex.2 <<'//GO.SYSIN DD ex.2'
+-#define MAX 8
+-proctype A(chan in, out)
+-{     byte mt; /* message data */
+-      bit  vr;
+-S1:   mt = (mt+1)%MAX;
+-      out!mt,1;
+-      goto S2;
+-S2:   in?vr;
+-      if
+-      :: (vr == 1) -> goto S1
+-      :: (vr == 0) -> goto S3
+-      :: printf("AERROR1\n") -> goto S5
+-      fi;
+-S3:   out!mt,1;
+-      goto S4;
+-S4:   in?vr;
+-      if
+-      :: goto S1
+-      :: printf("AERROR2\n"); goto S5
+-      fi;
+-S5:   out!mt,0;
+-      goto S4
+-}
+-proctype B(chan in, out)
+-{     byte mr, lmr;
+-      bit ar;
+-      goto S2; /* initial state */
+-S1:   assert(mr == (lmr+1)%MAX);
+-      lmr = mr;
+-      out!1;
+-      goto S2;
+-S2:   in?mr,ar;
+-      if
+-      :: (ar == 1) -> goto S1
+-      :: (ar == 0) -> goto S3
+-      :: printf("ERROR1\n"); goto S5
+-      fi;
+-S3:   out!1;
+-      goto S2;
+-S4:   in?mr,ar;
+-      if
+-      :: goto S1
+-      :: printf("ERROR2\n"); goto S5
+-      fi;
+-S5:   out!0;
+-      goto S4
+-}
+-init {
+-      chan a2b = [2] of { bit };
+-      chan b2a = [2] of { byte, bit };
+-      atomic {
+-              run A(a2b, b2a);
+-              run B(b2a, a2b)
+-      }
+-}
+//GO.SYSIN DD ex.2
+echo ex.3 1>&2
+sed 's/.//' >ex.3 <<'//GO.SYSIN DD ex.3'
+-mtype = { a, b, c, d, e, i, l, m, n, q, r, u, v };
+-
+-chan dce = [0] of { mtype };
+-chan dte = [0] of { mtype };
+-
+-active proctype dte_proc()
+-{
+-state01:
+-      do
+-      :: dce!b -> /* state21 */ dce!a
+-      :: dce!i -> /* state14 */
+-                      if
+-                      :: dte?m -> goto state19
+-                      :: dce!a
+-                      fi
+-      :: dte?m -> goto state18
+-      :: dte?u -> goto state08
+-      :: dce!d -> break
+-      od;
+-
+-      /* state02: */
+-      if
+-      :: dte?v
+-      :: dte?u -> goto state15
+-      :: dte?m -> goto state19
+-      fi;
+-state03:
+-      dce!e;
+-      /* state04: */
+-      if
+-      :: dte?m -> goto state19
+-      :: dce!c
+-      fi;
+-      /* state05: */
+-      if
+-      :: dte?m -> goto state19
+-      :: dte?r
+-      fi;
+-      /* state6A: */
+-      if
+-      :: dte?m -> goto state19
+-      :: dte?q
+-      fi;
+-state07:
+-      if
+-      :: dte?m -> goto state19
+-      :: dte?r
+-      fi;
+-      /* state6B: */
+-      if              /* non-deterministic select */
+-      :: dte?q -> goto state07
+-      :: dte?q
+-      :: dte?m -> goto state19
+-      fi;
+-      /* state10: */
+-      if
+-      :: dte?m -> goto state19
+-      :: dte?r
+-      fi;
+-state6C:
+-      if
+-      :: dte?m -> goto state19
+-      :: dte?l
+-      fi;
+-      /* state11: */
+-      if
+-      :: dte?m -> goto state19
+-      :: dte?n
+-      fi;
+-      /* state12: */
+-      if
+-      :: dte?m -> goto state19
+-      :: dce!b -> goto state16
+-      fi;
+-
+-state15:
+-      if
+-      :: dte?v -> goto state03
+-      :: dte?m -> goto state19
+-      fi;
+-state08:
+-      if
+-      :: dce!c
+-      :: dce!d -> goto state15
+-      :: dte?m -> goto state19
+-      fi;
+-      /* state09: */
+-      if
+-      :: dte?m -> goto state19
+-      :: dte?q
+-      fi;
+-      /* state10B: */
+-      if
+-      :: dte?r -> goto state6C
+-      :: dte?m -> goto state19
+-      fi;
+-state18:
+-      if
+-      :: dte?l -> goto state01
+-      :: dte?m -> goto state19
+-      fi;
+-state16:
+-      dte?m;
+-      /* state17: */
+-      dte?l;
+-      /* state21: */
+-      dce!a; goto state01;
+-state19:
+-      dce!b;
+-      /* state20: */
+-      dte?l;
+-      /* state21: */
+-      dce!a; goto state01
+-}
+-
+-active proctype dce_proc()
+-{
+-state01:
+-      do
+-      :: dce?b -> /* state21 */ dce?a
+-      :: dce?i -> /* state14 */
+-                      if
+-                      :: dce?b -> goto state16
+-                      :: dce?a
+-                      fi
+-      :: dte!m -> goto state18
+-      :: dte!u -> goto state08
+-      :: dce?d -> break
+-      od;
+-
+-      /* state02: */
+-      if
+-      :: dte!v
+-      :: dte!u -> goto state15
+-      :: dce?b -> goto state16
+-      fi;
+-state03:
+-      dce?e;
+-      /* state04: */
+-      if
+-      :: dce?b -> goto state16
+-      :: dce?c
+-      fi;
+-      /* state05: */
+-      if
+-      :: dce?b -> goto state16
+-      :: dte!r
+-      fi;
+-      /* state6A: */
+-      if
+-      :: dce?b -> goto state16
+-      :: dte!q
+-      fi;
+-state07:
+-      if
+-      :: dce?b -> goto state16
+-      :: dte!r
+-      fi;
+-      /* state6B: */
+-      if              /* non-deterministic select */
+-      :: dte!q -> goto state07
+-      :: dte!q
+-      :: dce?b -> goto state16
+-      fi;
+-      /* state10: */
+-      if
+-      :: dce?b -> goto state16
+-      :: dte!r
+-      fi;
+-state6C:
+-      if
+-      :: dce?b -> goto state16
+-      :: dte!l
+-      fi;
+-      /* state11: */
+-      if
+-      :: dce?b -> goto state16
+-      :: dte!n
+-      fi;
+-      /* state12: */
+-      if
+-      :: dce?b -> goto state16
+-      :: dte!m -> goto state19
+-      fi;
+-
+-state15:
+-      if
+-      :: dte!v -> goto state03
+-      :: dce?b -> goto state16
+-      fi;
+-state08:
+-      if
+-      :: dce?c
+-      :: dce?d -> goto state15
+-      :: dce?b -> goto state16
+-      fi;
+-      /* state09: */
+-      if
+-      :: dce?b -> goto state16
+-      :: dte!q
+-      fi;
+-      /* state10B: */
+-      if
+-      :: dte!r -> goto state6C
+-      :: dce?b -> goto state16
+-      fi;
+-state18:
+-      if
+-      :: dte!l -> goto state01
+-      :: dce?b -> goto state16
+-      fi;
+-state16:
+-      dte!m;
+-      /* state17: */
+-      dte!l;
+-      /* state21: */
+-      dce?a; goto state01;
+-state19:
+-      dce?b;
+-      /* state20: */
+-      dte!l;
+-      /* state21: */
+-      dce?a; goto state01
+-}
+//GO.SYSIN DD ex.3
+echo ex.4b 1>&2
+sed 's/.//' >ex.4b <<'//GO.SYSIN DD ex.4b'
+-#define true  1
+-#define false 0
+-
+-bool flag[2];
+-bool turn;
+-
+-active [2] proctype user()
+-{     flag[_pid] = true;
+-      turn = _pid;
+-      (flag[1-_pid] == false || turn == 1-_pid);
+-crit: skip;   /* critical section */
+-      flag[_pid] = false
+-}
+//GO.SYSIN DD ex.4b
+echo ex.4c 1>&2
+sed 's/.//' >ex.4c <<'//GO.SYSIN DD ex.4c'
+-byte in;
+-byte x, y, z;
+-active [2] proctype user()    /* file ex.4c */
+-{     byte me = _pid+1;                       /* me is 1 or 2 */
+-L1:   x = me;
+-L2:   if
+-      :: (y != 0 && y != me) -> goto L1       /* try again */
+-      :: (y == 0 || y == me)
+-      fi;
+-L3:   z = me;
+-L4:   if
+-      :: (x != me)  -> goto L1                /* try again */
+-      :: (x == me)
+-      fi;
+-L5:   y = me;
+-L6:   if
+-      :: (z != me) -> goto L1                 /* try again */
+-      :: (z == me)
+-      fi;
+-L7:                                           /* success */
+-      in = in+1;
+-      assert(in == 1);
+-      in = in - 1;
+-      goto L1
+-}
+//GO.SYSIN DD ex.4c
+echo ex.5a 1>&2
+sed 's/.//' >ex.5a <<'//GO.SYSIN DD ex.5a'
+-#define Place byte    /* assume < 256 tokens per place */
+-
+-Place p1, p2, p3;
+-Place p4, p5, p6;
+-#define inp1(x)               (x>0) -> x=x-1
+-#define inp2(x,y)     (x>0&&y>0) -> x = x-1; y=y-1
+-#define out1(x)               x=x+1
+-#define out2(x,y)     x=x+1; y=y+1
+-init
+-{     p1 = 1; p4 = 1; /* initial marking */
+-      do
+-/*t1*/        :: atomic { inp1(p1)    -> out1(p2) }
+-/*t2*/        :: atomic { inp2(p2,p4) -> out1(p3) }
+-/*t3*/        :: atomic { inp1(p3)    -> out2(p1,p4) }
+-/*t4*/        :: atomic { inp1(p4)    -> out1(p5) }
+-/*t5*/        :: atomic { inp2(p1,p5) -> out1(p6) }
+-/*t6*/        :: atomic { inp1(p6)    -> out2(p4,p1) }
+-      od
+-}
+//GO.SYSIN DD ex.5a
+echo ex.5b 1>&2
+sed 's/.//' >ex.5b <<'//GO.SYSIN DD ex.5b'
+-#define Place byte    /* assume < 256 tokens per place */
+-
+-Place P1, P2, P4, P5, RC, CC, RD, CD;
+-Place p1, p2, p4, p5, rc, cc, rd, cd;
+-
+-#define inp1(x)               (x>0) -> x=x-1
+-#define inp2(x,y)     (x>0&&y>0) -> x = x-1; y=y-1
+-#define out1(x)               x=x+1
+-#define out2(x,y)     x=x+1; y=y+1
+-
+-init                  /* file ex.5b */
+-{     P1 = 1; p1 = 1; /* initial marking */
+-      do
+-      :: atomic { inp1(P1)    -> out2(rc,P2)  }       /* DC */
+-      :: atomic { inp2(P2,CC) -> out1(P4)     }       /* CA */
+-      :: atomic { inp1(P4)    -> out2(P5,rd)  }       /* DD */
+-      :: atomic { inp2(P5,CD) -> out1(P1)     }       /* FD */
+-      :: atomic { inp2(P1,RC) -> out2(P4,cc)  }       /* AC */
+-      :: atomic { inp2(P4,RD) -> out2(P1,cd)  }       /* AD */
+-      :: atomic { inp2(P5,RD) -> out1(P1)     }       /* DA */
+-
+-      :: atomic { inp1(p1)    -> out2(RC,p2)  }       /* dc */
+-      :: atomic { inp2(p2,cc) -> out1(p4)     }       /* ca */
+-      :: atomic { inp1(p4)    -> out2(p5,RD)  }       /* dd */
+-      :: atomic { inp2(p5,cd) -> out1(p1)     }       /* fd */
+-      :: atomic { inp2(p1,rc) -> out2(p4,CC)  }       /* ac */
+-      :: atomic { inp2(p4,rd) -> out2(p1,CD)  }       /* ad */
+-      :: atomic { inp2(p5,rd) -> out1(p1)     }       /* da */
+-      od
+-}
+//GO.SYSIN DD ex.5b
+echo ex.6 1>&2
+sed 's/.//' >ex.6 <<'//GO.SYSIN DD ex.6'
+-#if 0
+-      Cambridge Ring Protocol [Needham'82]
+-      basic protocol - no LTL properties
+-#endif
+-
+-#define LOSS  1
+-#define RELAXED       1
+-
+-#if RELAXED==1
+-#define stimeout      empty(sender)
+-#define rtimeout      empty(recv)
+-#else
+-#define stimeout      timeout
+-#define rtimeout      timeout
+-#endif
+-
+-#define QSZ   6       /* length of message queues */
+-
+-      mtype = {
+-              RDY, NOTRDY, DATA, NODATA, RESET
+-      };
+-      chan sender     = [QSZ] of { mtype, byte };
+-      chan recv       = [QSZ] of { mtype, byte };
+-
+-active proctype Sender()
+-{     short n = -1; byte t,m;
+-
+-      xr sender;
+-      xs recv;
+-
+-I:            /* Idle State */
+-              do
+-#if LOSS==1
+-              :: sender?_,_ -> progress2: skip
+-#endif
+-              :: sender?RESET,0 ->
+-ackreset:             recv!RESET,0;   /* stay in idle */
+-                      n = -1;
+-                      goto I
+-
+-              /* E-rep: protocol error */
+-
+-              :: sender?RDY,m ->              /* E-exp */
+-                      assert(m == (n+1)%4);
+-advance:              n = (n+1)%4;
+-                      if
+-/* buffer */          :: atomic {
+-                              printf("MSC: NEW\n");
+-                              recv!DATA,n;
+-                              goto E
+-                         }
+-/* no buffer */               :: recv!NODATA,n;
+-                              goto N
+-                      fi
+-
+-              :: sender?NOTRDY,m ->   /* N-exp */
+-expected:             assert(m == (n+1)%4);
+-                      goto I
+-
+-              /* Timeout */
+-              /* ignored (p.154, in [Needham'82]) */
+-
+-              :: goto reset
+-
+-              od;
+-
+-E:            /* Essential element sent, ack expected */
+-              do
+-#if LOSS==1
+-              :: sender?_,_ -> progress0: skip
+-#endif
+-              :: sender?RESET,0 ->
+-                      goto ackreset
+-
+-              :: sender?RDY,m ->
+-                      if
+-                      :: (m == n) ->          /* E-rep */
+-                              goto retrans
+-                      :: (m == (n+1)%4) ->    /* E-exp */
+-                              goto advance
+-                      fi
+-
+-              :: sender?NOTRDY,m ->   /* N-exp */
+-                      goto expected
+-
+-              /* Timeout */
+-              :: stimeout ->
+-                      printf("MSC: STO\n");
+-retrans:              recv!DATA,n     /* retransmit */
+-
+-              :: goto reset
+-
+-              od;
+-
+-
+-N:            /* Non-essential element sent */
+-              do
+-#if LOSS==1
+-              :: sender?_,_ -> progress1: skip
+-#endif
+-              :: sender?RESET,0 ->
+-                      goto ackreset
+-
+-              :: sender?RDY,m ->              /* E-rep */
+-                      assert(m == n)          /* E-exp: protocol error */
+-                      -> recv!NODATA,n        /* retransmit and stay in N */
+-
+-              :: recv!DATA,n;         /* buffer ready event */
+-                      goto E
+-
+-              :: goto reset
+-
+-              /* Timeout */
+-              /* ignored (p.154, in [Needham'82]) */
+-              od;
+-
+-reset:                recv!RESET,0;
+-              do
+-#if LOSS==1
+-              :: sender?_,_ -> progress3: skip
+-#endif
+-              :: sender?t,m ->
+-                      if
+-                      :: t == RESET -> n = -1; goto I
+-                      :: else /* ignored, p. 152 */
+-                      fi
+-              :: timeout ->   /* a real timeout */
+-                      goto reset
+-              od
+-}
+-
+-active proctype Receiver()
+-{     byte t, n, m, Nexp;
+-
+-      xr recv;
+-      xs sender;
+-
+-I:            /* Idle State */
+-              do
+-#if LOSS==1
+-              :: recv?_,_ -> progress2: skip
+-#endif
+-              :: recv?RESET,0 ->
+-ackreset:             sender!RESET,0;         /* stay in idle */
+-                      n = 0; Nexp = 0;
+-                      goto I
+-
+-              :: atomic { recv?DATA(m) ->     /* E-exp */
+-                      assert(m == n);
+-advance:              printf("MSC: EXP\n");
+-                      n = (n+1)%4;
+-                      assert(m == Nexp);
+-                      Nexp = (m+1)%4;
+-                      if
+-                      :: sender!RDY,n; goto E
+-                      :: sender!NOTRDY,n; goto N
+-                      fi
+-                 }
+-
+-              :: recv?NODATA(m) ->            /* N-exp */
+-                      assert(m == n)
+-
+-              /* Timeout: ignored */
+-
+-      /* only receiver can initiate transfer; p. 156 */
+-      :: empty(recv) -> sender!RDY,n; goto E
+-
+-              :: goto reset
+-              od;
+-
+-E:
+-              do
+-#if LOSS==1
+-              :: recv?_,_ -> progress1: skip
+-#endif
+-              :: recv?RESET,0 ->
+-                      goto ackreset
+-
+-              :: atomic { recv?DATA(m) ->
+-                      if
+-                      :: ((m+1)%4 == n) ->            /* E-rep */
+-                              printf("MSC: REP\n");
+-                              goto retrans
+-                      :: (m == n) ->                  /* E-exp */
+-                              goto advance
+-                      fi
+-                 }
+-
+-              :: recv?NODATA(m) ->            /* N-exp  */
+-                      assert(m == n);
+-                      goto I
+-
+-              :: rtimeout ->
+-                      printf("MSC: RTO\n");
+-retrans:              sender!RDY,n;
+-                      goto E
+-
+-              :: goto reset
+-
+-              od;
+-
+-N:
+-              do
+-#if LOSS==1
+-              :: recv?_,_ -> progress0: skip
+-#endif
+-              :: recv?RESET,0 ->
+-                      goto ackreset
+-
+-              :: recv?DATA(m) ->              /* E-rep */
+-                      assert((m+1)%4 == n);   /* E-exp and N-exp: protocol error */
+-                      printf("MSC: REP\n");
+-                      sender!NOTRDY,n /* retransmit and stay in N */
+-
+-              :: sender!RDY,n ->              /* buffer ready event */
+-                      goto E
+-
+-              /* Timeout: ignored */
+-
+-              :: goto reset
+-
+-              od;
+-
+-progress:
+-reset:                sender!RESET,0;
+-              do
+-#if LOSS==1
+-              :: recv?_,_ -> progress3: skip
+-#endif
+-              :: recv?t,m ->
+-                      if
+-                      :: t == RESET -> n = 0; Nexp = 0; goto I
+-                      :: else /* ignored, p. 152 */
+-                      fi
+-              :: timeout ->   /* a real timeout */
+-                      goto reset
+-              od
+-}
+//GO.SYSIN DD ex.6
+echo ex.7 1>&2
+sed 's/.//' >ex.7 <<'//GO.SYSIN DD ex.7'
+-mtype = { Wakeme, Running };
+-
+-bit   lk,     sleep_q;
+-bit   r_lock, r_want;
+-mtype State = Running;
+-
+-active proctype client()
+-{
+-sleep:                                        /* sleep routine */
+-      atomic { (lk == 0) -> lk = 1 }; /* spinlock(&lk) */
+-      do                              /* while r->lock */
+-      :: (r_lock == 1) ->             /* r->lock == 1 */
+-              r_want = 1;
+-              State = Wakeme;
+-              lk = 0;                 /* freelock(&lk) */
+-              (State == Running);     /* wait for wakeup */
+-      :: else ->                      /* r->lock == 0 */
+-              break
+-      od;
+-progress:
+-      assert(r_lock == 0);            /* should still be true */
+-      r_lock = 1;                     /* consumed resource */
+-      lk = 0;                         /* freelock(&lk) */
+-      goto sleep
+-}
+-
+-active proctype server()              /* interrupt routine */
+-{
+-wakeup:                                       /* wakeup routine */
+-      r_lock = 0;                     /* r->lock = 0 */
+-      (lk == 0);                      /* waitlock(&lk) */
+-      if
+-      :: r_want ->                    /* someone is sleeping */
+-              atomic {                /* spinlock on sleep queue */
+-                      (sleep_q == 0) -> sleep_q = 1
+-              };
+-              r_want = 0;
+-#ifdef PROPOSED_FIX
+-              (lk == 0);              /* waitlock(&lk) */
+-#endif
+-              if
+-              :: (State == Wakeme) ->
+-                      State = Running;
+-              :: else ->
+-              fi;
+-              sleep_q = 0
+-      :: else ->
+-      fi;
+-      goto wakeup
+-}
+//GO.SYSIN DD ex.7
+echo ex.8 1>&2
+sed 's/.//' >ex.8 <<'//GO.SYSIN DD ex.8'
+-/* Dolev, Klawe & Rodeh for leader election in unidirectional ring
+- * `An O(n log n) unidirectional distributed algorithm for extrema
+- * finding in a circle,'  J. of Algs, Vol 3. (1982), pp. 245-260
+- */
+-
+-#define elected               (nr_leaders >  0)
+-#define noLeader      (nr_leaders == 0)
+-#define oneLeader     (nr_leaders == 1)
+-
+-/* properties:
+- *    ![] noLeader
+- *    <>  elected
+- *    <>[]oneLeader
+- *    [] (noLeader U oneLeader)
+- */
+-
+-#define N     7       /* nr of processes (use 5 for demos) */
+-#define I     3       /* node given the smallest number    */
+-#define L     14      /* size of buffer  (>= 2*N) */
+-
+-mtype = { one, two, winner };
+-chan q[N] = [L] of { mtype, byte};
+-
+-byte nr_leaders = 0;
+-
+-proctype node (chan in, out; byte mynumber)
+-{     bit Active = 1, know_winner = 0;
+-      byte nr, maximum = mynumber, neighbourR;
+-
+-      xr in;
+-      xs out;
+-
+-      printf("MSC: %d\n", mynumber);
+-      out!one(mynumber);
+-end:  do
+-      :: in?one(nr) ->
+-              if
+-              :: Active -> 
+-                      if
+-                      :: nr != maximum ->
+-                              out!two(nr);
+-                              neighbourR = nr
+-                      :: else ->
+-                              /* Raynal p.39:  max is greatest number */
+-                              assert(nr == N);
+-                              know_winner = 1;
+-                              out!winner,nr;
+-                      fi
+-              :: else ->
+-                      out!one(nr)
+-              fi
+-
+-      :: in?two(nr) ->
+-              if
+-              :: Active -> 
+-                      if
+-                      :: neighbourR > nr && neighbourR > maximum ->
+-                              maximum = neighbourR;
+-                              out!one(neighbourR)
+-                      :: else ->
+-                              Active = 0
+-                      fi
+-              :: else ->
+-                      out!two(nr)
+-              fi
+-      :: in?winner,nr ->
+-              if
+-              :: nr != mynumber ->
+-                      printf("MSC: LOST\n");
+-              :: else ->
+-                      printf("MSC: LEADER\n");
+-                      nr_leaders++;
+-                      assert(nr_leaders == 1)
+-              fi;
+-              if
+-              :: know_winner
+-              :: else -> out!winner,nr
+-              fi;
+-              break
+-      od
+-}
+-
+-init {
+-      byte proc;
+-      atomic {
+-              proc = 1;
+-              do
+-              :: proc <= N ->
+-                      run node (q[proc-1], q[proc%N], (N+I-proc)%N+1);
+-                      proc++
+-              :: proc > N ->
+-                      break
+-              od
+-      }
+-}
+-
+-#if 0
+-/* !(<>[]oneLeader) */
+-
+-never {
+-T0:
+-        if
+-        :: skip -> goto T0
+-        :: !oneLeader -> goto accept
+-        fi;
+-accept:
+-        if
+-        :: skip -> goto T0
+-        fi
+-}
+-#endif
+//GO.SYSIN DD ex.8
+echo ex.9 1>&2
+sed 's/.//' >ex.9 <<'//GO.SYSIN DD ex.9'
+-#define MaxSeq        3
+-#define MaxSeq_plus_1 4
+-#define inc(x)        x = (x + 1) % (MaxSeq_plus_1)
+-
+-chan q[2] = [MaxSeq] of { byte, byte };
+-
+-active [2] proctype p5()
+-{     byte    NextFrame, AckExp, FrameExp,
+-              r, s, nbuf, i;
+-      chan in, out;
+-
+-      in = q[_pid];
+-      out = q[1-_pid];
+-
+-      xr in;
+-      xs out;
+-
+-      do
+-      :: nbuf < MaxSeq ->
+-              nbuf++;
+-              out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq_plus_1);
+-              inc(NextFrame)
+-      :: in?r,s ->
+-              if
+-              :: r == FrameExp ->
+-                      inc(FrameExp)
+-              :: else
+-              fi;
+-              do
+-              :: ((AckExp <= s) && (s <  NextFrame))
+-              || ((AckExp <= s) && (NextFrame <  AckExp))
+-              || ((s <  NextFrame) && (NextFrame <  AckExp)) ->
+-                      nbuf--;
+-                      inc(AckExp)
+-              :: else ->
+-                      break
+-              od
+-      :: timeout ->
+-              NextFrame = AckExp;
+-              i = 1;
+-              do
+-              :: i <= nbuf ->
+-                      out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq_plus_1);
+-                      inc(NextFrame);
+-                      i++
+-              :: else ->
+-                      break
+-              od
+-      od
+-}
+//GO.SYSIN DD ex.9
+echo ex.9b 1>&2
+sed 's/.//' >ex.9b <<'//GO.SYSIN DD ex.9b'
+-#define MaxSeq        3
+-#define MaxSeq_plus_1 4
+-#define inc(x)        x = (x + 1) % (MaxSeq + 1)
+-
+-chan q[2] = [MaxSeq] of { byte, byte };
+-
+-active [2] proctype p5()
+-{     byte    NextFrame, AckExp, FrameExp,
+-              r, s, nbuf, i;
+-      chan in, out;
+-
+-      d_step {
+-              in = q[_pid];
+-              out = q[1-_pid]
+-      };
+-      xr in;
+-      xs out;
+-
+-      do
+-      :: atomic { nbuf < MaxSeq ->
+-              nbuf++;
+-              out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
+-              printf("MSC: nbuf: %d\n", nbuf);
+-              inc(NextFrame)
+-      }
+-      :: atomic { in?r,s ->
+-              if
+-              :: r == FrameExp ->
+-                      printf("MSC: accept %d\n", r);
+-                      inc(FrameExp)
+-              :: else
+-                      -> printf("MSC: reject\n")
+-              fi
+-      };
+-      d_step {
+-              do
+-              :: ((AckExp <= s) && (s <  NextFrame))
+-              || ((AckExp <= s) && (NextFrame <  AckExp))
+-              || ((s <  NextFrame) && (NextFrame <  AckExp)) ->
+-                      nbuf--;
+-                      printf("MSC: nbuf: %d\n", nbuf);
+-                      inc(AckExp)
+-              :: else ->
+-                      printf("MSC: %d %d %d\n", AckExp, s, NextFrame);
+-                      break
+-              od; skip
+-      }
+-      :: timeout ->
+-      d_step {
+-              NextFrame = AckExp;
+-              printf("MSC: timeout\n");
+-              i = 1;
+-              do
+-              :: i <= nbuf ->
+-                      out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
+-                      inc(NextFrame);
+-                      i++
+-              :: else ->
+-                      break
+-              od; i = 0
+-      }
+-      od
+-}
+//GO.SYSIN DD ex.9b
+echo ex.9c 1>&2
+sed 's/.//' >ex.9c <<'//GO.SYSIN DD ex.9c'
+-#define MaxSeq        3
+-#define MaxSeq_plus_1 4
+-#define inc(x)        x = (x + 1) % (MaxSeq + 1)
+-
+-#define CHECKIT
+-
+-#ifdef CHECKIT
+-      mtype = { red, white, blue };   /* Wolper's test */
+-      chan source = [0] of { mtype };
+-      chan q[2] = [MaxSeq] of { mtype, byte, byte };
+-      mtype rcvd = white;
+-      mtype sent = white;
+-#else
+-      chan q[2] = [MaxSeq] of { byte, byte };
+-#endif
+-
+-active [2] proctype p5()
+-{     byte    NextFrame, AckExp, FrameExp,
+-              r, s, nbuf, i;
+-      chan in, out;
+-#ifdef CHECKIT
+-      mtype   ball;
+-      byte frames[MaxSeq_plus_1];
+-#endif
+-
+-      d_step {
+-              in = q[_pid];
+-              out = q[1-_pid]
+-      };
+-
+-      xr in;
+-      xs out;
+-
+-      do
+-      :: atomic {
+-              nbuf < MaxSeq ->
+-              nbuf++;
+-#ifdef CHECKIT
+-              if
+-              :: _pid%2 -> source?ball
+-              :: else
+-              fi;
+-              frames[NextFrame] = ball;
+-              out!ball, NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
+-              if
+-              :: _pid%2 -> sent = ball;
+-              :: else
+-              fi;
+-#else
+-              out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
+-#endif
+-#ifdef VERBOSE
+-              printf("MSC: nbuf: %d\n", nbuf);
+-#endif
+-              inc(NextFrame)
+-      }
+-#ifdef CHECKIT
+-      :: atomic { in?ball,r,s ->
+-#else
+-      :: atomic { in?r,s ->
+-#endif
+-              if
+-              :: r == FrameExp ->
+-#ifdef VERBOSE
+-                      printf("MSC: accept %d\n", r);
+-#endif
+-#ifdef CHECKIT
+-                      if
+-                      :: _pid%2
+-                      :: else -> rcvd = ball
+-                      fi;
+-#endif
+-                      inc(FrameExp)
+-              :: else
+-#ifdef VERBOSE
+-                      -> printf("MSC: reject\n")
+-#endif
+-              fi
+-      };
+-      d_step {
+-              do
+-              :: ((AckExp <= s) && (s <  NextFrame))
+-              || ((AckExp <= s) && (NextFrame <  AckExp))
+-              || ((s <  NextFrame) && (NextFrame <  AckExp)) ->
+-                      nbuf--;
+-#ifdef VERBOSE
+-                      printf("MSC: nbuf: %d\n", nbuf);
+-#endif
+-                      inc(AckExp)
+-              :: else ->
+-#ifdef VERBOSE
+-                      printf("MSC: %d %d %d\n", AckExp, s, NextFrame);
+-#endif
+-                      break
+-              od;
+-              skip
+-      }
+-      :: timeout ->
+-      d_step {
+-              NextFrame = AckExp;
+-#ifdef VERBOSE
+-              printf("MSC: timeout\n");
+-#endif
+-              i = 1;
+-              do
+-              :: i <= nbuf ->
+-#ifdef CHECKIT
+-                      if
+-                      :: _pid%2 -> ball = frames[NextFrame]
+-                      :: else
+-                      fi;             
+-                      out!ball, NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
+-#else
+-                      out!NextFrame , (FrameExp + MaxSeq) % (MaxSeq + 1);
+-#endif
+-                      inc(NextFrame);
+-                      i++
+-              :: else ->
+-                      break
+-              od;
+-              i = 0
+-      }
+-      od
+-}
+-#ifdef CHECKIT
+-active proctype Source()
+-{
+-      do
+-      :: source!white
+-      :: source!red -> break
+-      od;
+-      do
+-      :: source!white
+-      :: source!blue -> break
+-      od;
+-end:  do
+-      :: source!white
+-      od
+-}
+-
+-#define sw    (sent == white)
+-#define sr    (sent == red)
+-#define sb    (sent == blue)
+-
+-#define rw    (rcvd == white)
+-#define rr    (rcvd == red)
+-#define rb    (rcvd == blue)
+-
+-#define LTL   3
+-#if LTL==1
+-
+-never {               /* ![](sr -> <> rr) */
+-              /* the never claim is generated by
+-                      spin -f "![](sr -> <> rr)"
+-                 and then edited a little for readability
+-                 the same is true for all others below
+-               */
+-        do
+-        :: 1
+-        :: !rr && sr -> goto accept
+-        od;
+-accept:
+-        if
+-        :: !rr -> goto accept
+-        fi
+-}
+-
+-#endif
+-#if LTL==2
+-
+-never {               /* !rr U rb */
+-      do
+-        :: !rr
+-        :: rb -> break        /* move to implicit 2nd state */
+-        od
+-}
+-
+-#endif
+-#if LTL==3
+-
+-never {               /* (![](sr -> <> rr)) || (!rr U rb) */
+-
+-        if
+-        :: 1 -> goto T0_S5
+-        :: !rr && sr -> goto accept_S8
+-        :: !rr -> goto T0_S2
+-        :: rb -> goto accept_all
+-        fi;
+-accept_S8:
+-        if
+-        :: !rr -> goto T0_S8
+-        fi;
+-T0_S2:
+-        if
+-        :: !rr -> goto T0_S2
+-        :: rb -> goto accept_all
+-        fi;
+-T0_S8:
+-        if
+-        :: !rr -> goto accept_S8
+-        fi;
+-T0_S5:
+-        if
+-        :: 1 -> goto T0_S5
+-        :: !rr && sr -> goto accept_S8
+-        fi;
+-accept_all:
+-        skip
+-}
+-#endif
+-
+-#endif
+//GO.SYSIN DD ex.9c
diff --git a/trunk/verif/Spin/Test/hello b/trunk/verif/Spin/Test/hello
new file mode 100755 (executable)
index 0000000..cf80a12
--- /dev/null
@@ -0,0 +1,3 @@
+init {
+       printf("passed first test!\n")
+}
diff --git a/trunk/verif/Spin/Test/leader b/trunk/verif/Spin/Test/leader
new file mode 100755 (executable)
index 0000000..fa7ffc3
--- /dev/null
@@ -0,0 +1,85 @@
+/* Dolev, Klawe & Rodeh for leader election in unidirectional ring
+ * `An O(n log n) unidirectional distributed algorithm for extrema
+ * finding in a circle,'  J. of Algs, Vol 3. (1982), pp. 245-260
+ */
+
+#define N      5       /* nr of processes (use 5 for demos) */
+#define I      3       /* node given the smallest number    */
+#define L      10      /* size of buffer  (>= 2*N) */
+
+mtype = { one, two, winner };
+chan q[N] = [L] of { mtype, byte};
+
+byte nr_leaders = 0;
+
+proctype node (chan in, out; byte mynumber)
+{      bit Active = 1, know_winner = 0;
+       byte nr, maximum = mynumber, neighbourR;
+
+       xr in;
+       xs out;
+
+       printf("MSC: %d\n", mynumber);
+       out!one(mynumber);
+end:   do
+       :: in?one(nr) ->
+               if
+               :: Active -> 
+                       if
+                       :: nr != maximum ->
+                               out!two(nr);
+                               neighbourR = nr
+                       :: else ->
+                               /* Raynal p.39:  max is greatest number */
+                               assert(nr == N);
+                               know_winner = 1;
+                               out!winner,nr;
+                       fi
+               :: else ->
+                       out!one(nr)
+               fi
+
+       :: in?two(nr) ->
+               if
+               :: Active -> 
+                       if
+                       :: neighbourR > nr && neighbourR > maximum ->
+                               maximum = neighbourR;
+                               out!one(neighbourR)
+                       :: else ->
+                               Active = 0
+                       fi
+               :: else ->
+                       out!two(nr)
+               fi
+       :: in?winner,nr ->
+               if
+               :: nr != mynumber ->
+                       printf("MSC: LOST\n");
+               :: else ->
+                       printf("MSC: LEADER\n");
+                       nr_leaders++;
+                       assert(nr_leaders == 1)
+               fi;
+               if
+               :: know_winner
+               :: else -> out!winner,nr
+               fi;
+               break
+       od
+}
+
+init {
+       byte proc;
+       atomic {
+               proc = 1;
+               do
+               :: proc <= N ->
+                       run node (q[proc-1], q[proc%N], (N+I-proc)%N+1);
+                       proc++
+               :: proc > N ->
+                       break
+               od
+       }
+}
+
diff --git a/trunk/verif/Spin/Test/leader.ltl b/trunk/verif/Spin/Test/leader.ltl
new file mode 100755 (executable)
index 0000000..776c367
--- /dev/null
@@ -0,0 +1,70 @@
+#define elected                (nr_leaders >  0)
+#define noLeader       (nr_leaders == 0)
+#define oneLeader      (nr_leaders == 1)
+
+       /*
+        * Formula As Typed: <>[]oneLeader
+        * The Never Claim Below Corresponds
+        * To The Negated Formula !(<>[]oneLeader)
+        * (formalizing violations of the original)
+        */
+
+never {    /* !(<>[]oneLeader) */
+T0_init:
+       if
+       :: (1) -> goto T0_init
+       :: (! ((oneLeader))) -> goto accept_S5
+       fi;
+accept_S5:
+       if
+       :: (1) -> goto T0_init
+       fi;
+accept_all:
+       skip
+}
+
+#ifdef NOTES
+Some other properties:
+       ![] noLeader
+       <>  elected
+       [] (noLeader U oneLeader)
+
+
+
+
+
+
+#endif
+#ifdef RESULT
+warning: for p.o. reduction to be valid the never claim must be stutter-closed
+(never claims generated from LTL formulae are stutter-closed)
+(Spin Version 3.1.2 -- 14 March 1998)
+       + Partial Order Reduction
+
+Full statespace search for:
+       never-claim             +
+       assertion violations    + (if within scope of claim)
+       acceptance   cycles     + (fairness disabled)
+       invalid endstates       - (disabled by never-claim)
+
+State-vector 200 byte, depth reached 233, errors: 0
+     202 states, stored (402 visited)
+     281 states, matched
+     683 transitions (= visited+matched)
+      36 atomic steps
+hash conflicts: 0 (resolved)
+(max size 2^19 states)
+
+2.542  memory usage (Mbyte)
+
+unreached in proctype node
+       line 105, state 28, "out!two,nr"
+       (1 of 49 states)
+unreached in proctype :init:
+       (0 of 11 states)
+
+real 0.13
+user 0.04
+sys  0.09
+
+#endif
diff --git a/trunk/verif/Spin/Test/leader2 b/trunk/verif/Spin/Test/leader2
new file mode 100755 (executable)
index 0000000..40f2ec3
--- /dev/null
@@ -0,0 +1,130 @@
+/* Dolev, Klawe & Rodeh for leader election in unidirectional ring
+ * `An O(n log n) unidirectional distributed algorithm for extrema
+ * finding in a circle,'  J. of Algs, Vol 3. (1982), pp. 245-260
+
+ * Randomized initialization added -- Feb 17, 1997
+ */
+
+#define elected                (nr_leaders >  0)
+#define noLeader       (nr_leaders == 0)
+#define oneLeader      (nr_leaders == 1)
+
+/* sample properties:
+ *     ![] noLeader
+ *     <>  elected
+ *     <>[]oneLeader
+ *     [] (noLeader U oneLeader)
+ */
+
+byte nr_leaders = 0;
+
+#define N      5       /* number of processes in the ring */
+#define L      10      /* 2xN */
+byte I;
+
+mtype = { one, two, winner };
+chan q[N] = [L] of { mtype, byte};
+
+proctype node (chan in, out; byte mynumber)
+{      bit Active = 1, know_winner = 0;
+       byte nr, maximum = mynumber, neighbourR;
+
+       xr in;
+       xs out;
+
+       printf("MSC: %d\n", mynumber);
+       out!one(mynumber);
+end:   do
+       :: in?one(nr) ->
+               if
+               :: Active -> 
+                       if
+                       :: nr != maximum ->
+                               out!two(nr);
+                               neighbourR = nr
+                       :: else ->
+                               know_winner = 1;
+                               out!winner,nr;
+                       fi
+               :: else ->
+                       out!one(nr)
+               fi
+
+       :: in?two(nr) ->
+               if
+               :: Active -> 
+                       if
+                       :: neighbourR > nr && neighbourR > maximum ->
+                               maximum = neighbourR;
+                               out!one(neighbourR)
+                       :: else ->
+                               Active = 0
+                       fi
+               :: else ->
+                       out!two(nr)
+               fi
+       :: in?winner,nr ->
+               if
+               :: nr != mynumber ->
+                       printf("MSC: LOST\n");
+               :: else ->
+                       printf("MSC: LEADER\n");
+                       nr_leaders++;
+                       assert(nr_leaders == 1)
+               fi;
+               if
+               :: know_winner
+               :: else -> out!winner,nr
+               fi;
+               break
+       od
+}
+
+init {
+       byte proc;
+       byte Ini[6];    /* N<=6 randomize the process numbers */
+       atomic {
+
+               I = 1;  /* pick a number to be assigned 1..N */
+               do
+               :: I <= N ->
+                       if      /* non-deterministic choice */
+                       :: Ini[0] == 0 && N >= 1 -> Ini[0] = I
+                       :: Ini[1] == 0 && N >= 2 -> Ini[1] = I
+                       :: Ini[2] == 0 && N >= 3 -> Ini[2] = I
+                       :: Ini[3] == 0 && N >= 4 -> Ini[3] = I
+                       :: Ini[4] == 0 && N >= 5 -> Ini[4] = I
+                       :: Ini[5] == 0 && N >= 6 -> Ini[5] = I  /* works for up to N=6 */
+                       fi;
+                       I++
+               :: I > N ->     /* assigned all numbers 1..N */
+                       break
+               od;
+
+               proc = 1;
+               do
+               :: proc <= N ->
+                       run node (q[proc-1], q[proc%N], Ini[proc-1]);
+                       proc++
+               :: proc > N ->
+                       break
+               od
+       }
+}
+
+#if 0
+
+/* !(<>[]oneLeader) -- a sample LTL property */
+
+never {
+T0:
+        if
+        :: skip -> goto T0
+        :: !oneLeader -> goto accept
+        fi;
+accept:
+        if
+        :: skip -> goto T0
+        fi
+}
+#endif
diff --git a/trunk/verif/Spin/Test/leader_trace b/trunk/verif/Spin/Test/leader_trace
new file mode 100755 (executable)
index 0000000..a81f7e9
--- /dev/null
@@ -0,0 +1,96 @@
+/* Dolev, Klawe & Rodeh for leader election in unidirectional ring
+ * `An O(n log n) unidirectional distributed algorithm for extrema
+ * finding in a circle,'  J. of Algs, Vol 3. (1982), pp. 245-260
+ */
+
+#define N      5       /* nr of processes (use 5 for demos) */
+#define I      3       /* node given the smallest number    */
+#define L      10      /* size of buffer  (>= 2*N) */
+
+mtype = { one, two, winner };
+chan q[N] = [L] of { mtype, byte};
+
+byte nr_leaders = 0;
+
+notrace {
+       do
+       :: q[0]?one,_
+       :: q[0]?two,_ -> break
+       od;
+       do
+       :: q[0]?two,_
+       :: q[0]?winner,_ -> break
+       od
+}
+
+proctype node (chan in, out; byte mynumber)
+{      bit Active = 1, know_winner = 0;
+       byte nr, maximum = mynumber, neighbourR;
+
+       xr in;
+       xs out;
+
+       printf("MSC: %d\n", mynumber);
+       out!one(mynumber);
+end:   do
+       :: in?one(nr) ->
+               if
+               :: Active -> 
+                       if
+                       :: nr != maximum ->
+                               out!two(nr);
+                               neighbourR = nr
+                       :: else ->
+                               /* Raynal p.39:  max is greatest number */
+                               assert(nr == N);
+                               know_winner = 1;
+                               out!winner,nr;
+                       fi
+               :: else ->
+                       out!one(nr)
+               fi
+
+       :: in?two(nr) ->
+               if
+               :: Active -> 
+                       if
+                       :: neighbourR > nr && neighbourR > maximum ->
+                               maximum = neighbourR;
+                               out!one(neighbourR)
+                       :: else ->
+                               Active = 0
+                       fi
+               :: else ->
+                       out!two(nr)
+               fi
+       :: in?winner,nr ->
+               if
+               :: nr != mynumber ->
+                       printf("MSC: LOST\n");
+               :: else ->
+                       printf("MSC: LEADER\n");
+                       nr_leaders++;
+                       assert(nr_leaders == 1)
+               fi;
+               if
+               :: know_winner
+               :: else -> out!winner,nr
+               fi;
+               break
+       od
+}
+
+init {
+       byte proc;
+       atomic {
+               proc = 1;
+               do
+               :: proc <= N ->
+                       run node (q[proc-1], q[proc%N], (N+I-proc)%N+1);
+                       proc++
+               :: proc > N ->
+                       break
+               od
+       }
+}
+
diff --git a/trunk/verif/Spin/Test/loops b/trunk/verif/Spin/Test/loops
new file mode 100755 (executable)
index 0000000..1ed711d
--- /dev/null
@@ -0,0 +1,12 @@
+active proctype loop()
+{      byte a, b;
+
+       do
+       :: a = (a+1)%3;
+               if
+               :: b = 2*a; skip
+               :: b = 2*a; accept: skip
+               fi;
+progress:      b--
+       od
+}
diff --git a/trunk/verif/Spin/Test/mobile1 b/trunk/verif/Spin/Test/mobile1
new file mode 100755 (executable)
index 0000000..b179f0b
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Model of cell-phone handoff strategy in a mobile network.
+ * A translation from the pi-calculus description of this
+ * model presented in:
+ * Fredrik Orava and Joachim Parrow, 'An algebraic verification
+ * of a mobile network,' Formal aspects of computing, 4:497-543 (1992).
+ * For more information on this model, email: joachim@it.kth.se
+ *
+ * See also the simplified version of this model in mobile2
+ *
+ * The ltl property definition for this version is in mobile1.ltl
+ *
+ * to perform the verification with xspin, simply use the ltl property
+ * manager, which will load the above .ltl file by default.
+ * to perform the verificaion from a Unix command line, type:
+ *     $ spin -a -N mobile1.ltl mobile1
+ *     $ cc -o pan pan.c
+ *     $ pan -a
+ */
+
+mtype = { data, ho_cmd, ho_com, ho_acc, ho_fail, ch_rel, white, red, blue };
+
+chan in  = [1] of { mtype };
+chan out = [1] of { mtype };
+
+byte a_id, p_id;       /* ids of processes refered to in the property */
+
+proctype CC(chan fa, fp, l)    /* communication controller */
+{      chan  m_old, m_new, x;
+       mtype v;
+
+       do
+       :: in?v ->
+               printf("MSC: DATA\n");
+               fa!data; fa!v
+       :: l?m_new ->
+               fa!ho_cmd; fa!m_new;
+               printf("MSC: HAND-OFF\n");
+               if
+               :: fp?ho_com ->
+                       printf("MSC: CH_REL\n");
+                       fa!ch_rel; fa?m_old;
+                       l!m_old;
+                       x = fa; fa = fp; fp = x
+               :: fa?ho_fail ->
+                       printf("MSC: FAIL\n");
+                       l!m_new
+               fi
+       od
+}
+
+proctype HC(chan l, m)                 /* handover controller */
+{
+       do
+       :: l!m; l?m
+       od
+}
+
+proctype MSC(chan fa, fp, m)           /* mobile switching center */
+{      chan l  = [0] of { chan };
+
+       atomic {
+               run HC(l, m);
+               run CC(fa, fp, l)
+       }
+}
+
+proctype BS(chan f, m; bit how)                /* base station */
+{      chan v;
+
+       if
+       :: how -> goto Active
+       :: else -> goto Passive
+       fi;
+
+Active:
+       printf("MSC: ACTIVE\n");
+       do
+       :: f?data -> f?v; m!data; m!v
+       :: f?ho_cmd ->                  /* handover command */
+progress:      f?v; m!ho_cmd; m!v;
+               if
+               :: f?ch_rel ->
+                       f!m;
+                       goto Passive
+               :: m?ho_fail ->
+                       printf("MSC: FAILURE\n");
+                       f!ho_fail
+               fi
+       od;
+
+Passive:
+       printf("MSC: PASSIVE\n");
+       m?ho_acc -> f!ho_com;
+       goto Active
+}
+
+proctype MS(chan m)                    /* mobile station */
+{      chan m_new;
+       mtype v;
+
+       do
+       :: m?data -> m?v; out!v
+       :: m?ho_cmd; m?m_new;
+               if
+               :: m_new!ho_acc; m = m_new
+               :: m!ho_fail
+               fi
+       od
+}
+
+proctype P(chan fa, fp)
+{      chan m  = [0] of { mtype };
+
+       atomic {
+               run MSC(fa, fp, m);
+               p_id = run BS(fp, m, 0) /* passive base station */
+       }
+}
+
+proctype Q(chan fa)
+{      chan m  = [0] of { mtype }; /* mixed use as mtype/chan */
+
+       atomic {
+               a_id = run BS(fa, m, 1);        /* active base station */
+               run MS(m)
+       }
+}
+
+active proctype System()
+{      chan fa = [0] of { mtype }; /* mixed use as mtype/chan */
+       chan fp = [0] of { mtype }; /* mixed use as mtype/chan */
+
+       atomic {
+               run P(fa, fp);
+               run Q(fa)
+       }
+}
+
+active proctype top()
+{
+       do
+       :: in!red; in!white; in!blue
+       od
+}
+active proctype bot()
+{
+       do      /* deadlock on loss or duplication */
+       :: out?red; out?white; out?blue
+       od
+}
diff --git a/trunk/verif/Spin/Test/mobile1.ltl b/trunk/verif/Spin/Test/mobile1.ltl
new file mode 100755 (executable)
index 0000000..ea51a48
--- /dev/null
@@ -0,0 +1,112 @@
+#define p      in?[red]
+#define q      out?[red]
+#define r              (BS[a_id]@progress || BS[p_id]@progress)
+
+       /*
+        * Formula As Typed: (![]<>(r)) -> [](<>p -> <>q)
+        * The Never Claim Below Corresponds
+        * To The Negated Formula !((![]<>(r)) -> [](<>p -> <>q))
+        * (formalizing violations of the original)
+        */
+
+never {    /* !((![]<>(r)) -> [](<>p -> <>q)) */
+T0_init:
+       if
+       :: (! ((q)) && ! ((r)) && (p)) -> goto accept_S8
+       :: (! ((q)) && ! ((r))) -> goto T0_S17
+       :: (! ((q)) && (p)) -> goto T0_S44
+       :: (! ((q))) -> goto T0_S58
+       :: (! ((r))) -> goto T0_S91
+       :: (1) -> goto T0_init
+       fi;
+accept_S8:
+       if
+       :: (! ((q)) && ! ((r))) -> goto accept_S8
+       fi;
+T0_S17:
+       if
+       :: (! ((q)) && ! ((r)) && (p)) -> goto accept_S8
+       :: (! ((q)) && ! ((r))) -> goto T0_S17
+       fi;
+T0_S44:
+       if
+       :: (! ((q)) && ! ((r))) -> goto accept_S8
+       :: (! ((q))) -> goto T0_S44
+       fi;
+T0_S58:
+       if
+       :: (! ((q)) && ! ((r)) && (p)) -> goto accept_S8
+       :: (! ((q)) && ! ((r))) -> goto T0_S17
+       :: (! ((q)) && (p)) -> goto T0_S44
+       :: (! ((q))) -> goto T0_S58
+       fi;
+T0_S91:
+       if
+       :: (! ((q)) && ! ((r)) && (p)) -> goto accept_S8
+       :: (! ((q)) && ! ((r))) -> goto T0_S17
+       :: (! ((r))) -> goto T0_S91
+       fi;
+}
+
+#ifdef NOTES
+Use Load to open a file or a template.
+
+
+#endif
+#ifdef RESULT
+warning: for p.o. reduction to be valid the never claim must be stutter-closed
+(never claims generated from LTL formulae are stutter-closed)
+(Spin Version 3.4.0 -- 7 August 2000)
+       + Partial Order Reduction
+
+Full statespace search for:
+       never-claim             +
+       assertion violations    + (if within scope of claim)
+       acceptance   cycles     + (fairness disabled)
+       invalid endstates       - (disabled by never-claim)
+
+State-vector 128 byte, depth reached 1833, errors: 0
+   44455 states, stored (48719 visited)
+  137737 states, matched
+  186456 transitions (= visited+matched)
+     241 atomic steps
+hash conflicts: 8962 (resolved)
+(max size 2^19 states)
+
+Stats on memory usage (in Megabytes):
+6.046  equivalent memory usage for states (stored*(State-vector + overhead))
+3.379  actual memory usage for states (compression: 55.89%)
+       State-vector as stored = 68 byte + 8 byte overhead
+2.097  memory used for hash-table (-w19)
+0.240  memory used for DFS stack (-m10000)
+5.819  total actual memory usage
+
+unreached in proctype CC
+       line 49, state 25, "-end-"
+       (1 of 25 states)
+unreached in proctype HC
+       line 56, state 6, "-end-"
+       (1 of 6 states)
+unreached in proctype MSC
+       (0 of 4 states)
+unreached in proctype BS
+       line 95, state 31, "-end-"
+       (1 of 31 states)
+unreached in proctype MS
+       line 108, state 14, "-end-"
+       (1 of 14 states)
+unreached in proctype P
+       (0 of 4 states)
+unreached in proctype Q
+       (0 of 4 states)
+unreached in proctype System
+       (0 of 4 states)
+unreached in proctype top
+       line 143, state 7, "-end-"
+       (1 of 7 states)
+unreached in proctype bot
+       line 149, state 7, "-end-"
+       (1 of 7 states)
+5.1u 0.1s 5r    ./pan -X -m10000 -w19 -a ...
+
+#endif
diff --git a/trunk/verif/Spin/Test/mobile2 b/trunk/verif/Spin/Test/mobile2
new file mode 100755 (executable)
index 0000000..4526b10
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Simplified model of cell-phone handoff strategy in a mobile network.
+ * A translation from the pi-calculus description of this
+ * model presented in:
+ * Fredrik Orava and Joachim Parrow, 'An algebraic verification
+ * of a mobile network,' Formal aspects of computing, 4:497-543 (1992).
+ * For more information on this model, email: joachim@it.kth.se
+ *
+ * This version exploits some Promela features to reduce the number
+ * of processes -- which looks better in simulations, and reduces
+ * complexity (by about 60%) in verification.
+ *
+ * See also the more literal version of this model in mobile1.
+ *
+ * The ltl property definition for this version is in mobile2.ltl
+ *
+ * to perform the verification with xspin, simply use the ltl property
+ * manager, which will load the above .ltl file by default.
+ * to perform the verificaion from a Unix command line, type:
+ *     $ spin -a -N mobile2.ltl mobile2
+ *     $ cc -o pan pan.c
+ *     $ pan -a
+ */
+
+mtype = { data, ho_cmd, ho_com, ho_acc, ho_fail, ch_rel, white, red, blue };
+
+chan in  = [1] of { mtype };
+chan out = [1] of { mtype };
+chan fa  = [0] of { chan };
+chan fp  = [0] of { chan };
+chan m1  = [0] of { chan };
+chan m2  = [0] of { chan };
+chan l   = [0] of { chan };
+
+byte a_id, p_id;       /* ids of processes refered to in the property */
+
+proctype CC()  /* communication controller */
+{      chan  m_old, m_new, x;
+       mtype v;
+
+       do
+       :: in?v ->
+               printf("MSC: DATA\n");
+               fa!data; fa!v
+       :: l?m_new ->
+               fa!ho_cmd; fa!m_new;
+               printf("MSC: HAND-OFF\n");
+               if
+               :: fp?ho_com ->
+                       printf("MSC: CH_REL\n");
+                       fa!ch_rel; fa?m_old;
+                       l!m_old;
+                       x = fa; fa = fp; fp = x
+               :: fa?ho_fail ->
+                       printf("MSC: FAIL\n");
+                       l!m_new
+               fi
+       od
+}
+
+proctype HC(chan m)    /* handover controller */
+{
+       do
+       :: l!m; l?m
+       od
+}
+
+proctype BS(chan f, m; bit how)        /* base station */
+{      chan v;
+
+       if
+       :: how -> goto Active
+       :: else -> goto Passive
+       fi;
+
+Active:
+       printf("MSC: ACTIVE\n");
+       do
+       :: f?data -> f?v; m!data; m!v
+       :: f?ho_cmd ->  /* handover command */
+progress:      f?v; m!ho_cmd; m!v;
+               if
+               :: f?ch_rel ->
+                       f!m;
+                       goto Passive
+               :: m?ho_fail ->
+                       printf("MSC: FAILURE\n");
+                       f!ho_fail
+               fi
+       od;
+
+Passive:
+       printf("MSC: PASSIVE\n");
+       m?ho_acc -> f!ho_com;
+       goto Active
+}
+
+proctype MS(chan m)    /* mobile station */
+{      chan m_new;
+       mtype v;
+
+       do
+       :: m?data -> m?v; out!v
+       :: m?ho_cmd; m?m_new;
+               if
+               :: m_new!ho_acc; m = m_new
+               :: m!ho_fail
+               fi
+       od
+}
+
+active proctype System()
+{
+       atomic {
+               run HC(m1);
+               run CC();
+               p_id = run BS(fp, m1, 0);       /* passive base station */
+               a_id = run BS(fa, m2, 1);       /* active base station */
+               run MS(m2)
+       }
+
+end:   do
+       :: in!red; in!white; in!blue
+       od
+}
+
+active proctype Out()
+{
+end:   do      /* deadlocks if order is disturbed */
+       :: out?red; out?white; out?blue
+       od
+}
diff --git a/trunk/verif/Spin/Test/mobile2.ltl b/trunk/verif/Spin/Test/mobile2.ltl
new file mode 100755 (executable)
index 0000000..93d7def
--- /dev/null
@@ -0,0 +1,107 @@
+#define p      in?[red]
+#define q      out?[red]
+#define r      (BS[a_id]@progress || BS[p_id]@progress)
+
+       /*
+        * Formula As Typed: (![]<>(r)) -> [](<>p -> <>q)
+        * The Never Claim Below Corresponds
+        * To The Negated Formula !((![]<>(r)) -> [](<>p -> <>q))
+        * (formalizing violations of the original)
+        */
+
+never {    /*  !((![]<>(r)) -> [](<>p -> <>q))  */
+T0_init:
+       if
+       :: (! ((q)) && ! ((r)) && (p)) -> goto accept_S8
+       :: (! ((q)) && ! ((r))) -> goto T0_S13
+       :: (! ((q)) && (p)) -> goto T0_S26
+       :: (! ((q))) -> goto T0_S32
+       :: (! ((r))) -> goto T0_S44
+       :: (1) -> goto T0_init
+       fi;
+accept_S8:
+       if
+       :: (! ((q)) && ! ((r))) -> goto T0_S8
+       fi;
+T0_S8:
+       if
+       :: (! ((q)) && ! ((r))) -> goto accept_S8
+       fi;
+T0_S13:
+       if
+       :: (! ((q)) && ! ((r)) && (p)) -> goto accept_S8
+       :: (! ((q)) && ! ((r))) -> goto T0_S13
+       fi;
+T0_S26:
+       if
+       :: (! ((q)) && ! ((r))) -> goto accept_S8
+       :: (! ((q))) -> goto T0_S26
+       fi;
+T0_S32:
+       if
+       :: (! ((q)) && ! ((r)) && (p)) -> goto accept_S8
+       :: (! ((q)) && ! ((r))) -> goto T0_S13
+       :: (! ((q)) && (p)) -> goto T0_S26
+       :: (! ((q))) -> goto T0_S32
+       fi;
+T0_S44:
+       if
+       :: (! ((q)) && ! ((r)) && (p)) -> goto accept_S8
+       :: (! ((q)) && ! ((r))) -> goto T0_S13
+       :: (! ((r))) -> goto T0_S44
+       fi;
+accept_all:
+       skip
+}
+
+#ifdef NOTES
+Use Load to open a file or a template.
+#endif
+#ifdef RESULT
+warning: for p.o. reduction to be valid the never claim must be stutter-closed
+(never claims generated from LTL formulae are stutter-closed)
+(Spin Version 3.2.4 -- 16 October 1998)
+       + Partial Order Reduction
+
+Full statespace search for:
+       never-claim             +
+       assertion violations    + (if within scope of claim)
+       acceptance   cycles     + (fairness disabled)
+       invalid endstates       - (disabled by never-claim)
+
+State-vector 96 byte, depth reached 1944, errors: 0
+   16191 states, stored (18994 visited)
+   46781 states, matched
+   65775 transitions (= visited+matched)
+      16 atomic steps
+hash conflicts: 1713 (resolved)
+(max size 2^19 states)
+
+Stats on memory usage (in Megabytes):
+1.684  equivalent memory usage for states (stored*(State-vector + overhead))
+0.998  actual memory usage for states (compression: 59.24%)
+       State-vector as stored = 54 byte + 8 byte overhead
+2.097  memory used for hash-table (-w19)
+0.240  memory used for DFS stack (-m10000)
+3.464  total actual memory usage
+
+unreached in proctype CC
+       line 28, state 25, "-end-"
+       (1 of 25 states)
+unreached in proctype HC
+       line 35, state 6, "-end-"
+       (1 of 6 states)
+unreached in proctype BS
+       line 65, state 31, "-end-"
+       (1 of 31 states)
+unreached in proctype MS
+       line 78, state 14, "-end-"
+       (1 of 14 states)
+unreached in proctype System
+       line 98, state 13, "-end-"
+       (1 of 13 states)
+unreached in proctype Out
+       line 105, state 7, "-end-"
+       (1 of 7 states)
+
+#endif
diff --git a/trunk/verif/Spin/Test/pathfinder b/trunk/verif/Spin/Test/pathfinder
new file mode 100755 (executable)
index 0000000..a264eed
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Models the Pathfinder scheduling algorithm and explains the
+ * cause of the recurring reset problem during the mission on Mars
+ *
+ * there is a high priority process, that consumes
+ * data produced by a low priority process.
+ * data consumption and production happens under
+ * the protection of a mutex lock
+ * the mutex lock conflicts with the scheduling priorities
+ * which can deadlock the system if high() starts up
+ * while low() has the lock set
+ * there are 12 reachable states in the full (non-reduced)
+ * state space -- two of which are deadlock states
+ * partial order reduction cannot be used here because of
+ * the 'provided' clause that models the process priorities
+ */
+
+mtype = { free, busy, idle, waiting, running };
+
+show mtype h_state = idle;
+show mtype l_state = idle;
+show mtype mutex = free;
+
+active proctype high() /* can run at any time */
+{
+end:   do
+       :: h_state = waiting;
+               atomic { mutex == free -> mutex = busy };
+               h_state = running;
+
+               /* critical section - consume data */
+
+               atomic { h_state = idle; mutex = free }
+       od
+}
+
+active proctype low() provided (h_state == idle) /* scheduling rule */
+{
+end:   do
+       :: l_state = waiting;
+               atomic { mutex == free -> mutex = busy};
+               l_state = running;
+
+               /* critical section - produce data */
+
+               atomic { l_state = idle; mutex = free }
+       od
+
+}
+
diff --git a/trunk/verif/Spin/Test/peterson b/trunk/verif/Spin/Test/peterson
new file mode 100755 (executable)
index 0000000..156da7e
--- /dev/null
@@ -0,0 +1,20 @@
+/* Peterson's solution to the mutual exclusion problem - 1981 */
+
+bool turn, flag[2];
+byte ncrit;
+
+active [2] proctype user()
+{
+       assert(_pid == 0 || _pid == 1);
+again:
+       flag[_pid] = 1;
+       turn = _pid;
+       (flag[1 - _pid] == 0 || turn == 1 - _pid);
+
+       ncrit++;
+       assert(ncrit == 1);     /* critical section */
+       ncrit--;
+
+       flag[_pid] = 0;
+       goto again
+}
diff --git a/trunk/verif/Spin/Test/petersonN b/trunk/verif/Spin/Test/petersonN
new file mode 100755 (executable)
index 0000000..1cccdb5
--- /dev/null
@@ -0,0 +1,45 @@
+/* Peterson's algorithm for N processes - see Lynch's book, p. 284 */
+
+#ifndef N
+       #define N       3       /* nr of processes */
+#endif
+
+byte turn[N], flag[N];
+
+byte ncrit;    /* auxiliary var to check mutual exclusion */
+
+active [N] proctype user()
+{      byte j, k;
+       /* without never claims, _pid's are: 0 .. N-1 */
+again:
+       k = 0;  /* count max N-1 rounds of competition */
+       do
+       :: k < N-1 ->
+               flag[_pid] = k;
+               turn[k] = _pid;
+
+               j = 0;          /* for all j != _pid */
+               do
+               :: j == _pid ->
+                       j++
+               :: j != _pid ->
+                       if
+                       :: j < N ->
+                               (flag[j] < k || turn[k] != _pid);
+                               j++
+                       :: j >= N  ->
+                               break
+                       fi
+               od;
+               k++
+       :: else ->      /* survived all N-1 rounds */
+               break
+       od;
+
+       ncrit++;
+       assert(ncrit == 1);     /* critical section */
+       ncrit--;
+
+       flag[_pid] = 0;
+       goto again
+}
diff --git a/trunk/verif/Spin/Test/pftp b/trunk/verif/Spin/Test/pftp
new file mode 100755 (executable)
index 0000000..cd05dce
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * PROMELA Validation Model
+ * FLOW CONTROL LAYER VALIDATION
+ */
+
+#define LOSS           1       /* message loss   */
+#define DUPS           0       /* duplicate msgs */
+#define QSZ            2       /* queue size     */
+
+mtype = {
+       red, white, blue,
+       abort, accept, ack, sync_ack, close, connect,
+       create, data, eof, open, reject, sync, transfer,
+       FATAL, NON_FATAL, COMPLETE
+       }
+
+chan ses_to_flow[2] = [QSZ] of { byte, byte };
+chan flow_to_ses[2] = [QSZ] of { byte, byte };
+chan dll_to_flow[2] = [QSZ] of { byte, byte };
+
+/*
+ * Flow Control Layer Validation Model
+ */
+
+#define true   1
+#define false  0
+
+#define M      4       /* range sequence numbers   */
+#define W      2       /* window size: M/2         */
+
+proctype fc(chan s2f, f2d, f2s, d2f)
+{      bool    busy[M];        /* outstanding messages    */
+       byte    q;              /* seq# oldest unacked msg */
+       byte    m;              /* seq# last msg received  */
+       byte    s;              /* seq# next msg to send   */
+       byte    window;         /* nr of outstanding msgs  */
+       byte    type;           /* msg type                */
+       bit     received[M];    /* receiver housekeeping   */
+       bit     x;              /* scratch variable        */
+       byte    p;              /* seq# of last msg acked  */
+       byte    I_buf[M], O_buf[M];     /* message buffers */
+
+       xr s2f;
+       xs f2d;
+       xs f2s;
+       xr d2f;
+
+       /* sender part */
+end:   do
+       :: atomic {
+          (window < W  && nempty(s2f)
+                       && nfull(f2d)) ->
+                       s2f?type,x;
+                       window = window + 1;
+                       busy[s] = true;
+                       O_buf[s] = type;
+                       f2d!type,s;
+                       if
+                       :: (type != sync) ->
+                               s = (s+1)%M
+                       :: (type == sync) ->
+                               window = 0;
+                               s = M;
+                               do
+                               :: (s > 0) ->
+                                       s = s-1;
+                                       busy[s] = false
+                               :: (s == 0) ->
+                                       break
+                               od
+                       fi
+          }
+       :: atomic {
+               (window > 0 && busy[q] == false) ->
+               window = window - 1;
+               q = (q+1)%M
+          }
+#if DUPS
+       :: atomic {
+               (nfull(f2d) && window > 0 && busy[q] == true) ->
+               f2d!O_buf[q],q
+          }
+#endif
+       :: atomic {
+               (timeout && nfull(f2d) && window > 0 && busy[q] == true) ->
+               f2d!O_buf[q],q
+          }
+       /* receiver part */
+#if LOSS
+       :: d2f?type,m /* lose any message */
+#endif
+       :: d2f?type,m ->
+               if
+               :: atomic {
+                       (type == ack) ->
+                       busy[m] = false
+                  }
+               :: atomic {
+                       (type == sync) ->
+                       m = 0;
+                       do
+                       :: (m < M) ->
+                               received[m] = 0;
+                               m = m+1
+                       :: (m == M) ->
+                               break
+                       od
+                  };   f2d!sync_ack,0
+               :: (type == sync_ack) ->
+                       f2s!sync_ack,0
+               :: (type != ack && type != sync && type != sync_ack)->
+                       if
+                       :: atomic {
+                               (received[m] == true) ->
+                                       x = ((0<p-m   && p-m<=W)
+                                       ||   (0<p-m+M && p-m+M<=W)) };
+                                       if
+                                       :: (x) -> f2d!ack,m
+                                       :: (!x) /* else skip */
+                                       fi
+                       :: atomic {
+                               (received[m] == false) ->
+                                       I_buf[m] = type;
+                                       received[m] = true;
+                                       received[(m-W+M)%M] = false
+                          }
+                       fi
+               fi
+       :: /* atomic { */
+          (received[p] == true && nfull(f2s) && nfull(f2d)) ->
+               f2s!I_buf[p],0;
+               f2d!ack,p;
+               p = (p+1)%M
+          /* } */
+       od
+}
+
+proctype upper_s(chan s2f, f2s0)
+{      byte s_state;
+       byte type, toggle;
+
+       xs s2f;
+       xr f2s0;
+
+       s2f!sync,toggle;
+       do
+       :: f2s0?sync_ack,type ->
+               if
+               :: (type != toggle)
+               :: (type == toggle) -> break
+               fi
+       :: timeout ->
+               s2f!sync,toggle
+       od;
+       toggle = 1 - toggle;
+
+end:   do
+       :: s2f!white,0
+       :: atomic {
+               (s_state == 0 && nfull(s2f)) ->
+               s2f!red,0 ->
+               s_state = 1
+          }
+       :: atomic {
+               (s_state == 1 && nfull(s2f)) ->
+               s2f!blue,0 ->
+               s_state = 2
+          }
+       od
+}
+
+proctype upper_r(chan f2s1)
+{      byte r_state;
+
+       xr f2s1;
+
+       do
+       :: f2s1?white,0
+       :: f2s1?red,0 -> break
+       :: f2s1?blue,0 -> assert(0)
+       od;
+
+       do
+       :: f2s1?white,0
+       :: f2s1?red,0 -> assert(0)
+       :: f2s1?blue,0 -> goto end
+       od;
+end:
+       do
+       :: f2s1?white,0
+       :: f2s1?red,0 -> assert(0)
+       :: f2s1?blue,0 -> assert(0)
+       od
+}
+
+init
+{
+       atomic {
+         run fc(ses_to_flow[0], dll_to_flow[1], flow_to_ses[0], dll_to_flow[0]);
+         run fc(ses_to_flow[1], dll_to_flow[0], flow_to_ses[1], dll_to_flow[1]);
+         run upper_s(ses_to_flow[0], flow_to_ses[0]);
+         run upper_r(flow_to_ses[1])
+       }
+}
diff --git a/trunk/verif/Spin/Test/priorities b/trunk/verif/Spin/Test/priorities
new file mode 100755 (executable)
index 0000000..bf7a8c4
--- /dev/null
@@ -0,0 +1,22 @@
+/* test execution priorities
+   run this as:
+       spin -p -g priorities
+   requires Spin Version 2.5 or later
+*/
+
+int a[5];
+
+proctype A()
+{
+       do
+       :: printf("%d\n", _pid); a[_pid]++
+       od
+}
+
+init {
+       atomic {
+               run A() priority 1;
+               run A() priority 2;
+               run A() priority 3;
+               run A() priority 4;
+}      }
diff --git a/trunk/verif/Spin/Test/snoopy b/trunk/verif/Spin/Test/snoopy
new file mode 100755 (executable)
index 0000000..20c0294
--- /dev/null
@@ -0,0 +1,257 @@
+/* snooping cache algorithm
+ */
+#define QSZ    2
+
+mtype = {      r, w, raw,
+               RD, WR, RX,
+               MX, MXdone,
+               req0, req1,
+               CtoB, BtoC,
+               grant, done
+       };
+
+chan tocpu0    = [QSZ] of { mtype };
+chan fromcpu0  = [QSZ] of { mtype };
+chan tobus0    = [QSZ] of { mtype };
+chan frombus0  = [QSZ] of { mtype };
+chan grant0    = [QSZ] of { mtype };
+
+chan tocpu1    = [QSZ] of { mtype };
+chan fromcpu1  = [QSZ] of { mtype };
+chan tobus1    = [QSZ] of { mtype };
+chan frombus1  = [QSZ] of { mtype };
+chan grant1    = [QSZ] of { mtype };
+
+chan claim0    = [QSZ] of { mtype };
+chan claim1    = [QSZ] of { mtype };
+chan release0  = [QSZ] of { mtype };
+chan release1  = [QSZ] of { mtype };
+
+#define W      1
+#define R      2
+#define X      3
+
+proctype cpu0()
+{
+       xs fromcpu0;
+       xr tocpu0;
+       do
+       :: fromcpu0!r   -> tocpu0?done
+       :: fromcpu0!w   -> tocpu0?done
+       :: fromcpu0!raw -> tocpu0?done
+       od
+}
+
+proctype cpu1()
+{
+       xs fromcpu1;
+       xr tocpu1;
+       do
+       :: fromcpu1!r   -> tocpu1?done
+       :: fromcpu1!w   -> tocpu1?done
+       :: fromcpu1!raw -> tocpu1?done
+       od
+}
+
+proctype cache0()
+{      byte state = X;
+       byte which;
+
+       xr frombus0;
+       xr fromcpu0;
+       xs tocpu0;
+       xs tobus0;
+       xr grant0;
+       xs claim0;
+       xs release0;
+resume:
+       do
+       :: frombus0?RD ->
+               if
+               :: (state == W) -> state = R; tobus0!CtoB
+               :: (state != W) -> tobus0!done
+               fi
+       :: frombus0?MX -> state = X; tobus0!MXdone
+       :: frombus0?RX ->
+               if
+               :: (state == W) -> state = X; tobus0!CtoB
+               :: (state == R) -> state = X; tobus0!done
+               :: (state == X) -> tobus0!done
+               fi
+
+       :: fromcpu0?r ->
+               if
+               :: (state != X) -> tocpu0!done
+               :: (state == X) -> which = RD; goto buscycle
+               fi
+       :: fromcpu0?w ->
+               if
+               :: (state == W) -> tocpu0!done
+               :: (state != W) -> which = MX; goto buscycle
+               fi
+       :: fromcpu0?raw ->
+               if
+               :: (state == W) -> tocpu0!done
+               :: (state != W) -> which = RX; goto buscycle
+               fi
+       od;
+buscycle:
+       claim0!req0;
+       do
+       :: frombus0?RD ->
+               if
+               :: (state == W) -> state = R; tobus0!CtoB
+               :: (state != W) -> tobus0!done
+               fi
+       :: frombus0?MX -> state = X; tobus0!MXdone
+       :: frombus0?RX ->
+               if
+               :: (state == W) -> state = X; tobus0!CtoB
+               :: (state == R) -> state = X; tobus0!done
+               :: (state == X) -> tobus0!done
+               fi
+       :: grant0?grant ->
+               if
+               :: (which == RD) -> state = R
+               :: (which == MX) -> state = W
+               :: (which == RX) -> state = W
+               fi;
+               tocpu0!done;
+               break
+       od;
+       release0!done;
+
+       if
+       :: (which == RD) -> tobus0!RD -> frombus0?BtoC
+       :: (which == MX) -> tobus0!MX -> frombus0?done
+       :: (which == RX) -> tobus0!RX -> frombus0?BtoC
+       fi;
+       goto resume
+}
+
+proctype cache1()
+{      byte state = X;
+       byte which;
+
+       xr frombus1;
+       xr fromcpu1;
+       xs tobus1;
+       xs tocpu1;
+       xr grant1;
+       xs claim1;
+       xs release1;
+resume:
+       do
+       :: frombus1?RD ->
+               if
+               :: (state == W) -> state = R; tobus1!CtoB
+               :: (state != W) -> tobus1!done
+               fi
+       :: frombus1?MX -> state = X; tobus1!MXdone
+       :: frombus1?RX ->
+               if
+               :: (state == W) -> state = X; tobus1!CtoB
+               :: (state == R) -> state = X; tobus1!done
+               :: (state == X) -> tobus1!done
+               fi
+
+       :: fromcpu1?r ->
+               if
+               :: (state != X) -> tocpu1!done
+               :: (state == X) -> which = RD; goto buscycle
+               fi
+       :: fromcpu1?w ->
+               if
+               :: (state == W) -> tocpu1!done
+               :: (state != W) -> which = MX; goto buscycle
+               fi
+       :: fromcpu1?raw ->
+               if
+               :: (state == W) -> tocpu1!done
+               :: (state != W) -> which = RX; goto buscycle
+               fi
+       od;
+buscycle:
+       claim1!req1;
+       do
+       :: frombus1?RD ->
+               if
+               :: (state == W) -> state = R; tobus1!CtoB
+               :: (state != W) -> tobus1!done
+               fi
+       :: frombus1?MX -> state = X; tobus1!MXdone
+       :: frombus1?RX ->
+               if
+               :: (state == W) -> state = X; tobus1!CtoB
+               :: (state == R) -> state = X; tobus1!done
+               :: (state == X) -> tobus1!done
+               fi
+       :: grant1?grant ->
+               if
+               :: (which == RD) -> state = R
+               :: (which == MX) -> state = W
+               :: (which == RX) -> state = W
+               fi;
+               tocpu1!done;
+               break
+       od;
+       release1!done;
+
+       if
+       :: (which == RD) -> tobus1!RD -> frombus1?BtoC
+       :: (which == MX) -> tobus1!MX -> frombus1?done
+       :: (which == RX) -> tobus1!RX -> frombus1?BtoC
+       fi;
+       goto resume
+}
+
+proctype busarbiter()
+{
+       xs grant0;
+       xs grant1;
+       xr claim0;
+       xr claim1;
+       xr release0;
+       xr release1;
+
+       do
+       :: claim0?req0 -> grant0!grant; release0?done
+       :: claim1?req1 -> grant1!grant; release1?done
+       od
+}
+
+proctype bus()         /* models real bus + main memory */
+{
+       xs frombus1;
+       xs frombus0;
+       xr tobus0;
+       xr tobus1;
+
+       do
+       :: tobus0?CtoB -> frombus1!BtoC
+       :: tobus1?CtoB -> frombus0!BtoC
+
+       :: tobus0?done -> /* M -> B */ frombus1!BtoC
+       :: tobus1?done -> /* M -> B */ frombus0!BtoC
+
+       :: tobus0?MXdone -> /* B -> M */ frombus1!done
+       :: tobus1?MXdone -> /* B -> M */ frombus0!done
+
+       :: tobus0?RD -> frombus1!RD
+       :: tobus1?RD -> frombus0!RD
+
+       :: tobus0?MX -> frombus1!MX
+       :: tobus1?MX -> frombus0!MX
+
+       :: tobus0?RX -> frombus1!RX
+       :: tobus1?RX -> frombus0!RX
+       od
+}
+
+init {
+       atomic {
+               run cpu0(); run cpu1();
+               run cache0(); run cache1();
+               run bus(); run busarbiter()
+       }
+}
diff --git a/trunk/verif/Spin/Test/sort b/trunk/verif/Spin/Test/sort
new file mode 100755 (executable)
index 0000000..e1f5068
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * A program to sort concurrently N "random" numbers
+ * The reduced space and time should be linear in the
+ * number of processes, and can be reduced when the length of
+ * the buffer queues is increased.
+ * In full search it should be exponential.
+ */
+
+#define N      7                       /* Number of Proc */
+#define L      10                      /* Size of buffer queues */
+#define RANDOM (seed * 3 + 14) % 100   /* Calculate "random" number */
+
+chan q[N] = [L] of {byte};
+
+proctype left(chan out)                        /* leftmost process, generates random numbers */
+{      byte counter, seed;
+
+       xs out;
+
+       counter = 0; seed = 15;
+       do
+       :: out!seed ->                  /* output value to the right */
+               counter = counter + 1;
+               if
+               :: counter == N -> break
+               :: counter != N -> skip
+               fi;
+               seed = RANDOM           /* next "random" number */
+       od
+}
+
+proctype middle(chan in, out; byte procnum)
+{      byte counter, myval, nextval;
+
+       xs out;
+       xr in;
+
+       counter = N - procnum;
+       in?myval;                               /* get first value from the left */
+       do
+       :: counter > 0 ->
+               in?nextval;                     /* upon receipt of a new value */
+               if
+               :: nextval >= myval -> out!nextval
+               :: nextval <  myval ->
+                       out!myval;
+                       myval=nextval           /* send bigger, hold smaller */
+               fi;
+               counter = counter - 1
+       :: counter == 0 -> break
+       od
+}
+
+proctype right(chan in)        /* rightmost channel */
+{      byte biggest;
+
+       xr in;
+
+       in?biggest              /* accepts only one value, which is the biggest */
+}
+
+init {
+       byte proc=1;
+
+       atomic {
+               run left ( q[0] );
+               do
+               :: proc < N ->
+                       run middle ( q[proc-1] , q[proc], proc );
+                       proc = proc+1
+               :: proc == N -> break
+               od;
+               run right ( q[N-1] )
+       }
+}
diff --git a/trunk/verif/Spin/Test/wordcount b/trunk/verif/Spin/Test/wordcount
new file mode 100755 (executable)
index 0000000..5c3efc9
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+       Example of property-based slicing.
+       Try:    spin -A wordcount
+       Requires Spin version 3.4 or later
+ */
+
+chan STDIN;
+int c, nl, nw, nc;
+
+init {
+        bool inword = false;
+
+        do
+        :: STDIN?c ->
+                if
+                :: c == -1 ->   break  /* EOF */
+                :: c == '\n' -> nc++; nl++
+                :: else ->      nc++
+                fi;
+                if
+                :: c == ' ' || c == '\t' || c == '\n' ->
+                        inword = false
+                :: else ->
+                        if
+                        :: !inword ->
+                                nw++; inword = true
+                        :: else /* do nothing */
+                        fi
+                fi
+        od;
+       assert(nc >= nl);
+        printf("%d\t%d\t%d\n", nl, nw, nc)
+}
diff --git a/trunk/verif/Spin/Xspin5.1/xspin510.tcl b/trunk/verif/Spin/Xspin5.1/xspin510.tcl
new file mode 100755 (executable)
index 0000000..3597ebe
--- /dev/null
@@ -0,0 +1,7095 @@
+#!/bin/sh
+# the next line restarts using wish \
+exec wish c:/cygwin/bin/xspin -- $*
+
+# cd   ;# enable to cd to home directory by default
+
+# on PCs:
+# adjust the first argument to wish above with the name and
+# location of this tcl/tk file on your system, if different.
+#
+# Cygwin:
+# if you use cygwin, do not refer to the file as /usr/bin/xspin
+# /usr/bin is a symbolic link to /bin, which really
+# lives in c:/cygwin, hence the contortions above
+#
+# on Unix/Linux/Solaris systems
+# replace the first line with something like
+#      #!/usr/bin/wish -f
+# using the pathname for the wish executable on your system
+
+#======================================================================#
+# Tcl/Tk Spin Controller, written by Gerard J. Holzmann, 1995-2005.    #
+# See the README.html file for full installation notes.                #
+#        http://spinroot.com/spin/whatispin.html                       #
+#======================================================================#
+set xversion "5.1.0 -- 24 April 2008"
+
+# -- Xspin Installation Notes (see also README.html):
+
+# 1. On Unix systems: change the first line of this file to point to the wish
+#    executable you want to use (e.g., wish4.2 or /usr/local/bin/wish8.0)
+#    ==> be careful, the pathname should be 30 characters or less
+#
+# 2. If you use another C compiler than gcc, change the set CC line below
+#
+# 3. Browse the configurable options below if you would like to
+#    change or adjust the visual appearance of the GUI
+#
+# 4. If you run on a PC, and have an ancient version of tcl/tk,
+#    you must set the values fo Unix, CMD, and Go32 by hand below
+#    => with Tcl/Tk 7.5/4.1 or later, this happens automatically
+
+# set CC   "cc -w -Wl -woff,84"        ;# ANSI-C compiler, suppress warnings
+# set CC   "cl -w -nologo"     ;# Visual Studio C/C++ compiler, prefered on PCs
+  set CC   "gcc -w"            ;# standard gcc compiler - no warnings
+  set CC0  "gcc"
+
+# set CPP  "cpp"               ;# the normal default C preprocessor
+  set CPP  "gcc -E -x c"       ;# c preprocessor, assuming we have gcc
+
+  set SPIN "spin"      ;# use a full path-name if necessary, e.g. c:/cygwin/bin/spin.exe
+  set DOT  "dot"       ;# optional, graph layout interface
+                       ;# no prob if dot is not available
+  set BG   "white"     ;# default background color for text
+  set FG   "black"     ;# default foreground color for text
+  set CMD  ""          ;# default is empty, and adjusted below
+  set Unix 1           ;# default is Unix, but this is adjusted below
+  set Ptype "color"    ;# printer-type: mono, color, or gray
+  set NT 0             ;# scratch variable, ignore
+
+  set debug_on 0
+  if {$debug_on} {
+       toplevel .debug ;   #debugging window
+       text .debug.txt -width 80 -height 60 -relief raised -bd 2 \
+               -yscrollcommand ".debug.scroll set"
+       scrollbar .debug.scroll -command ".debug.txt yview"
+       pack .debug.scroll -side right -fill y
+       pack .debug.txt -side left
+  }
+  proc debug {txt} {
+       global debug_on
+       if {$debug_on} {
+       catch { .debug.txt insert end "\n$txt" }
+  }    }
+
+  if [info exists tcl_platform] {
+       set sys $tcl_platform(platform)
+#      if {$sys == "macintosh"} {
+#              ... no adjustments needed? ...
+#      }
+        if {[string match windows $sys]} {
+               set Unix 0      ;# means Windows95/98/2000/NT/XP
+
+#              if {[auto_execok cl] != ""} {
+#                      set CC   "cl -w -nologo"        ;# Visual Studio compiler, PCs
+#                      set CC0  "cl"
+#              }
+
+               if {$tcl_platform(os) == "Windows 95"} {
+                       set CMD  "command.com"  ;# Windows95
+               } else {
+                       set CMD  "cmd"
+                       set NT 1
+  }    }       }
+
+#-- GUI configuration options - by Leszek Holenderski <lhol@win.tue.nl>
+#-- basic text size:
+       set HelvBig     -Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*
+# mscs:
+       if {$NT} {      ;# on a windows nt machine
+       set SmallFont   "-*-Courier-Bold-R-Normal--*-110-*"
+       set BigFont     "-*-Courier-Bold-R-Normal--*-110-*"
+       } else {
+       set SmallFont   "-*-Courier-Bold-R-Normal--*-80-*"
+       set BigFont     "-*-Courier-Bold-R-Normal--*-80-*"
+       }
+
+# Some visual aspects of Xspin GUI can be configured by the user.
+# On PCs, the values of configuration options that are hard-coded
+# into this script can be modified (see below). On Unix, in addition to
+# (or rather, instead of) the manual modification, the values can be set in
+# an Xspin resource file ($HOME/.xspinrc) and/or in the X11 default resource
+# file (usually, $HOME/.Xdefaults).
+
+# Since the same option can be specified in several places, options can have
+# several, possibly inconsistent, values. The value which takes effect is
+# determined by the order in which options are scanned. The values specified
+# later in the order have higher priority. First, hard-coded options are
+# scanned, then options specified in .Xdefaults, and finally options
+# specified in .xspinrc.
+
+# When setting configuration options in an .xspinrc file, convert the 
+# settings below to the format of an X11 resource file. For example,
+#
+#      # width of scrollbars (any Tk dimension, default 15 pixels)
+#      option add *Scrollbar.width     13      startupFile
+#
+# should be converted to
+#
+#      ! width of scrollbars (any Tk dimension, default 15 pixels)
+#      *Scrollbar.width        13
+# In .Xdefaults file, configuration options should be preceded by the
+# application's name, so the above option should be converted to
+#
+#      ! width of scrollbars (any Tk dimension, default 15 pixels)
+#      xspin*Scrollbar.width   13
+# side on which side scrollbars are put (left or right, default=right)
+
+option add *Scrollbar.side     left    startupFile
+
+#--- sizes
+       # width of scrollbars (any Tk dimension, default 15 pixels)
+       option add *Scrollbar.width     13      startupFile
+       # width of borders (in pixels, typically 1 or 2, default 2)
+       option add *borderWidth         1       startupFile
+       # initial width of the input/log area (in characters, default 80)
+       option add *Input*Text.width    72      startupFile
+       option add *Log*Text.width      72      startupFile
+       # initial height of the input area (in lines, default 24)
+       option add *Input*Text.height   20      startupFile
+       # initial height of the log area (in lines, default 24)
+       option add *Log*Text.height     5       startupFile
+       # size of the handle used to adjust the height of the log area
+       # (in pixels, default 0)
+       option add *Handle.width        10      startupFile
+       option add *Handle.height       10      startupFile
+#--- colors
+       # colors for the input/log area
+       option add *Input*Text.background       white   startupFile
+       option add *Input*Text.foreground       black   startupFile
+       option add *Log*Text.background         gray95  startupFile
+       option add *Log*Text.foreground         black   startupFile
+       # colors for the editable/read-only area
+       option add *Entry.background            white   startupFile
+       option add *Edit*Text.background        white   startupFile
+       option add *Edit*Text.foreground        black   startupFile
+       # colors for the editable/read-only area
+       option add *Read*Text.background        gray95  startupFile
+       option add *Read*Text.foreground        black   startupFile
+#--- fonts
+       # fonts for the input/log area (default is system dependent,
+       # usually -*-Courier-Medium-R-Normal--*-120-*)
+option add *Input*Text.font    -*-Helvetica-Medium-R-Normal--*-120-*   startupFile
+#option add *Input*Text.font   -schumacher-clean-medium-r-normal--*-120-*-60-* startupFile
+#option add *Log*Text.font     -schumacher-clean-medium-r-normal--*-120-*-60-* startupFile
+
+#--- widgets
+       # simple texts (dialogs which present read-only texts, such as help)
+       option add *SimpleText.Text.width 60
+       option add *SimpleText.Text.height 30
+       option add *SimpleText.Text.background white
+
+       # sections (decorated frames for grouping related buttons)
+       option add *Section*Title.font          -*-Helvetica-Bold-R-Normal--*-100-*     startupFile
+
+#option add *Section*Checkbutton.font  -*-Helvetica-Medium-R-Normal--*-100-*   startupFile
+#option add *Section*Radiobutton.font  -*-Helvetica-Medium-R-Normal--*-100-*   startupFile
+#option add *Section*Label.font                -*-Helvetica-Medium-R-Normal--*-100-*   startupFile
+
+################ end of configurable parameters #######################
+
+wm title . "SPIN CONTROL $xversion"
+wm iconname . "SPIN"
+wm geometry . +41+50
+wm minsize  . 400 200
+
+set Fname ""
+set firstime 1
+set notignored 0
+
+#### seed the advanced parameters settings
+
+set e(0)       "Physical Memory Available (in Mbytes): "
+set ival(0)    128
+set expl(0)    "explain"
+
+set e(1)       "Estimated State Space Size (states x 10^3): "
+set ival(1)    500
+set expl(1)    "explain"
+
+set e(2)       "Maximum Search Depth (steps): "
+set ival(2)    10000
+set expl(2)    "explain"
+
+set e(7)       "Nr of hash-functions in Bitstate mode: "
+set ival(7)    2
+set expl(7)    "explain"
+
+set e(3)       "Extra Compile-Time Directives (Optional): "
+set ival(3)    ""
+set expl(3)    "Choose"
+
+set e(4)       "Extra Run-Time Options (Optional): "
+set ival(4)    ""
+set expl(4)    "Choose"
+
+set e(5)       "Extra Verifier Generation Options: "
+set ival(5)    ""
+set expl(5)    "Choose"
+
+set ival(6)    1       ;# which error is reported, default is 1st
+
+
+# allow no more than one entry per selection
+catch { tk_listboxSingleSelect Listbox }
+
+proc msg_file {f nowarn} {
+       set msg ""
+       set ef [open $f r]
+
+       while {[gets $ef line] > -1} {
+               if {$nowarn} {
+                       if {[string first "warning" $line] < 0} {
+                               set msg "$msg\n$line"
+                       }
+               } else {
+                       set msg "$msg\n$line"
+       }       }
+       close $ef
+       return $msg
+}
+
+       scan $tk_version "%d.%d" tk_major tk_minor
+
+       set version ""
+
+       if {[auto_execok $SPIN] == "" \
+       ||  [auto_execok $SPIN] == 0} {
+               set version "Error: No executable $SPIN found..."
+       } else {
+               if {$Unix} {
+                       set version [exec $SPIN -V]
+               } else {
+                       catch { exec $SPIN -V >&pan.tmp } err
+                       if {$err == ""} {
+                               set version [msg_file pan.tmp 1]
+                       } else {
+                               puts "error: $err"
+                               puts "is there a $SPIN and a go32.exe?"
+                               exit
+               }       }
+               if {[string first "Spin Version 5" $version] < 0 \
+               &&  [string first "Spin Version 4" $version] < 0 \
+               &&  [string first "Spin Version 3" $version] < 0 } {
+                       set version "Spin Version not recognized: $version"
+               }
+       }
+
+frame .menu
+       # top level menu bar
+       menubutton .menu.file -text "File.." \
+               -relief raised -menu .menu.file.m
+       menubutton .menu.run -text "Run.." -fg red \
+               -relief raised -menu .menu.run.m
+       menubutton .menu.edit -text "Edit.." \
+               -relief raised -menu .menu.edit.m
+       menubutton .menu.view -text "View.." \
+               -relief raised -menu .menu.view.m
+       label .menu.title -text "SPIN  DESIGN  VERIFICATION" -fg blue
+
+       set lno 1
+       label .menu.lno -text "Line#:" -relief raised 
+       entry .menu.ent -width 6 -textvariable lno \
+               -relief sunken -background white -foreground black
+       bind  .menu.ent <Return> {
+               .inp.t tag remove hilite 0.0 end
+               .inp.t tag add hilite $lno.0 $lno.1000
+               .inp.t tag configure hilite -background $FG -foreground $BG
+               .inp.t yview -pickplace [expr $lno-4]
+       }
+
+       label .menu.fnd1 -text "Find:" -relief raised 
+       entry .menu.fnd2 -width 8 -textvariable pat \
+               -relief sunken -background white -foreground black
+       bind  .menu.fnd2 <Return> {
+               .inp.t tag remove hilite 0.0 end
+               forAllMatches .inp.t $pat
+       }
+
+       menubutton .menu.help -text "Help" -relief raised \
+               -menu .menu.help.m
+
+       pack append .menu \
+               .menu.file {left frame w} \
+               .menu.edit {left frame w} \
+               .menu.view {left frame w} \
+               .menu.run {left frame w} \
+               .menu.help {left frame w} \
+               .menu.title {left frame c expand} \
+               .menu.fnd2 {right frame e} \
+               .menu.fnd1 {right frame e} \
+               .menu.ent {right frame e} \
+               .menu.lno {right frame e}
+
+set loglines 5
+frame .log
+       text .log.t -bd 2 -height $loglines -background $FG -foreground $BG
+frame .log.b
+       button .log.b.pl -text "+" \
+               -command {incr loglines  1; .log.t configure -height $loglines}
+       button .log.b.mn -text "-" \
+               -command {incr loglines -1; .log.t configure -height $loglines}
+       pack append .log.b .log.b.pl {top}
+       pack append .log.b .log.b.mn {top}
+       pack append .log .log.b {left filly}
+       pack append .log .log.t {right expand fill}
+
+proc dopaste {} {
+       global FG BG
+       set from [.inp.t index insert]
+       tk_textPaste .inp.t
+       set upto [.inp.t index insert]
+       .inp.t tag add sel $from $upto
+#      .inp.t tag configure hilite -background $FG -foreground $BG
+}
+
+#- fetch the value of user-defined configuration options
+
+proc fetchOption {name default args} {
+
+  set class Dummy
+  set fullName $name
+
+  # class encoded in name ?
+  switch -glob -- $name *.* {
+    set list [split $name .]
+    switch [llength $list] 2 {} default { error "wrong option \"$name\" }
+    set class [lindex $list 0]
+    set name  [lindex $list 1]
+  }
+
+  # create a unique dummy frame of requested class and get the option's value
+  set dummy .0
+  while {[winfo exists $dummy]} { append dummy 0 }
+  frame $dummy -class $class
+  set value [option get $dummy $name $class]
+  destroy $dummy
+
+  # option not defined ?
+  switch -- $value "" { return $default }
+
+  # check a restriction on option's value
+  switch [llength $args] {
+    0 { # no restriction
+      }
+    1 { # restriction is given as a list of allowed values
+        switch -- [lsearch -exact [lindex $args 0] $value] -1 {
+          set msg "wrong value \"$value\" of option \"$fullName\"\
+                   (should be one of $args)"
+          return -code error -errorinfo $msg $msg
+        }
+      }
+    2 { # restriction is given as a range (min and max)
+        set min [lindex $args 0]
+        set max [lindex $args 1]
+        if {$value < $min} { set $value $min }
+        if {$value > $max} { set $value $max }
+      }
+    default {
+      error "internal error in fetchOption: wrong restriction \"$args\""
+    }
+  }
+
+  return $value
+}
+
+# width of borders
+set BD [fetchOption borderWidth 1 0 4]
+#option add *Text.highlightThickness $BD startupFile
+
+# scrollbar's side
+set scrollbarSide [fetchOption Scrollbar.side right {left right}]
+
+frame .inp
+       # view of spin input
+       scrollbar .inp.s  -command ".inp.t yview"
+       text .inp.t -bd 2  -font $HelvBig -yscrollcommand ".inp.s set" -wrap word
+
+       pack .inp.s -side $scrollbarSide -fill y
+       pack append .inp \
+               .inp.t {left expand fill}
+
+       menu .inp.t.edit -tearoff 0
+       .inp.t.edit add command -label "Cut" \
+               -command {tk_textCopy .inp.t; tk_textCut .inp.t}
+       .inp.t.edit add command -label "Copy" \
+               -command {tk_textCopy .inp.t}
+       .inp.t.edit add command -label "Paste" \
+               -command {dopaste}
+
+       bind .inp.t <ButtonPress-3> {
+               tk_popup .inp.t.edit %X %Y
+       }
+       bind .inp.t <ButtonRelease-1> { setlno }
+
+
+set l_typ 0;   # used by both simulator and validator
+set lt_typ 0;  # used by ltl panel
+set ol_typ -1; # remembers setting last used in compilation
+set m_typ 2;   # used by simulator
+
+menu .menu.file.m
+       .menu.file.m add command -label "New"  \
+               -command ".inp.t delete 0.0 end"
+#      .menu.file.m add command -label "UnSelect" \
+#              -command ".inp.t tag remove hilite 0.0 end;\
+#                        .inp.t tag remove Rev 0.0 end;\
+#                        .inp.t tag remove sel 0.0 end"
+       .menu.file.m add command -label "ReOpen" -command "open_spec"
+       .menu.file.m add command -label "Open.." -command "open_spec 0"
+       .menu.file.m add command -label "Save As.." -command "save_spec 0"
+       .menu.file.m add command -label "Save" -command "save_spec"
+       .menu.file.m add command -label "Quit" \
+               -command "cleanup 1; destroy .; exit"
+
+menu .menu.help.m
+       .menu.help.m add command -label "About Spin" \
+               -command "aboutspin"
+       .menu.help.m add separator
+       .menu.help.m add command -label "Promela Usage" \
+               -command "promela"
+       .menu.help.m add command -label "Xspin Usage" \
+               -command "helper"
+       .menu.help.m add command -label "Simulation" \
+               -command "roadmap1"
+       .menu.help.m add command -label "Verification" \
+               -command "roadmap2"
+       .menu.help.m add command -label "LTL Formulae" \
+               -command "roadmap4"
+       .menu.help.m add command -label "Spin Automata View" \
+               -command "roadmap5"
+       .menu.help.m add command -label "Reducing Complexity" \
+               -command "roadmap3"
+
+menu .menu.run.m
+       .menu.run.m add command -label "Run Syntax Check" \
+               -command {syntax_check "-a -v" "Syntax Check"}
+       .menu.run.m add command -label "Run Slicing Algorithm" \
+               -command {syntax_check "-A" "Property-Specific Slicing"}
+       .menu.run.m add separator
+       .menu.run.m add command -label "Set Simulation Parameters.." \
+               -command simulation
+       .menu.run.m add command -label "(Re)Run Simulation" \
+               -command Rewind -state disabled
+       .menu.run.m add separator
+       .menu.run.m add command -label "Set Verification Parameters.." \
+               -command "basicval"
+       .menu.run.m add command -label "(Re)Run Verification" \
+               -command {runval "0"} -state disabled
+       .menu.run.m add separator
+       .menu.run.m add command -label "LTL Property manager.." \
+               -command call_tl
+       .menu.run.m add separator
+       .menu.run.m add command -label "View Spin Automaton for each Proctype.." \
+               -command fsmview
+
+
+menu .menu.edit.m
+       .menu.edit.m add command -label "Cut" \
+               -command {tk_textCopy .inp.t; tk_textCut .inp.t}
+       .menu.edit.m add command -label "Copy" \
+               -command {tk_textCopy .inp.t}
+       .menu.edit.m add command -label "Paste" \
+               -command {tk_textPaste .inp.t}
+
+set FSz 110
+
+menu .menu.view.m
+       .menu.view.m add command -label "Larger" \
+               -command {
+                       incr FSz 10
+                       set HelvBig "-Adobe-Helvetica-Medium-R-Normal--*-$FSz-*-*-*-*-*-*"
+                       .inp.t configure -font $HelvBig
+               }
+       .menu.view.m add command -label "Default text size" \
+               -command {
+                       set FSz 110
+                       set HelvBig "-Adobe-Helvetica-Medium-R-Normal--*-$FSz-*-*-*-*-*-*"
+                       .inp.t configure -font $HelvBig
+               }
+       .menu.view.m add command -label "Smaller" \
+               -command {
+                       incr FSz -10
+                       set HelvBig "-Adobe-Helvetica-Medium-R-Normal--*-$FSz-*-*-*-*-*-*"
+                       .inp.t configure -font $HelvBig
+               }
+       .menu.view.m add separator
+       .menu.view.m add command -label "Clear Selections" \
+               -command ".inp.t tag remove hilite 0.0 end;\
+                         .inp.t tag remove Rev 0.0 end;\
+                         .inp.t tag remove sel 0.0 end"
+
+proc setlno {} {
+       scan [.inp.t index insert] "%d.%d" lno cno
+       .menu.ent delete 0 end
+       .menu.ent insert end $lno
+       .inp.t tag remove hilite $lno.0 $lno.end        ;# or else cursor is invis
+       update
+}
+
+proc add_log {{y ""}} {
+
+       if {$y == "\n"} { return }
+       .log.t insert end "\n$y"
+       .log.t yview -pickplace end
+}
+
+proc cleanup {how} {
+       global Unix
+       if {$Unix == 0 && $how == 1} {
+               add_log "removing temporary files, please wait.."; update
+       }
+       rmfile "pan.h pan.c pan.t pan.m pan.b pan.tmp pan.ltl"
+       rmfile "pan.oin pan.pre pan.out pan.exe pan.otl"
+       rmfile "pan_in pan_in.trail trail.out pan"
+       rmfile "_tmp1_ _tmp2_ pan.o pan.obj pan.exe"
+       if {$Unix == 0 && $how == 1} { add_log "done.." }
+}
+
+
+pack append . \
+       .log  {bot frame w fillx} \
+       .inp  {bot frame w expand fill} \
+       .menu {top fillx}
+
+# simulation parameters - initial settings
+       set fvars 1
+       set msc   1;    set svars 1
+       set rvars 1
+       set stop  0;    set tsc 0
+       set seed        "1";    # random sumulation
+       set jumpsteps   "0";    # guided simulation
+
+       set s_typ 0
+       # meaning s_type values:
+       # 0 - Random Simulation (using seed)
+       # 1 - Guided Simulation (using pan.trail)
+       # 2 - Interactive Simulation
+
+       set whichsim 0
+       # meaning of whichsim values:
+       # 0 - use pan_in.tra(il)
+       # 1 - use user specified file
+
+tkwait visibility .log
+add_log "SPIN LOG:"
+add_log " $version"
+add_log "Xspin Version $xversion"
+add_log "TclTk Version [info tclversion]/$tk_version\n"
+
+       if {$Unix == 0} {
+       if {[auto_execok $CC0] == "" \
+       ||  [auto_execok $CC0] == 0} {
+               set m "Error: no C compiler found: $CC"
+               add_log $m
+               catch { tk_messageBox -icon info -message $m }
+       }}
+
+.inp.t configure -background $BG -foreground $FG
+
+# process execution barchart
+
+set Data(0) 0
+set Name(0) "-"
+set n 0
+set bar_handle 0
+set PlaceBar   ""
+
+proc stopbar {} {
+       global Data Name n PlaceBar
+       for {set i 0} {$i <= $n} {incr i} {
+               set Data($i) 0
+               set Name($i) ""
+       }
+       set n 0
+       set PlaceBar [wm geometry .bar]
+       set k [string first "\+" $PlaceBar]
+       if {$k > 0} {
+               set PlaceBar [string range $PlaceBar $k end]
+       }
+       catch { destroy .bar }
+}
+
+proc growbar {v} {
+       global n Data
+       set Data($n) $v
+       incr n
+       catch { fillbar }
+}
+
+proc shrinkbar {} {
+       global n
+       incr n -1
+       set Data($n) 0
+       catch { fillbar }
+}
+
+proc stepbar {v nm} {
+       global n Data Name
+
+       if {$v >= 0} {
+               if { [info exists Data($v)] } {
+                       incr Data($v)
+               } else {
+                       set Data($v) 1
+               }
+               if {$v >= $n} {
+                       set n [expr $v+1]
+               }
+               if { [string length $nm] > 4} {
+                       set Name($v) [string range $nm 0 4]
+               } else {
+                       set Name($v) $nm
+               }
+               catch { fillbar }
+       }
+}
+
+proc adjustbar {v w} {
+       global Data
+
+       set Data($v) $w
+       catch { fillbar }
+}
+
+proc startbar {tl} {
+       global n Data bar_handle Ptype PlaceBar
+
+       catch { destroy .bar }
+       toplevel .bar
+       wm minsize .bar 200 200
+       wm title .bar "$tl"
+
+       set maxy [expr [winfo screenheight .] - 200]
+       if {$PlaceBar == ""} {
+               set PlaceBar "+[expr [winfo rootx .]+150]+$maxy"
+       }
+       wm geometry .bar $PlaceBar
+
+       set bar_handle [canvas .bar.c -height 410 -width 410 -relief raised]
+       frame  .bar.buts
+
+       button .bar.buts.s1 -text "Save in:  panbar.ps" \
+               -command ".bar.c postscript -file panbar.ps -colormode $Ptype"
+
+       button .bar.buts.b -text " Close " -command "stopbar"
+       pack .bar.buts.b .bar.buts.s1 -side right
+       pack append .bar  .bar.c {top expand fill}  .bar.buts {bot frame e}
+}
+
+proc fillbar {} {
+       global n Data Name
+
+       .bar.c delete grid
+       .bar.c delete data
+       set sum 0
+       for {set i 0} {$i < $n} {incr i} {
+               if { [info exists Data($i)] } {
+                       incr sum $Data($i)
+               } else {
+                       set Data($i) 0
+                       set Name($i) "-"
+               }
+       }
+       for {set i 0} {$i < $n} {incr i} {
+               .bar.c create line \
+                       $i 0 \
+                       $i 100 \
+                       -fill #222222 -tags grid
+               .bar.c create text $i 105 \
+                       -text $i -tags grid
+               .bar.c create text $i 110 \
+                       -text "$Name($i)" \
+                       -fill blue -tags grid
+
+               if { [info exists Data($i)] } {
+                       set y [expr ($Data($i)*100)/$sum]
+                       .bar.c create line \
+                               $i 100  \
+                               $i [expr 100-$y] \
+                               -width 35 -fill red -tags data
+                       if {$y > 6} {
+                               set nrcol "yellow"
+                       } else {
+                               set nrcol "red"
+                       }
+                       .bar.c create text $i 95 \
+                               -text "$Data($i)" \
+                               -fill $nrcol -tags grid
+               }
+       }
+
+       .bar.c create text [expr ($n)/2.0] -15 -text "Percentage of $sum System Steps" \
+               -anchor c -justify center -tags grid
+       .bar.c create text [expr ($n)/2.0] -8 -text "Executed Per Process ($n total)" \
+               -anchor c -justify center -tags grid
+       .bar.c scale all 0 0 55 3
+       if {$n <= 5} {
+               .bar.c move all 100 60
+       } else {
+               .bar.c move all 50 60
+       }
+}
+
+proc barscales {} {
+       global bar_handle
+
+       catch {
+               button .bar.buts.b4 -text "Larger" \
+                       -command "$bar_handle scale all 0 0 1.1 1.1"
+               button .bar.buts.b5 -text "Smaller" \
+                       -command "$bar_handle scale all 0 0 0.9 0.9"
+               pack append .bar.buts \
+                       .bar.buts.b4 {right padx 5} \
+                       .bar.buts.b5 {right padx 5}
+       }
+}
+
+# Files and Generic Boxes
+
+set file ""
+set boxnr 0
+
+proc rmfile {f} {
+       global Unix CMD tk_major tk_minor
+
+       set err ""
+       catch { eval file delete -force $f } err
+       if {$err == "" } { return }
+
+       if {$Unix} {
+               catch {exec rm -f $f}
+       } else {
+               set n [llength $f]
+               for {set i 0} {$i < $n} {incr i} {
+                       set g [lindex $f $i]
+                       add_log "rm $g"
+                       if {$tk_major >= 4 && $tk_minor >= 2} {
+                               catch {exec $CMD /c del $g}
+                       } else {
+                               catch {exec $CMD >&@stdout /c del $g}
+                       }
+       }       }
+}
+
+proc mvfile {f g} {
+       global Unix CMD tk_major tk_minor
+
+       set err ""
+       catch { file rename -force $f $g } err
+       if {$err == "" } { return }
+
+       if {$Unix} {
+               catch {exec mv $f $g}
+       } else {
+               if {$tk_major >= 4 && $tk_minor >= 2} {
+                       catch {exec $CMD /c move $f $g}
+               } else {
+                       catch {exec $CMD >&@stdout /c move $f $g}
+               }
+       }
+}
+
+proc cpfile {f g} {
+       global Unix CMD tk_major tk_minor
+
+       set err ""
+       catch { file copy -force $f $g } err
+       if {$err == "" } { return }
+
+       if {$Unix} {
+               catch {exec cp $f $g}
+       } else {
+               if {$tk_major >= 4 && $tk_minor >= 2} {
+               catch {exec $CMD /c copy $f $g}
+               } else {
+               catch {exec $CMD >&@stdout /c copy $f $g}
+       }       }
+}
+
+proc cmpfile {f g} {
+       global Unix
+
+       set err ""
+       if {$Unix} {
+               catch {exec cmp $f $g} err
+       } else {
+               if {[file exists $f] == 0 \
+               ||  [file exists $g] == 0} {
+                       return "error"
+               }
+               set fd1 [open $f r]
+               set fd2 [open $g r]
+               while {1} {
+                       set n1 [gets $fd1 line1]
+                       set n2 [gets $fd2 line2]
+                       if {$n1 != $n2 \
+                       ||  [string compare $line1 $line2] != 0} {
+                               set err "files differ"
+                               break
+                       }
+                       if {$n1 < 0} { break }
+               }
+               close $fd1
+               close $fd2
+       }
+       return $err
+}
+
+proc file_ok {f} {
+       if {[file exists $f]} {
+               if {![file isfile $f] || ![file writable $f]} {
+                       set m "error: file $f is not writable"
+                       add_log $m
+                       catch { tk_messageBox -icon info -message $m }
+                       return 0
+       }       }
+       return 1
+}
+
+proc mkpan_in {} {
+       global HasNever
+       set fd [open pan_in w]
+
+       fconfigure $fd -translation lf
+       puts $fd [.inp.t get 0.0 end] nonewline
+
+       if {$HasNever != ""} {
+               if [catch {set fdn [open $HasNever r]} errmsg] {
+                       add_log $errmsg
+                       catch { tk_messageBox -icon info -message $errmsg }
+               } else {
+                       while {[gets $fdn line] > -1} {
+                               puts $fd $line
+                       }
+                       catch "close $fdn"
+       }       }
+       catch "flush $fd"
+       catch "close $fd"
+}
+
+proc no_ltlchange {} {
+
+       if {![file exists pan.ltl]} {
+               return 1
+       }
+       if {![file exists pan.otl]} {
+               cpfile pan.ltl pan.otl
+               return 0                ; first time
+       }
+       set err [cmpfile pan.ltl pan.otl]
+       if {[string length $err] > 0} {
+               cpfile pan.ltl pan.otl
+               return 0                ;# different
+       }
+       return 1                        ;# unchanged
+}
+
+proc no_change {} {
+       global nv_typ
+
+       mkpan_in        ;# keep this up to date
+       if {![file exists pan.oin]} {
+               cpfile pan_in pan.oin
+               return 0                ; first time
+       }
+       set err [cmpfile pan_in pan.oin]
+       if {[string length $err] > 0} {
+               cpfile pan_in pan.oin
+               return 0                ;# different
+       }
+       if {$nv_typ == 0} {
+               return 1
+       }
+       return [no_ltlchange]           ;# unchanged
+}
+
+proc mk_exec {} {
+       global Unix CC SPIN notignored
+
+       set nochange [no_change]
+       if {$nochange == 1 && [file exists "pan"]} {
+               add_log "<no recompilation needed>"
+               return 1
+       }
+
+       add_log "<compiling executable>"
+       catch {
+       warner "Compiling" "Please wait until compilation of the \
+executable produced by spin completes." 300
+       }
+       add_log "$SPIN -a pan_in"
+
+       catch {exec $SPIN -a pan_in >&pan.tmp}
+       set errmsg [msg_file pan.tmp 1]
+
+       if {[string length $errmsg]>0} {
+               add_log "$errmsg"
+               catch { tk_messageBox -icon info -message $errmsg }
+               add_log "<stopped compilation attempt>"
+               catch { destroy .warn }
+               return 0
+       }
+
+       add_log "$CC -o pan -D_POSIX_SOURCE pan.c"; update
+       if {$Unix} {
+               catch { eval exec $CC -o pan -D_POSIX_SOURCE pan.c >pan.tmp 2>pan.err} errmsg
+       } else {
+               catch { eval exec $CC -o pan -D_POSIX_SOURCE pan.c >pan.tmp 2>pan.err}
+       }
+       set errmsg [msg_file pan.tmp 0]
+       set errmsg "$errmsg \n [msg_file pan.err 0]"
+
+               if {[string length $errmsg]>0 && $notignored} {
+                       add_log "$errmsg"
+                       catch { tk_messageBox -icon info -message $errmsg }
+                       catch { destroy .warn }
+                       return 0
+               }
+       add_log "<compilation complete>"
+       catch {destroy .warn}
+       return 1
+}
+
+set PlaceWarn  "+20+20"
+
+proc warner {banner msg w} {
+       global PlaceWarn
+
+       catch {destroy .warn}
+       toplevel .warn
+
+       wm title .warn "$banner"
+       wm iconname .warn "Info"
+       set k [string first "\+" $PlaceWarn]
+       if {$k > 0} {
+               set PlaceWarn [string range $PlaceWarn $k end]
+       }
+       wm geometry .warn $PlaceWarn
+
+       message .warn.t -width $w -text $msg
+       button .warn.ok -text "Ok" \
+               -command "set PlaceWarn [wm geometry .warn]; destroy .warn"
+
+       pack append .warn .warn.t {top expand fill}
+       pack append .warn .warn.ok {bottom}
+
+       update
+}
+
+proc dosave {} {
+       global Fname xversion
+
+       if {[file_ok $Fname]==0} return
+       set fd [open $Fname w]
+       add_log "<saved spec in $Fname>"
+       puts $fd "[.inp.t get 0.0 end]" nonewline
+       catch "flush $fd"
+       catch "close $fd"
+       wm title . "SPIN CONTROL $xversion -- File: $Fname"
+}
+
+proc save_spec {{curr 1}} {
+#-
+#- Save the input area into a file.
+#-
+#- If 'curr' is true then we save to the current file. Otherwise, a file
+#- selection dialog is presented. If a file is selected (note that the
+#- dialog can be canceled) then we try to write to it.
+#-
+
+  global Fname
+
+  if $curr {
+    switch -- $Fname "" {
+      add_log "no file to save to, try \"Save as ...\""
+      return
+    }
+    writeoutfile .inp.t $Fname
+  } else {
+    # try to use the predefined file selection dialog
+    switch [info commands tk_getSaveFile] "" {
+      # some old version of Tk so use our own file selection dialog
+      set fileselect "FileSelect save"
+    } default {
+      set fileselect "tk_getSaveFile"
+    }
+  
+    # get the file (return if the file selection dialog canceled)
+    switch -- [set file [eval $fileselect]] "" return
+  
+    # write the file and update Fname if the file written successfully
+    if [writeoutfile .inp.t $file] {
+      set Fname $file
+    }
+  }
+}
+
+proc consider_it {} {
+       global file Fname xversion
+
+       if {[file isdirectory $file]} then {
+               cd $file
+               fillerup ""
+               add_log "cd $file"
+       } else {
+               if {![file isfile $file]} {
+                       set file ""
+               } else {
+                       readinfile .inp.t $file
+
+                       rmfile pan_in.trail
+                       cpfile $file.trail pan_in.trail
+
+                       set dir [pwd]
+                       set Fname $file
+                       wm title . "SPIN CONTROL $xversion -- File: $Fname"
+                       destroy .b
+       }       }
+}
+
+#----------------------------------------------------------------------
+# Improvements - by Leszek Holenderski <lhol@win.tue.nl>
+# GUI configuration and File Selection dialogs
+#----------------------------------------------------------------------
+
+# predefined priorities for options stored in the option data base are
+#      widgetDefault   20
+#      startupFile     40
+#      userDefault     60
+#      interactive     80
+
+# most of frames are used for layout purposes so they should be invisible
+option add *Frame.borderWidth 0 interactive
+
+proc try_with {xspinrc} {
+
+  if ![file exists $xspinrc] return
+
+  if ![file isfile $xspinrc] {
+    puts "xspin warning: the resource file \"$xspinrc\" exists but is not\
+          a normal file"
+    return
+  }
+  if ![file readable $xspinrc] {
+    puts "xspin warning: the resource file \"$xspinrc\" exists but is not\
+          readable"
+    return
+  }
+  if [catch {option readfile $xspinrc userDefault} result] {
+    puts "xspin warning: some problems when trying to load the resource\
+          file \"$xspinrc\"\n$result"
+    return
+  }
+}
+
+if [info exists env(HOME)] {
+  if $Unix {
+    try_with [file join $env(HOME) .xspinrc]
+  } else {
+    try_with [file join $env(HOME) xspinrc]
+  }
+}
+
+proc FileSelect {mode {title ""}} {
+  switch -- $mode open - save {} default { set mode open }
+
+  switch $mode {
+    open {
+      set title Open
+      set okButtonText Open
+    }
+    save {
+      set title Save
+      set okButtonText Save
+    }
+  }
+
+  set w .fileselect
+  upvar #0 $w this
+
+  if [winfo exists $w] {
+    wm title $w $title
+    $this(okButton) config -text $okButtonText
+    catch {wm geom $w $this(geom)}
+    wm deiconify $w
+  } else {
+    toplevel $w -class Fileselect
+    wm title $w $title
+    # the minimal size is given in characters and lines (setgrid is on)
+    wm minsize $w 14 7
+
+    # layout frames
+    pack [set f [frame $w.f]] -padx 5 -pady 5 -fill both -expand yes
+    pack [set buttons [frame $f.b]] -side bottom -fill x
+    pack [set name    [frame $f.n]] -side bottom -fill x -pady 5
+    pack [set path    [frame $f.p]] -side top -fill x
+    pack [set files   [frame $f.f]] -side top -fill both -expand yes
+  
+    # create ok/cancel buttons
+    set okButton [button $buttons.ok -text $okButtonText \
+                       -command "FileSelect.Close $w 1"]
+    pack $okButton -side right
+
+    set cancelButton [button $buttons.cancel -text Cancel \
+                       -command "FileSelect.Close $w 0"]
+    pack $cancelButton -side left
+
+    MakeSameWidth "$okButton $cancelButton"
+  
+    # create path button
+    set pathButton $path.path
+    global $w|currDir
+    set pathMenu [tk_optionMenu $pathButton $w|currDir ""]
+    pack $pathButton -side top
+  
+    # create the list of files
+    global scrollbarSide
+
+    set fileList $files.l
+    set scrollbar $files.s
+    pack [scrollbar $files.s -command "$fileList yview"] \
+        -side $scrollbarSide -fill y
+    pack [listbox $fileList -yscrollcommand "$files.s set" -selectmode single -setgrid on] \
+        -side $scrollbarSide -expand yes -fill both
+  
+    bind $fileList <ButtonPress-1>        "FileSelect.Selected $w %x %y"
+    bind $fileList <Double-ButtonPress-1> "FileSelect.Chosen   $w %x %y"
+
+    set fileEntry $name.e
+    pack [label $name.l -text File:] -side left
+    pack [entry $fileEntry] -side right -expand yes -fill x
+
+    set this(okButton)   $okButton
+    set this(pathButton) $pathButton
+    set this(pathMenu)   $pathMenu
+    set this(fileList)   $fileList
+    set this(fileEntry)  $fileEntry
+
+    foreach widget "$okButton $cancelButton $pathButton $fileList $scrollbar" {
+      $widget config -highlightthickness 0
+    }
+
+    wm protocol $w WM_DELETE_WINDOW [$cancelButton cget -command]
+  }
+
+  # fill in the list of files
+  if ![info exists this(path)] { set this(path) [pwd] }
+  FileSelect.cd $w $this(path)
+
+  # make the dialog modal (set a grab and claim the focus)
+
+  set oldFocus [focus]
+  set oldGrab [grab current $w]
+  if {$oldGrab != ""} { set grabStatus [grab status $oldGrab] }
+  grab $w
+  focus $this(fileEntry)
+
+  # make the contents of file entry selected (for easy deletion)
+  $this(fileEntry) select from 0
+  $this(fileEntry) select to end
+
+  # Wait for the user to respond, then restore the focus and return the
+  # contents of file entry.
+  # Restore the focus before deleting the window, since otherwise the
+  # window manager may take the focus away so we can't redirect it.
+  # Finally, restore any grab that was in effect.
+
+  global $w|response
+  tkwait variable $w|response
+  catch {focus $oldFocus}
+  grab release $w
+  set this(geom) [wm geom $w]
+  wm withdraw $w
+  if {$oldGrab != ""} {
+      if {$grabStatus == "global"} {
+         grab -global $oldGrab
+      } else {
+         grab $oldGrab
+      }
+  }
+  return [set $w|response]
+}
+
+proc CompareNoCase {s1 s2} {
+  return [string compare [string tolower $s1] [string tolower $s2]]
+}
+
+proc FileSelect.LoadFiles {w} {
+    upvar #0 $w this
+
+    # split all names in the current directory into dirs and files
+    set dirs ""
+    set files ""
+    set filter ""
+    if [info exists this(filter)] { set filter $this(filter) }
+    switch -- $filter "" { set filter * }
+    foreach f [lsort -command CompareNoCase [glob -nocomplain .* *]] {
+       if [file isdir $f] {
+         # exclude the '.' and '..' directory
+         switch -- $f . - .. continue
+         lappend dirs $f
+       }
+       if [file isfile $f] {
+         # filter files
+         switch -glob -- $f $filter { lappend files $f }
+       }
+    }
+
+    # Fill in the file list
+    $this(fileList) delete 0 end
+    foreach d $dirs {
+       # append directory mark to the name (tricky)
+       set d [string trimright [file join $d a] a]
+       $this(fileList) insert end $d
+    }
+    foreach f $files { $this(fileList) insert end $f }
+}
+
+proc FileSelect.LoadPath {w} {
+    upvar #0 $w this
+
+    # convert path to list
+    set dirs [file split $this(path)]
+
+    # compute prefix paths
+    set path ""
+    set paths ""
+    foreach d $dirs {
+       set path [file join $path $d]
+       lappend paths $path
+    }
+
+    # reverse dirs and paths
+    set rev_dirs ""
+    foreach d $dirs { set rev_dirs [concat [list $d] $rev_dirs] }
+    set rev_paths ""
+    foreach p $paths { set rev_paths [concat [list $p] $rev_paths] }
+
+    # update the path menubutton
+    global $w|currDir
+    set $w|currDir [lindex $rev_dirs 0]
+
+    # fill in the path menu
+    $this(pathMenu) delete 0 end
+    foreach d [lrange $rev_dirs 1 end] p [lrange $rev_paths 1 end] {
+       $this(pathMenu) add command -label $d -command "FileSelect.cd $w $p"
+    }
+}
+
+proc FileSelect.Selected {w x y} {
+    upvar #0 $w this
+
+    # determine the selected list element
+    set elem [$this(fileList) get [$this(fileList) index @$x,$y]]
+    switch -- $elem "" return
+
+    # directories cannot be selected (they can only be chosen)
+    if [file isdir $elem] return
+
+    $this(fileEntry) delete 0 end
+    $this(fileEntry) insert end $elem
+}
+
+proc FileSelect.Chosen {w x y} {
+    upvar #0 $w this
+
+    # determine the selected list element
+    set elem [$this(fileList) get [$this(fileList) index @$x,$y]]
+    switch -- $elem "" return
+
+    # if directory then cd, otherwise close the dialog
+    if [file isdir $elem] { FileSelect.cd $w $elem } { FileSelect.Close $w 1 }
+}
+
+proc FileSelect.Close {w {ok 1}} {
+  # trigger the end of dialog
+  upvar #0 $w this $w|response response
+  if $ok {
+    set response [file join $this(path) [$this(fileEntry) get]]
+  } else {
+    set response ""
+  }
+}
+
+proc FileSelect.cd {w dir} {
+    upvar #0 $w this
+
+    if [catch {cd $dir} errmsg] {
+       puts "xspin warning: $errmsg"
+       return
+    }
+
+    set this(path) [pwd]
+    FileSelect.LoadFiles $w
+    FileSelect.LoadPath $w
+}
+
+proc open_spec {{curr 1}} {
+  global Fname
+
+  if $curr {
+    switch -- $Fname "" {
+      add_log "no file to reopen, try \"Open ...\""
+      return
+    }
+    readinfile .inp.t $Fname
+  } else {
+    # try to use the predefined file selection dialog
+    switch [info commands tk_getOpenFile] "" {
+      # some old version of Tk so use our own file selection dialog
+      set fileselect "FileSelect open"
+    } default {
+      set fileselect "tk_getOpenFile"
+    }
+    set init_dir [pwd]
+    # get the file (return if the file selection dialog canceled)
+    switch -- [set file [eval $fileselect -initialdir { $init_dir } ]] "" return
+  
+    # load the file and update some items if the file loaded successfully
+    if [readinfile .inp.t $file] {
+      rmfile pan_in.trail
+      cpfile $file.trail pan_in.trail
+      set Fname $file
+      set_path $Fname
+    }
+  }
+}
+
+
+proc set_path {Fname} {
+       #cd to directory in file
+       set fullpath [split $Fname /]
+       set nlen [llength $fullpath]
+       set fullpath [lrange $fullpath 0 [expr $nlen - 2]]      ;# get rid of filename
+       set wd [join $fullpath /]                               ;#put path back together
+       catch {cd $wd}
+}
+
+set defname ""
+
+proc loaddefault_tl {} {
+       global Fname defname
+
+       if {$defname ==""} {
+               set file2 "$Fname.ltl"
+       } else {
+               set file2 $defname
+       }
+       catch {
+               .tl.main.e1 delete 0 end
+               .tl.macros.t delete 0.0 end
+               .tl.notes.t delete 0.0 end
+               .tl.never.t delete 0.0 end
+               .tl.results.t delete 0.0 end
+       }
+       if {![file exists $file2]} {
+               .tl.notes.t insert end "Use Load to open a file or a template."
+               return
+       }
+       catch {
+               .tl.notes.title configure -text "Notes \[file $file2]:"
+       }
+       readinfile .tl.never.t $file2
+       catch { extract_defs }
+}
+
+set suffix "ltl"
+
+proc browse_tl {} {
+       global defname suffix
+
+       set suffix "ltl"
+
+       catch {destroy .b}
+       toplevel .b
+       wm iconname .b "Load"
+
+       frame .b.top
+       frame .b.bot
+       scrollbar .b.top.scroll -command ".b.top.list yview"
+       listbox .b.top.list -yscroll ".b.top.scroll set" -relief raised 
+
+       button .b.zap -text "Cancel" -command "destroy .b"
+       button .b.all -text "Show All Files" \
+               -command {
+                       set suffix ""
+                       fillerup ""
+                       destroy .b.all
+               }
+       message .b.bot.msg -text "Dir: "
+       entry .b.bot.entry -textvariable dir -relief sunken -width 20
+       pack append .b.top \
+               .b.top.scroll {right filly} \
+               .b.top.list {left expand fill}
+       pack append .b.bot \
+               .b.bot.msg {left} \
+               .b.bot.entry {left}
+       pack append .b \
+               .b.top {top fillx} \
+               .b.all {left} \
+               .b.zap {left} \
+               .b.bot {left}
+       
+       bind .b.bot.entry <Return> {
+               set nd [.b.bot.entry get]
+               if {[file isdirectory $nd]} {
+                       cd $nd
+                       fillerup $suffix
+                       add_log "cd $nd"
+               }
+       }
+
+       fillerup  $suffix
+       bind .b.top.list <Double-Button-1> {
+               set file2 [selection get]
+               if {[string first "---" $file2] >= 0} {
+                       # ignore
+               } elseif {[string first "Invariance" $file2] >= 0} {
+                       catch {
+                       .tl.main.e1 delete 0 end
+                       .tl.macros.t delete 0.0 end
+                       .tl.notes.t delete 0.0 end
+                       .tl.never.t delete 0.0 end
+                       .tl.results.t delete 0.0 end
+
+                       .tl.main.e1 insert end "\[\] (p)"
+                       .tl.notes.t insert end "'p' is invariantly true throughout
+an execution"
+                       .tl.notes.title configure \
+                               -text "Notes \[template $file2]:"
+                       do_ltl
+                       destroy .b
+                       }
+               } elseif {[string first "Response" $file2] >= 0} {
+                       catch {
+                       .tl.main.e1 delete 0 end
+                       .tl.macros.t delete 0.0 end
+                       .tl.notes.t delete 0.0 end
+                       .tl.never.t delete 0.0 end
+                       .tl.results.t delete 0.0 end
+
+                       .tl.main.e1 insert end "\[\] ((p) -> (<> (q)))"
+                       .tl.notes.t insert end "if 'p' is true in at least one state,
+then sometime thereafter 'q' must also
+become true at least once."
+                       .tl.notes.title configure \
+                               -text "Notes \[template $file2]:"
+                       do_ltl
+                       destroy .b
+                       }
+               } elseif {[string first "Precedence" $file2] >= 0} {
+                       catch {
+                       .tl.main.e1 delete 0 end
+                       .tl.macros.t delete 0.0 end
+                       .tl.notes.t delete 0.0 end
+                       .tl.never.t delete 0.0 end
+                       .tl.results.t delete 0.0 end
+
+                       .tl.main.e1 insert end "\[\] ((p) -> ((q) U (r)))"
+                       .tl.notes.t insert end "'p' is a trigger, or 'enabling' condition that
+determines when this requirement becomes applicable
+'r' is the fullfillment of the requirement, and
+'q' is a condition that must remain true in the interim."
+                       .tl.notes.title configure \
+                               -text "Notes \[template $file2]:"
+                       do_ltl
+                       destroy .b
+                       }
+               } elseif {[string first "Objective" $file2] >= 0} {
+                       catch {
+                       .tl.main.e1 delete 0 end
+                       .tl.macros.t delete 0.0 end
+                       .tl.notes.t delete 0.0 end
+                       .tl.never.t delete 0.0 end
+                       .tl.results.t delete 0.0 end
+
+                       .tl.main.e1 insert end "\[\] ((p) -> <>((q) || (r)))"
+                       .tl.notes.t insert end "'p' is a trigger, or 'enabling' condition that
+determines when this requirement becomes applicable
+'q' is the fullfillment of the requirement, and
+'r' is a discharging condition that terminates the
+applicability of the requirement."
+
+                       .tl.notes.title configure \
+                               -text "Notes \[template $file2]:"
+                       do_ltl
+                       destroy .b
+                       }
+               } elseif {[file isdirectory $file2]} then {
+                       cd $file2
+                       fillerup $suffix
+                       add_log "cd $file2"
+               } else {
+                       if {![file isfile $file2]} {
+                               set file2 ""
+                       } else {
+                               catch {
+                               .tl.main.e1 delete 0 end
+                               .tl.macros.t delete 0.0 end
+                               .tl.notes.t delete 0.0 end
+                               .tl.never.t delete 0.0 end
+                               .tl.results.t delete 0.0 end
+                               .tl.notes.title configure \
+                                       -text "Notes \[file $file2]:"
+                               }
+                               readinfile .tl.never.t $file2
+                               set defname $file2
+                               catch { extract_defs }
+                               set dir [pwd]
+                               destroy .b
+                       }
+               }
+       }
+}
+
+proc reopen {} {
+       global Fname
+
+       catch {readinfile .inp.t $Fname} ermsg
+       if {[string length $ermsg]<=1} { return }
+       add_log $ermsg
+       catch { tk_messageBox -icon info -message $ermsg }
+}
+
+proc check_xsp {f} {
+       set ff ${f}.xsp
+       if [catch {set fd [open $ff r]} errmsg] {
+               # add_log "no file $ff"
+               return
+       }
+       add_log "reading $ff file"
+       update
+       while {[gets $fd line] > -1} {
+               if {[string first "X:" $line] == 0} {
+                       set C [string range $line 3 end]
+                       add_log "X: $C"
+                       update
+                       catch { eval exec $C } errmsg
+                       if {$errmsg != ""} { add_log $errmsg }
+               }
+               if {[string first "L:" $line] == 0} {
+                       set N [string range $line 3 end]
+                       catch {.log.t configure -height $N -bg black -fg gold}
+               }
+       }
+}
+
+proc writeoutfile {from to} {
+
+  if ![file_ok $to] { return 0 }
+
+  if [catch {set fd [open $to w]} errmsg] {
+    add_log $errmsg
+    catch { tk_messageBox -icon info -message $ermsg }
+    return 0
+  }
+
+  add_log "<saved spec in $to>"
+  puts $fd [string trimright [$from get 0.0 end] "\n"]
+# puts -nonewline $fd [$from get 0.0 end]
+  close $fd
+  return 1
+}
+
+proc readinfile {into from} {
+
+  if [catch {set fd [open $from r]} errmsg] {
+    add_log $errmsg
+    catch { tk_messageBox -icon info -message $ermsg }
+    return 0
+  }
+       
+  $into delete 0.0 end
+  while {[gets $fd line] > -1} { $into insert end $line\n }
+  catch { close $fd }
+  add_log "<open $from>"
+
+  global LastGenerate
+  set LastGenerate ""  ;# used in Validation.tcl
+  return 1
+}
+
+proc fillerup {suffix} {
+       wm title .b [pwd]
+       .b.top.list delete 0 end
+
+       set dotdot 0
+       set l {}
+       catch { if {$suffix != ""} {
+                       set l [lsort [glob *.$suffix]]
+               } else {
+                       set l [lsort [glob *]]
+       }       }
+       foreach i $l {
+               .b.top.list insert end $i
+               if {$i == ".."} { set dotdot 1 }
+       }
+       if {$dotdot == 0} {
+               .b.top.list insert 0 ".."
+       }
+       if {$suffix != ""} {
+               .b.top.list insert 0 "------files:--------"
+               .b.top.list insert 0 "Objective(p,q,r)"
+               .b.top.list insert 0 "Precedence(p,q,r)"
+               .b.top.list insert 0 "Response(p,q)"
+               .b.top.list insert 0 "Invariance(p)"
+               .b.top.list insert 0 "-----templates:-----"
+       }
+}
+
+proc gotoline {} {
+       global BG FG
+
+       catch { destroy .ln }
+       toplevel .ln
+       wm title .ln "Goto Line"
+       wm iconname .ln "Goto"
+
+       label .ln.lab -text "Enter line number:"
+       entry .ln.ent -width 20 -relief sunken -textvariable lno
+       pack append .ln \
+               .ln.lab {left padx 1m} \
+               .ln.ent {right expand}
+       bind .ln.ent <Return> {
+               .inp.t tag remove hilite 0.0 end
+               .inp.t tag add hilite $lno.0 $lno.1000
+               .inp.t tag configure hilite \
+                       -background $FG -foreground $BG
+               .inp.t yview -pickplace [expr $lno-1]
+       }
+       focus .ln.ent
+}
+
+proc savebox {b} {
+       set fname [.c$b.f.e1 get]
+       if {[file_ok $fname]==0} return
+       set fd [open $fname w]
+       add_log "<saved output in $fname>"
+       puts $fd "[.c$b.z.t get 0.0 end]" nonewline
+       catch "flush $fd"
+       catch "close $fd"
+}
+
+proc doplace {a b} {
+       global PlaceBox
+       set PlaceBox($a) [wm geometry .c$b]
+       set k [string first "\+" $PlaceBox($a)]
+       if {$k > 0} {
+               set PlaceBox($a) [string range $PlaceBox($a) $k end]
+       }
+}
+
+proc mkbox {n m p {wd 60} {ht 10} {xp 200} {yp 200}} {
+       global boxnr FG BG PlaceBox HelvBig
+       global ind old_ss old_insert new_insert;# for search capability
+
+       incr boxnr
+
+       toplevel .c$boxnr
+       wm title .c$boxnr $n
+       wm iconname .c$boxnr $m
+
+       if {[info exists PlaceBox($n)] == 0} {
+               set PlaceBox($n) "+$xp+$yp"
+       } 
+       wm geometry .c$boxnr $PlaceBox($n)
+
+       #initialize search parameters
+       set ind 1.0
+       set old_ss ""
+       set old_insert ""
+       set new_insert ""
+       frame .c$boxnr.d ;# search bar
+               label .c$boxnr.d.l -text "Search for: "
+               entry .c$boxnr.d.e -width 15
+               bind .c$boxnr.d.e <KeyPress-Return> "search_sim .c$boxnr.z.t .c$boxnr.d.e .c$boxnr" 
+               button .c$boxnr.d.b -text "Find" -command "search_sim .c$boxnr.z.t .c$boxnr.d.e .c$boxnr"
+
+       pack .c$boxnr.d -side top -fill x
+       pack .c$boxnr.d.b -side right
+       pack .c$boxnr.d.e -side right
+       pack .c$boxnr.d.l -side right
+
+       frame .c$boxnr.z
+       
+       text .c$boxnr.z.t -relief raised -bd 2 -font $HelvBig \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".c$boxnr.z.s set" \
+               -setgrid 1 -width $wd -height $ht -wrap word
+       bind .c$boxnr.z.t <ButtonRelease-1> "+update idletasks; update_insert .c$boxnr.z.t"
+       scrollbar .c$boxnr.z.s \
+               -command ".c$boxnr.z.t yview"
+       pack append .c$boxnr.z \
+               .c$boxnr.z.s {left filly} \
+               .c$boxnr.z.t {left expand fill}
+
+       button .c$boxnr.b -text "Close" \
+       -command "doplace {$n} {$boxnr}; destroy .c$boxnr"
+       button .c$boxnr.c -text "Clear" \
+               -command ".c$boxnr.z.t delete 0.0 end"
+       pack append .c$boxnr \
+               .c$boxnr.z {top expand fill} \
+               .c$boxnr.b {right padx 5} \
+               .c$boxnr.c {right padx 5}
+
+       if {[string length $p]>0} {
+               frame  .c$boxnr.f -relief sunken
+               button .c$boxnr.f.e0 -text "Save in: " \
+                       -command "savebox $boxnr"
+               entry  .c$boxnr.f.e1 -relief flat -width 10
+               .c$boxnr.f.e1 insert end $p
+               pack append .c$boxnr.f \
+                       .c$boxnr.f.e0 {left padx 5} \
+                       .c$boxnr.f.e1 {left}
+               pack append .c$boxnr \
+                       .c$boxnr.f {right padx 5}
+       }
+
+       tkwait visibility .c$boxnr
+       raise .c$boxnr
+       return $boxnr
+}
+proc update_insert {t} {
+       global new_insert
+       update idletasks
+       set new_insert [$t index insert]
+}
+
+proc search_sim {t e b} {
+       global ind old_ss old_insert new_insert
+
+       set ss [$e get]
+
+       if {$ss == ""} {
+               return
+               }
+
+       #if user has selected use that lin.char as 'ind'. otherwise use end of last word found
+       #set new_insert [$t index insert]
+       if {$new_insert != $old_insert} {
+               set ind $new_insert ;# this is where we will start searching
+               set old_insert $new_insert ;# update select location
+       }
+       set cur_ind $ind
+       set ind [$t search $ss $ind]
+
+       set old_ss $ss
+       if {$ind != ""} {
+               $t yview -pickplace $ind
+               $t tag configure hilite -foreground black -background white
+               $t tag delete hilite 
+               set split_ind [split $ind "."]
+               set char [lindex $split_ind 1]  
+               set char [incr char [string length $ss]]
+               set indstart $ind
+               set indend ""
+               append indend [lindex $split_ind 0] "." $char
+               $t tag add hilite $indstart $indend
+               $t tag configure hilite -foreground white -background black
+               set ind $indend
+       } else {
+               # set ind 1.0
+               catch { tk_messageBox -icon info -message "no match for $ss" }
+               set ind $cur_ind ;# restore ind to last good value
+               raise $b
+       }       
+
+}
+
+# Tcl/Tk book, page 219
+proc forAllMatches {w pattern} {
+       global BG FG lno
+
+       scan [$w index end] %d numLines
+       for {set i 1} {$i < $numLines} { incr i} {
+               $w mark set last $i.0
+               if {[regexp -indices $pattern \
+                       [$w get last "last lineend"] indices]} {
+                               $w mark set first \
+                                       "last + [lindex $indices 0] chars"
+                               $w mark set last "last + 1 chars \
+                                       + [lindex $indices 1] chars"
+                       .inp.t tag add hilite $i.0 $i.end
+                       .inp.t tag configure hilite \
+                               -background $FG -foreground $BG
+#                      .inp.t yview -pickplace [expr $i-1]
+       }       }
+
+#      move to the next line that matches
+
+       for {set i [expr $lno+1]} {$i < $numLines} { incr i} {
+               $w mark set last $i.0
+               if {[regexp -indices $pattern \
+                       [$w get last "last lineend"] indices]} {
+                               $w mark set first \
+                                       "last + [lindex $indices 0] chars"
+                               $w mark set last "last + 1 chars \
+                                       + [lindex $indices 1] chars"
+                       .inp.t yview -pickplace [expr $i-5]
+                       set lno $i
+                       return
+       }       }
+       for {set i 1} {$i <= $lno} { incr i} {
+               $w mark set last $i.0
+               if {[regexp -indices $pattern \
+                       [$w get last "last lineend"] indices]} {
+                               $w mark set first \
+                                       "last + [lindex $indices 0] chars"
+                               $w mark set last "last + 1 chars \
+                                       + [lindex $indices 1] chars"
+                       .inp.t yview -pickplace [expr $i-5]
+                       set lno $i
+                       return
+       }       }
+       catch {
+               tk_messageBox -icon info -message "No Match of \"$pattern\""
+       }
+}
+
+set noprep 0
+
+proc hasWord {pattern} {
+       global SPIN noprep
+       set err ""
+       if {![file exists pan.pre] && $noprep == 0} {
+               add_log "$SPIN -Z pan_in ;# preprocess input $pattern"
+               catch {exec $SPIN -Z pan_in >&pan.tmp} err
+               # leaves output in pan.pre
+               add_log "<done preprocess>"
+       }
+
+       if {[string length $err] == 0 && $noprep == 0} {
+               set fd [open pan.pre r]
+               while {[gets $fd line] > -1} {
+                 if {[regexp -indices $pattern $line indices]} {
+                       catch "close $fd"
+                       return 1
+               } }
+               catch "close $fd"
+               return 0
+       }
+
+       # else, there were errors, just ignore the include files:
+       set noprep 1
+       add_log "$err"
+       scan [.inp.t index end] %d numLines
+       for {set i 1} {$i < $numLines} { incr i} {
+               .inp.t mark set last $i.0
+               if {[regexp -indices $pattern \
+                       [.inp.t get last "last lineend"] indices]} {
+                               return 1
+               }
+       }
+       return 0
+}
+
+# FSM view option
+
+set nodeX(0) 0
+set nodeY(0) 0
+set Label(0) 0
+set Transit(0) {}
+set TLabel(0) 0
+set Lab2Node(0) 0
+set Dist(0) 0
+set State(0) 0
+set Edges(0) {}
+set New 0
+set MaxDist 0
+set Maxx 0
+set Maxy 0
+set Minx 50
+set Miny 50
+set reached_end 0
+set Scale 1
+
+set cnr        0
+set x 0
+set y 0
+
+proc fsmview {} {
+       global Unix
+
+       add_log "<fsm view option>"
+
+       if {[mk_exec] != 1} { return }
+
+       catch {destroy .z}
+       toplevel .z
+
+       wm title .z "Double-Click Proc"
+
+       listbox .z.list -setgrid 1
+       button .z.b -text "Cancel" -command "destroy .z"
+
+       pack append .z \
+               .z.list {top expand fill} \
+               .z.b {right padx 5}
+
+       if {$Unix} {
+               add_log "./pan -d       # find proc names"; update
+               set fd [open "|./pan -d" w+]
+       } else {
+               add_log "pan -d # find proc names"; update
+               catch { eval exec pan -d >&pan.tmp } err
+               if {$err != ""} {
+                       add_log "error: $err"
+               }
+               set fd [open pan.tmp r]
+       }
+       while {[gets $fd line] > -1} {
+               if {[string first "proctype" $line] >= 0 } {
+                       .z.list insert end \
+                       [string trim [string range $line 9 end]]
+       }       }
+       catch { close $fd }
+
+       bind .z.list <Double-Button-1> {
+               set pfind [selection get]
+               catch { destroy .z }
+               findfsm $pfind
+       }
+       focus .z.list
+}
+
+proc findfsm {pfind} {
+       global Unix New Dist State Edges Label
+       global Transit MaxDist reached_end TLabel DOT
+
+       if {[mk_exec] != 1} { return }
+
+       set src  0; set trn 0; set trg 0
+       set Want 0; set MaxDist 0; set startstate ""
+
+       catch { foreach el [array names State] { unset State($el) } }
+       catch { foreach el [array names Edges] { unset Edges($el) } }
+       catch { foreach el [array names Dist]  { unset Dist($el) } }
+
+       if {$Unix} {
+               add_log "./pan -d       # compute fsm"; update
+               set fd [open "|./pan -d" w+]
+       } else {
+               add_log "pan -d # compute fsm"; update
+               catch { eval exec pan -d >&pan.tmp }
+               set fd [open pan.tmp r]
+       }
+       while {[gets $fd line] > -1} {
+               set k [string first "proctype" $line]
+               if { $k >= 0 } {
+                       if { $Want == 1 } {
+                               break
+                       }
+                       incr k 9
+                       set pname [string range $line $k end]
+
+                       if { [string first $pfind $line] >= 0 \
+                       &&   [string length $pfind] == [string length $pname]} {
+                               set Want 1
+                               set reached_end 0
+                               set nsrc "$pname:0"
+                               set Dist($nsrc) 0
+                               set Label($nsrc) "end"
+                               set Edges($nsrc) {}
+                       }
+               } elseif { $Want == 1 \
+                       && [string first "statement" $line] < 0 
+                       && [string first "state" $line] >= 0} {
+                       scan $line "    state %d -(tr %d)-> state %d" \
+                               src trn trg
+                       if {$trg == 0} { set reached_end 1 }
+
+                       set nsrc "$pname:$src"
+                       set ntrg "$pname:$trg"
+
+                       if {$startstate == ""} { set startstate $nsrc }
+
+                       set k [string first "line" $line]
+                       if { $k > 0 } {
+                               set m [string first "=>" $line]
+                               incr m -1
+                               set lbl [string range $line $k $m]
+                               incr m 3
+                               set action [string range $line $m end]
+                       } else {
+                               set lbl "line 0"
+                               set action "line 0"
+                       }
+                       set Label($nsrc) $lbl
+                       if { [info exists Dist($nsrc)] == 0 } {
+                               set Dist($nsrc) 0
+                               set Edges($nsrc) {}
+                       }
+                       if { [info exists Dist($ntrg)] == 0 } {
+                               set Dist($ntrg) [expr $Dist($nsrc) + 1]
+                               set Edges($ntrg) {}
+                               if {$Dist($ntrg) > $MaxDist } {
+                                       set MaxDist $Dist($ntrg)
+                               }
+                       } else {
+                               if { [expr $Dist($nsrc) + 1] < $Dist($ntrg) } {
+                                       set Dist($ntrg) [expr $Dist($nsrc) + 1]
+                                       if {$Dist($ntrg) > $MaxDist } {
+                                               set MaxDist $Dist($ntrg)
+                                       }
+                       }       }
+if {0 \
+&&  [auto_execok $DOT] != 0 \
+&&  [auto_execok $DOT] != ""} {
+       set z1 [string first "\[" $action]
+       set z2 [string last  "\]" $action]
+       if {$z1 > 0 && $z2 > $z1} {
+               incr z1 -1; incr z2
+               set a1 [string range $action 0 $z1]
+               set a2 [string range $action $z2 end]
+               set action "$a1$a2"
+       }
+                       set kkk "$nsrc;$trg:$action"
+                       lappend Edges($nsrc) "$kkk"
+                       lappend Edges($kkk) $ntrg
+                       lappend Transit($nsrc) "$lbl"
+                       lappend Transit($kkk) ""
+                       set Dist($kkk) $Dist($ntrg)
+                       set Label($kkk) "T3"
+} else {
+                       lappend Edges($nsrc) $ntrg
+                       lappend Transit($nsrc) $action
+}
+               }
+       }
+       if { $Want == 1 } {
+               dograph $pfind $startstate
+       } else {
+               add_log "sorry, $pfind not found..."
+               catch {
+               tk_messageBox -icon info -message "$pfind not found..."
+               }
+       }
+       catch "close $fd"
+       add_log "<done>"
+       update
+}
+
+proc plunknode {el prefix} {
+       global State Label TLabel
+       global x y
+
+       set pn [string range $el $prefix end]
+       set State($el) [mkNode "$Label($el)" $pn $x $y]
+
+       if { $x > 250 } {
+               set x [expr $x - 250]
+               set x [expr 250 - $x]
+       } else {
+               set x [expr 250 - $x]
+               incr x 75
+               set x [expr 250 + $x]
+       }
+}
+
+proc dograph {n s} {
+       global Dist Edges Label Transit MaxDist State ELabel
+       global cnr lcnr reached_end x y Unix DOT
+       set count -1
+
+       set lcnr [mkcanvas "FSM $n" $n 300 300 0]
+       set prefix [string length $n]
+       incr prefix
+       set y 0
+
+       while {$count < $MaxDist} {
+               incr count
+               incr y 50
+               set x 250
+               foreach el [array names Dist] {
+                       if { [ string first $n $el ] >= 0 \
+                       &&   $Dist($el) == $count \
+                       &&   $el != "$n:0" } {
+                               plunknode $el $prefix
+               }       }
+       }
+       if {$reached_end == 1} {
+               # force end state at the bottom
+               incr y 50
+               set x 250
+               plunknode "$n:0" $prefix
+       }
+
+       foreach el [array names Edges] {
+               if { [ string first $n $el ] >= 0 } {
+                       for {set i 0} { [lindex $Edges($el) $i] != "" } {incr i} {
+                               set ntrg [lindex $Edges($el) $i]
+                               set lbl  [lindex $Transit($el) $i]
+                               mkEdge $lbl $State($el) $State($ntrg)
+                               set ELabel($el,$ntrg) "$lbl"
+                       }
+       }       }
+       addscales $lcnr
+
+       .f$cnr.c itemconfigure $State($s) -outline red; update
+
+       if {[auto_execok $DOT] != 0 \
+       &&  [auto_execok $DOT] != ""} {
+               dodot $n
+#              button .f$lcnr.b66 -text "Redraw with Dot"  -command "dodot $n"
+#              pack append .f$lcnr .f$lcnr.b66 {right padx 5}
+       }
+       update
+}
+
+proc mkNode {n t x y} {
+       # tcl book p. 213
+       global cnr NodeWidth NodeHeight HelvBig
+       global nodeX nodeY New TLabel Lab2Node
+
+       if {[string first ";" $t] > 0} {
+               set New [.f$cnr.c create rectangle [expr $x-1] [expr $y-1] \
+                       [expr $x+1] [expr $y+1] \
+                       -outline white \
+                       -fill white \
+                       -tags node]
+               set z [string first ":" $t]; incr z
+               set t [string range $t $z end]
+               set Lab [.f$cnr.c create text $x $y -font $HelvBig -text $n -tags node]
+       } else {
+               set New [.f$cnr.c create oval [expr $x-10] [expr $y-10] \
+                       [expr $x+10] [expr $y+10] \
+                       -outline black \
+                       -fill white \
+                       -tags node]
+               set Lab [.f$cnr.c create text $x $y -font $HelvBig -text $n -tags node]
+       
+               .f$cnr.c bind $Lab <Any-Enter> "
+                       .f$cnr.c itemconfigure {$Lab} -fill black -text {$t}
+                       if {[string first \"end\" $n] < 0 } { set_src {$t} }
+               "
+               .f$cnr.c bind $Lab <Any-Leave> "
+                       .f$cnr.c itemconfigure {$Lab} -fill black -text {$n}
+               "
+       }
+       set nodeX($New) $x
+       set nodeY($New) $y
+       set TLabel($New) $Lab
+       set Lab2Node($Lab) $New
+       set NodeWidth($New) 10
+       set NodeHeight($New) 10
+
+       update
+       return $New
+}
+
+proc set_src {n} {
+       set where 0
+       scan $n "line %d" where
+       .inp.t tag remove hilite 0.0 end
+       src_line $where
+}
+
+proc mkEdge {L a b} {
+       global cnr Xrem Yrem TransLabel HelvBig
+       global nodeX nodeY edgeHead edgeTail
+
+       if { $nodeY($b) > $nodeY($a) } {
+               set ydiff -11
+       } elseif { $nodeY($b) < $nodeY($a) } {
+               set ydiff 11
+       } else {
+               set ydiff 0
+       }
+       if { $nodeX($b) > $nodeX($a) } {
+               set xdiff -6
+       } elseif { $nodeX($b) < $nodeX($a) } {
+               set xdiff 6
+       } else {
+               set xdiff 0
+       }
+       set edge [.f$cnr.c create line \
+               $nodeX($a) $nodeY($a) \
+               [expr $nodeX($b) + $xdiff] \
+               [expr $nodeY($b) + $ydiff] \
+                -arrow both -arrowshape {4 3 3} ]
+       .f$cnr.c lower $edge
+       lappend edgeHead($a) $edge
+       lappend edgeTail($b) $edge
+
+       set Xrem($edge) $xdiff
+       set Yrem($edge) $ydiff
+
+       set midX [expr $nodeX($a) + $nodeX($b)]
+       set midX [expr $midX / 2 ]
+       set midY [expr $nodeY($a) + $nodeY($b)]
+       set midY [expr $midY / 2 ]
+
+       set TransLabel($a,$b) \
+       [.f$cnr.c create text $midX $midY -font $HelvBig -tags texttag]
+
+       .f$cnr.c bind $edge <Button-1> "
+               .f$cnr.c coords $TransLabel($a,$b) \[.f$cnr.c canvasx %x\] \[.f$cnr.c canvasy %y\]
+               .f$cnr.c itemconfigure $TransLabel($a,$b) \
+                       -fill black -text {$L} -font $HelvBig
+       "
+       .f$cnr.c bind $edge <ButtonRelease-1> "
+               .f$cnr.c itemconfigure $TransLabel($a,$b) \
+                       -fill black -text {}
+       "
+}
+
+proc moveNode {cnr node mx my together} {
+       global edgeHead edgeTail TLabel NodeWidth NodeHeight
+       global nodeX nodeY Lab2Node
+       global Xrem Yrem Scale
+
+       set x [.f$cnr.c coords $node]
+       if {[llength $x] == 2} { set node $Lab2Node($node) }
+
+       set mx [.f$cnr.c canvasx $mx]
+       set my [.f$cnr.c canvasy $my]
+
+       set wx $NodeWidth($node)
+       set wy $NodeHeight($node)
+
+       .f$cnr.c coords $node \
+               [expr $mx-$wx] [expr $my-$wy] \
+               [expr $mx+$wx] [expr $my+$wy]
+       .f$cnr.c coords $TLabel($node) $mx $my
+
+       set nodeX($node) $mx
+       set nodeY($node) $my
+       if {$together == 0} { return }
+       catch {
+       foreach edge $edgeHead($node) {
+               set ec [.f$cnr.c coords $edge]
+               set nx [expr $nodeX($node) + $Xrem($edge)*$Scale]
+               set ny [expr $nodeY($node) + $Yrem($edge)*$Scale]
+               .f$cnr.c coords $edge \
+                       $nx $ny \
+                       [lindex $ec 2] [lindex $ec 3]
+       }}
+       catch {
+       foreach edge $edgeTail($node) {
+               set ec [.f$cnr.c coords $edge]
+               set nx [expr $nodeX($node) + $Xrem($edge)*$Scale]
+               set ny [expr $nodeY($node) + $Yrem($edge)*$Scale]
+               .f$cnr.c coords $edge \
+                       [lindex $ec 0] [lindex $ec 1] \
+                       $nx $ny
+       }}
+}
+
+set PlaceCanvas(msc)   ""
+
+proc mkcanvas {n m geox geoy placed} {
+       global cnr tk_version
+       global Chandle Sticky
+       global FG BG Ptype PlaceCanvas
+
+       incr cnr
+       toplevel .f$cnr
+       wm title .f$cnr "$n"
+       wm iconname .f$cnr $m
+       if {$placed} {
+               if {$PlaceCanvas($m) == ""} {
+                       set PlaceCanvas($m) "+$geox+$geoy"
+               }
+               set k [string first "\+" $PlaceCanvas($m)]
+               if {$k > 0} {
+               set PlaceCanvas($m) [string range $PlaceCanvas($m) $k end]
+               }
+               wm geometry .f$cnr $PlaceCanvas($m)
+       }
+       wm minsize .f$cnr 100 100
+
+       if {[string first "4." $tk_version] == 0 \
+       ||  [string first "8." $tk_version] == 0} {
+               set cv [canvas .f$cnr.c  -relief raised -bd 2\
+                       -scrollregion {-15c -5c 30c 40c} \
+                       -background $BG \
+                       -xscrollcommand ".f$cnr.hscroll set" \
+                       -yscrollcommand ".f$cnr.vscroll set"]
+               scrollbar .f$cnr.vscroll -relief sunken \
+                       -command ".f$cnr.c yview"
+               scrollbar .f$cnr.hscroll -relief sunken -orient horiz \
+                       -command ".f$cnr.c xview"
+       } else {
+               set cv [canvas .f$cnr.c  -relief raised -bd 2\
+                       -scrollregion {-15c -5c 30c 40c} \
+                       -background $BG \
+                       -xscroll ".f$cnr.hscroll set" \
+                       -yscroll ".f$cnr.vscroll set"]
+               scrollbar .f$cnr.vscroll -relief sunken \
+                       -command ".f$cnr.c yview"
+               scrollbar .f$cnr.hscroll -relief sunken -orient horiz \
+                       -command ".f$cnr.c xview"
+       }
+       set Chandle($cnr) $cv
+       #-width 500 -height 500
+
+       button .f$cnr.b1 -text "Close" \
+               -command "set PlaceCanvas($m) [wm geometry .f$cnr]; destroy .f$cnr"
+       button .f$cnr.b2 -text "Save in: $m.ps" \
+               -command "$cv postscript -file $m.ps -colormode $Ptype"
+
+       pack append .f$cnr \
+               .f$cnr.vscroll {right filly} \
+               .f$cnr.hscroll {bottom fillx} \
+               .f$cnr.c {top expand fill}
+
+       if {$m == "msc"} {
+               set Sticky($cnr) 0
+               checkbutton .f$cnr.b6 -text "Preserve" \
+                       -variable Sticky($cnr) \
+                       -relief flat
+               pack append .f$cnr \
+                       .f$cnr.b6 { right padx 5}
+       }
+       pack append .f$cnr \
+               .f$cnr.b1 {right padx 5} \
+               .f$cnr.b2 {right padx 5}
+
+       bind $cv <2> "$cv scan mark %x %y"      ;# Geert Janssen, TUE
+       bind $cv <B2-Motion> "$cv scan dragto %x %y"
+
+       .f$cnr.c bind node <B1-Motion> "
+               moveNode $cnr \[.f$cnr.c find withtag current] %x %y 1
+       "
+
+#      .f$cnr.c bind node <B2-Motion> "
+#              moveNode $cnr \[.f$cnr.c find withtag current] %x %y 1
+#      "
+
+       tkwait visibility .f$cnr
+       return $cnr
+}
+
+proc addscales {p} {
+       global Chandle Scale
+
+       catch {
+               set cv $Chandle($p)
+               button .f$p.b4 -text "Larger" \
+                       -command "$cv scale all 0 0 1.1 1.1; set Scale [expr $Scale*1.1]"
+               button .f$p.b5 -text "Smaller" \
+                       -command "$cv scale all 0 0 0.9 0.9; set Scale [expr $Scale*0.9]"
+               pack append .f$p \
+                       .f$p.b4 {right padx 5} \
+                       .f$p.b5 {right padx 5}
+       }
+}
+
+proc dodot {n} {
+       global Edges edgeHead edgeTail NodeWidth NodeHeight Maxx Maxy
+       global State ELabel TransLabel Unix cnr lcnr Xrem Yrem DOT
+
+       add_log "<dot graph layout...>"
+       set fd [open "|$DOT" w+]
+
+       puts $fd "digraph dodot {"
+
+       foreach el [array names Edges] {
+               if { [ string first $n $el ] >= 0 } {
+               for {set i 0} { [lindex $Edges($el) $i] != "" } {incr i} {
+                       set ntrg [lindex $Edges($el) $i]
+                       puts $fd " \"$el\" -> \"$ntrg\"; "
+               }
+       }}
+
+       puts $fd "}"
+       flush $fd
+       set ends ""
+       set nodot 1
+       while {[gets $fd line] > -1} {
+               if {[string first "\}" $line] >= 0} {
+                       break;
+               }
+               set dd [string length $line]; incr dd -1
+               while {[string range $line $dd $dd] == "\\"} {
+                       gets $fd more
+                       set line "[string range $line 0 [expr $dd-1]]$more"
+                       set dd [string length $line]; incr dd -1
+               }
+               if {[string first " -> " $line] >= 0} {
+                       set a [string first "\[pos=\"" $line]; incr a 8
+                       set b [string first "\"\];" $line]; incr b -1
+                       set b2 [string first "->" $line]
+                       set line1 [string range $line 0 [expr $a - 9]]
+                       set src [string range $line1 0 [expr $b2 - 1]]
+                       set src [string trim $src "      \""]
+                       set trg [string range $line1 [expr $b2 + 3] [expr $a - 1]]
+                       set trg [string trim $trg "      \""]
+                       set tp [string range $line [expr $a-2] [expr $a-2]]
+                       set line [string range $line $a $b]
+                       set k [split $line " "]
+                       set j [llength $k]
+                       set j2 [trunc [expr $j/2]]
+                       set coords ".f$cnr.c create line "
+                       set spline "-smooth 1"
+                       set nl $ELabel($src,$trg)
+                       if {$tp == "e"} {
+                               set ends "last"
+                               for {set i 1} {$i < $j} {incr i} {
+                                       scan [lindex $k $i] "%d,%d" x y
+                                       set coords " $coords[expr 50 + $x] [expr 50 + $Maxy - $y] "
+                                       if {$i == $j2} {
+                                               .f$cnr.c coords \
+                                                       $TransLabel($State($src),$State($trg)) \
+                                                       [expr 50 + $x] [expr 50 + $Maxy - $y]
+                                               .f$cnr.c itemconfigure \
+                                                       $TransLabel($State($src),$State($trg)) \
+                                                       -fill black -text "$nl"
+                                       }
+                               }
+                               scan [lindex $k 0] "%d,%d" x y
+                               set coords " $coords[expr 50 + $x] [expr 50 + $Maxy - $y] "
+                       } else {
+                               set ends "first"
+                               for {set i 0} {$i < $j} {incr i} {
+                                       scan [lindex $k $i] "%d,%d" x y
+                                       set coords " $coords[expr 50 + $x] [expr 50 + $Maxy - $y] "
+                                       if {$i == $j2} {
+                                               .f$cnr.c coords \
+                                                       $TransLabel($State($src),$State($trg)) \
+                                                       [expr 50 + $x] [expr 50 + $Maxy - $y]
+                                               .f$cnr.c itemconfigure \
+                                                       $TransLabel($State($src),$State($trg)) \
+                                                       -fill black -text "$nl"
+                       }       }       }
+                       set coords "$coords -arrow $ends $spline -tags connector"
+
+                       set ne [eval $coords]
+                       set Xrem($ne) 10
+                       set Yrem($ne) 10
+
+                       continue
+               }
+               if {[string first "node " $line] >= 0 \
+               ||  [string first "\{" $line]    >= 0} {
+                       continue
+               }
+               if {[string first "graph " $line] >= 0} {
+                       set a [string first "\"" $line]; incr a
+                       set b [string last  "\"" $line]; incr b -1
+                       set line [string range $line $a $b]
+                       set k [split $line ","]
+                       if {[llength $k] == 4} {
+                               set Maxx [lindex $k 2]
+                               set Maxy [lindex $k 3]
+                       } else {
+                               set Maxx [lindex $k 0]
+                               set Maxy [lindex $k 1]
+                       }
+                       set nodot 0
+               } else {        ;# a node
+                       set a [string first "\[" $line]; incr a
+                       set b [string last  "\]" $line]; incr b -1
+                       set line1 [string range $line 0 [expr $a - 2]]
+                       set line  [string range $line $a $b]
+                       set nn [string trim $line1 "     \""]
+
+                       set a [string first "pos=" $line]; incr a 5
+                       set b [string first "\"" [string range $line $a end]]
+                       set b [expr $a + $b - 1]
+                       set line1  [string range $line $a $b]
+                       set k [split $line1 ","]
+                       set x [lindex $k 0]
+                       set y [lindex $k 1]
+
+                       set a [string first "width=" $line]; incr a 7
+                       set b [string first "\"" [string range $line $a end]]
+                       set b [expr $a + $b - 1]
+                       set w [expr 75 * [string range $line $a $b]]
+
+                       set a [string first "height=" $line]; incr a 8
+                       set b [string first "\"" [string range $line $a end]]
+                       set b [expr $a + $b - 1]
+                       set h [expr 75 * [string range $line $a $b]]
+
+               catch {
+                       set NodeWidth($State($nn)) [expr $w/2]
+                       set NodeHeight($State($nn)) [expr $h/2]
+                       moveNode $lcnr $State($nn) \
+                               [expr 50 + $x] [expr 50 + $Maxy - $y] 0
+               } err
+#puts $err
+               }
+       }
+       catch { close $fd }
+
+       if {$nodot} {
+               add_log "<cannot find dot>"
+               catch {
+               tk_messageBox -icon info -message "<cannot find dot>"
+               }
+               return
+       }
+
+       foreach el [array names Edges] {
+               if { [ string first $n $el ] >= 0 } {
+                       catch {
+                       foreach edge $edgeHead($State($el)) {
+                               .f$cnr.c delete $edge
+                       }
+                       unset edgeHead($State($el))
+                       unset edgeTail($State($el))
+                       }
+       }       }
+       .f$cnr.c bind node <B1-Motion> {}       ;# no moving
+       .f$cnr.c bind node <B2-Motion> {}
+       catch { destroy .f$lcnr.b6 }
+#      button .f$lcnr.b6 -text "No Labels" \
+#              -command ".f$lcnr.c delete texttag; destroy .f$lcnr.b6"
+       button .f$lcnr.b6 -text "No Labels" \
+               -command "hide_automata_labels .f$lcnr.b6 .f$cnr.c"
+       pack append .f$lcnr .f$lcnr.b6 {right padx 5}
+}
+
+proc hide_automata_labels {b c} {
+       $b configure -text "Add Labels"
+       $c itemconfigure texttag -fill white
+       $b configure -command "show_automata_labels $b $c"
+}
+
+proc show_automata_labels {b c} {
+       $b configure -text "No Labels"
+       $c itemconfigure texttag -fill black
+       $b configure -command "hide_automata_labels $b $c"
+}
+
+proc trunc {p} {
+       set foo [string first "." $p]
+       if {$foo >= 0} {
+               incr foo -1
+               set p [string range $p 0 $foo]
+       }
+       return $p
+}
+
+# Help menus
+
+proc aboutspin {} {
+       global FG BG HelvBig version xversion
+
+       catch {destroy .h}
+       toplevel .h
+
+       wm title .h "About SPIN"
+       wm iconname .h "About"
+       message .h.t -width 600 -background $BG -foreground $FG -font $HelvBig \
+       -text " $version
+Xspin Version $xversion
+
+Spin is an on-the-fly LTL model checking system
+for proving properties of asynchronous software
+system designs, first distributed in 1991.
+
+The master sources for the latest version of
+this software can always be found via:
+
+http://spinroot.com/spin/whatispin.html
+
+For help:  spin_list@spinroot.com
+
+The Spin sources are (c) 1990-2004 Bell Labs,
+Lucent Technologies, Murray Hill, NJ, USA.
+All rights are reserved. This software is for
+educational and research purposes only.
+No guarantee whatsoever is expressed or implied
+by the distribution of this code.
+"
+       button .h.b -text "Ok" -command {destroy .h}
+       pack append .h .h.t {top expand fill}
+       pack append .h .h.b {top}
+}
+
+proc promela {} {
+       global FG BG HelvBig
+
+       catch {destroy .h}
+       toplevel .h
+
+       wm title .h "Promela URL"
+       wm iconname .h "Promela"
+       message .h.t -width 600 -background $BG -foreground $FG -font $HelvBig \
+       -text "All Promela references are available online:
+
+http://spinroot.com/spin/Man/index.html
+
+"
+       button .h.b -text "Ok" -command {destroy .h}
+       pack append .h .h.t {top expand fill}
+       pack append .h .h.b {top}
+}
+
+proc helper {} {
+       global FG BG HelvBig
+
+       catch {destroy .h}
+       toplevel .h
+
+       wm title .h "Help with Xspin"
+       wm iconname .h "Help"
+       message .h.t -background $BG -foreground $FG -font $HelvBig \
+       -text "\
+Spin Version Controller - (c) 1993-2004 Bell Laboratories
+
+Enter a Promela model into the main text window, or 'Open'
+one via the File Menu (e.g., from Spin's Test directory).
+Once loaded, you can revert to the stored version of the file
+with option ReOpen.  Select Clear to empty the text window.
+
+In the log, just below the text-window, background
+commands are printed that Xspin generates.
+Outputs from Simulation and Verification runs always
+appear in separate windows.
+
+All run-time options are available through the Run menu.
+A typical way of working with Xspin is to use:
+
+- First a Syntax Check to get hints and warnings
+- Random Simulation for further debugging
+- Add the properties to be verified (assertions, never claims)
+- Perform a Slicing Check to check for redundancy
+- Perform Verification for a correctness proof
+- Guided Simulation to inspect errors reported by
+  the Verification option
+
+Clicking Button-1 in the main window updates the
+Line number display at the top of the window -- as a
+simple way of finding out at what line you are.
+
+You can also use another editor to update the
+specifications outside Xspin, and use the ReOpen
+command from the File menu to refresh the Xspin
+edit buffer before starting each new simulation or
+verification run."
+       button .h.b -text "Ok" -command {destroy .h}
+       pack append .h .h.t {top expand fill}
+       pack append .h .h.b {top}
+}
+
+# LTL interface
+
+set formula ""
+set tl_stat 0
+
+proc put_template {s} {
+       .tl.main.e1 delete 0 end
+       .tl.main.e1 insert end "$s"
+}
+
+set PlaceTL    "+100+1"
+
+proc call_tl {} {      ;# expanded interface
+       global formula tl_stat nv_typ an_typ cp_typ
+       global FG BG Fname firstime PlaceTL
+
+       catch {destroy .tl}
+       toplevel .tl
+
+       set k [string first "\+" $PlaceTL]
+       if {$k > 0} {
+               set PlaceTL [string range $PlaceTL $k end]
+       }
+
+       wm title .tl "Linear Time Temporal Logic Formulae"
+       wm iconname .tl "LTL"
+       wm geometry .tl $PlaceTL
+
+       frame .tl.main
+       entry .tl.main.e1 -relief sunken \
+               -background $BG -foreground $FG
+       label .tl.main.e2 -text "Formula: "
+
+       frame .tl.op
+       set alw {\[\] }
+       set eve {\<\> }
+       pack append .tl.op [label .tl.op.s0 -text "Operators: " \
+               -relief flat] {left}
+       pack append .tl.op [button .tl.op.always -width 1 -text "\[\]" \
+               -command ".tl.main.e1 insert insert \"$alw \""] {left}
+       pack append .tl.op [button .tl.op.event -width 1 -text "\<\>" \
+               -command ".tl.main.e1 insert insert \"$eve \""] {left}
+       pack append .tl.op [button .tl.op.until -width 1 -text "U" \
+               -command ".tl.main.e1 insert insert \" U \""] {left}
+       pack append .tl.op [button .tl.op.impl -width 1 -text "->" \
+               -command ".tl.main.e1 insert insert \" -> \""] {left}
+       pack append .tl.op [button .tl.op.and -width 1 -text "and" \
+               -command ".tl.main.e1 insert insert \" && \""] {left}
+       pack append .tl.op [button .tl.op.or -width 1 -text "or" \
+               -command ".tl.main.e1 insert insert \" || \""] {left}
+       pack append .tl.op [button .tl.op.not -width 1 -text "not" \
+               -command ".tl.main.e1 insert insert \" ! \""] {left}
+
+       frame .tl.b -relief ridge -borderwidth 4
+       label .tl.b.s0 -text "Property holds for: "
+       radiobutton .tl.b.s1 -text "All Executions (desired behavior)" \
+               -variable tl_stat -value 0
+       radiobutton .tl.b.s2 -text "No Executions (error behavior)" \
+               -variable tl_stat -value 1
+       pack append .tl.b \
+               .tl.b.s0 {left} \
+               .tl.b.s1 {left} \
+               .tl.b.s2 {left}
+
+       .tl.main.e1 insert end $formula
+
+       button .tl.main.file -text "Load..." \
+               -command "browse_tl"
+
+       bind .tl.main.e1 <Return> { do_ltl }
+
+       pack append .tl.main \
+               .tl.main.e2 {top left}\
+               .tl.main.e1 {top left expand fill} \
+               .tl.main.file {top right}
+
+       pack append .tl .tl.main {top fillx frame e}
+       pack append .tl .tl.op {top frame w}
+       pack append .tl .tl.b {top fillx frame w}
+
+       frame .tl.macros -relief ridge -borderwidth 4
+       label .tl.macros.title -text "Symbol Definitions:" -relief flat
+       scrollbar .tl.macros.s -relief flat \
+               -command ".tl.macros.t yview"
+       text .tl.macros.t -height 4 -relief raised -bd 2 \
+               -yscrollcommand ".tl.macros.s set" \
+               -background $BG -foreground $FG \
+               -setgrid 1 \
+               -wrap word
+
+       pack append .tl.macros \
+               .tl.macros.title {top frame w} \
+               .tl.macros.s {left filly} \
+               .tl.macros.t {left expand fill}
+
+       frame .tl.notes -relief ridge -borderwidth 4
+       label .tl.notes.title -text "Notes: " -relief flat
+       scrollbar .tl.notes.s -relief flat \
+               -command ".tl.notes.t yview"
+       text .tl.notes.t -height 4 -relief raised -bd 2 \
+               -yscrollcommand ".tl.notes.s set" \
+               -background $BG -foreground $FG \
+               -setgrid 1 \
+               -wrap word
+       pack append .tl.notes \
+               .tl.notes.title {top fillx frame w} \
+               .tl.notes.s {left filly} \
+               .tl.notes.t {left expand fill}
+
+       frame .tl.never
+       frame .tl.never.top
+       label .tl.never.top.title -text "Never Claim:"\
+                -relief flat
+       button .tl.never.top.gc -text "Generate" \
+               -command "do_ltl"
+       pack append .tl.never.top \
+               .tl.never.top.gc {right}\
+               .tl.never.top.title {left}
+
+       scrollbar .tl.never.s -relief flat \
+               -command ".tl.never.t yview"
+       text .tl.never.t -height 8 -relief raised -bd 2 \
+               -yscrollcommand ".tl.never.s set" \
+               -setgrid 1 \
+               -wrap word
+       pack append .tl.never \
+               .tl.never.top {top fillx frame w} \
+               .tl.never.s {left filly} \
+               .tl.never.t {left expand fill}
+
+       frame .tl.results
+       frame .tl.results.top
+
+       button .tl.results.top.svp -text "Run Verification" \
+               -command "do_ltl; basicval2"
+       label .tl.results.top.title -text "Verification Result:"\
+                -relief flat
+       pack append .tl.results.top \
+               .tl.results.top.svp {right}\
+               .tl.results.top.title {left}
+
+       scrollbar .tl.results.s -relief flat \
+               -command ".tl.results.t yview"
+       text .tl.results.t -height 7 -relief raised -bd 2 \
+               -yscrollcommand ".tl.results.s set" \
+               -setgrid 1 \
+               -wrap word
+       pack append .tl.results \
+               .tl.results.top {top fillx frame w} \
+               .tl.results.s {left filly} \
+               .tl.results.t {left expand fill}
+
+       pack append .tl \
+               .tl.notes {top expand fill} \
+               .tl.macros {top expand fill} \
+               .tl.never {top expand fill} \
+               .tl.results {top expand fill} \
+
+       pack append .tl [button .tl.sv -text "Save As.." \
+               -command "save_tl"] {right}
+       pack append .tl [button .tl.exit -text "Close" \
+       -command "set PlaceTL [wm geometry .tl]; destroy .tl"] {right}
+
+       pack append .tl [button .tl.help -text "Help" -fg red \
+               -command "roadmap4"] {left}
+       pack append .tl [button .tl.clear -text "Clear" \
+               -command ".tl.main.e1 delete 0 end; .tl.never.t delete 0.0 end"] {left}
+
+       loaddefault_tl
+       focus .tl.main.e1
+}
+
+proc purge_nvr {foo} {
+       set j [llength $foo]; incr j -1
+       for {set i $j} {$i >= 0} {incr i -1} {
+               set k [lindex $foo $i]
+               set kk [expr $k+1]
+               .tl.never.t delete $k.0 $kk.0
+       }
+}
+
+proc grab_nvr {inp target} {
+
+       set pattern $inp
+       scan [.tl.never.t index end] %d numLines
+       set foo {}
+       set yes 0
+
+       for {set i 1} {$i < $numLines} { incr i} {
+               .tl.never.t mark set last $i.0
+               set have [.tl.never.t get last "last lineend + 1 chars"]
+               if {[regexp -indices $pattern $have indices]} {
+                       lappend foo $i
+                       set yes [expr 1 - $yes]
+                       if {$yes} {
+                               set pattern "#endif"
+                       } else {
+                               set pattern $inp
+                       }
+               }
+               if {$yes && [string first $inp $have] != 0} {
+                       $target insert end "$have"
+                       lappend foo $i
+               }
+       }
+       purge_nvr $foo
+}
+
+proc extract_defs {} {
+       global tl_stat
+
+       set pattern "#define "
+       scan [.tl.never.t index end] %d numLines
+       set foo {}
+       set tl_stat 1
+       for {set i 1} {$i < $numLines} { incr i} {
+               .tl.never.t mark set last $i.0
+               set have [.tl.never.t get last "last lineend + 1 chars"]
+               if {[regexp -indices $pattern $have indices]} {
+                       .tl.macros.t insert end "$have"
+                       lappend foo $i
+               }
+               set have [.tl.never.t get last "last lineend"]
+               set k [string first "Formula As Typed: " $have]
+               if {$k > 0} {
+                       set ff [string range $have [expr $k+18] end]
+                       .tl.main.e1 insert end $ff
+               }
+               if {[string first "To The Negated Formula " $have] > 0} {
+                       set tl_stat 0
+               }
+       }
+       purge_nvr $foo
+
+       grab_nvr "#ifdef NOTES"  .tl.notes.t
+       grab_nvr "#ifdef RESULT" .tl.results.t
+}
+
+proc inspect_ltl {} {
+       global formula
+       set formula "[.tl.main.e1 get]"
+
+       set x $formula
+       regsub -all {\&\&} "$x" " " y; set x $y
+       regsub -all {\|\|} "$x" " " y; set x $y
+       regsub -all {\/\\} "$x" " " y; set x $y
+       regsub -all {\\\/} "$x" " " y; set x $y
+       regsub -all {\!}  "$x" " " y; set x $y
+       regsub -all {<->} "$x" " " y; set x $y
+       regsub -all {\->}  "$x" " " y; set x $y
+       regsub -all {\[\]} "$x" " " y; set x $y
+       regsub -all {\<\>} "$x" " " y; set x $y
+       regsub -all {[()]} "$x" " " y; set x $y
+       regsub -all {\ \ *} "$x" " " y; set x $y
+       regsub -all { U} "$x" " " y; set x $y
+       regsub -all { V} "$x" " " y; set x $y
+       regsub -all { X} "$x" " " y; set x $y
+
+       set predefs " np_ true false "
+
+       set k [split $x " "]
+       set j [llength $k]
+       set line [.tl.macros.t get 0.0 end]
+       for {set i 0} {$i < $j} {incr i} {
+               if {[string length [lindex $k $i]] > 0 \
+               &&  [string first " [lindex $k $i] " $predefs] < 0} {
+                 set pattern "#define [lindex $k $i]"
+                 if {[string first $pattern $line] < 0} {
+                       catch {
+                       .tl.macros.t insert end "$pattern\t?\n"
+                       }
+                       set line [.tl.macros.t get 0.0 end]
+       }       } }
+}
+
+proc do_ltl {} {
+       global formula tl_stat SPIN tk_major tk_minor
+
+       set formula "[.tl.main.e1 get]"
+       .tl.never.t delete 0.0 end
+       update
+
+       catch { inspect_ltl }
+
+       set MostSystems 1       ;# change to 0 only if there are problems
+                               ;# see below
+
+       if {$tl_stat == 0} {
+               add_log "$SPIN -f \"!( $formula )\""
+               if {$MostSystems} {
+                       catch {exec $SPIN -f "!($formula)" >&pan.ltl} err
+               } else {
+                       # this variant was needed on some older systems,
+                       # but it causes problems on some of the newer ones...
+                       catch {exec $SPIN -f \"!($formula)\" >&pan.ltl} err
+               }
+       } else {
+               add_log "$SPIN -f \"( $formula )\""
+               if {$MostSystems} {
+               catch {exec $SPIN -f "($formula)" >&pan.ltl} err
+               } else {
+               # see above
+               catch {exec $SPIN -f \"($formula)\" >&pan.ltl} err
+               }
+       }
+       set lno 0
+
+       if {$err != ""} {
+               add_log "<error: $err>"
+               add_log "hint: check the Help Button for syntax rules"
+       } else {
+               .tl.never.t insert end \
+               "       /*\n"
+               .tl.never.t insert end \
+               "        * Formula As Typed: $formula\n"
+               incr lno 2
+               if {$tl_stat == 0} {
+                       .tl.never.t insert end \
+                       "        * The Never Claim Below Corresponds\n"
+                       .tl.never.t insert end \
+                       "        * To The Negated Formula !($formula)\n"
+                       .tl.never.t insert end \
+                       "        * (formalizing violations of the original)\n"
+                       incr lno 3
+               }
+               .tl.never.t insert end \
+               "        */\n\n"
+               incr lno 2
+       }
+       catch {
+               set fd [open pan.ltl r]
+               while {[gets $fd line] > -1} {
+                       .tl.never.t insert end "$line\n"
+               }
+               close $fd
+       }
+       rmfile pan.ltl
+}
+
+proc dump_tl {bb} {
+
+       if {$bb != ""} {
+               set fnm $bb
+       } else {
+               set fnm [.sv_tl.ent get]
+       }
+
+       if {[file_ok $fnm]==0} return
+       set fd [open $fnm w]
+       add_log "<save claim in $fnm>"
+       catch { puts $fd "[.tl.macros.t get 0.0 end]" nonewline }
+
+       puts $fd "[.tl.never.t get 0.0 end]" nonewline
+
+       catch { puts $fd "#ifdef NOTES"
+               puts $fd "[.tl.notes.t get 0.0 end]" nonewline
+               puts $fd "#endif"
+       }
+       catch { puts $fd "#ifdef RESULT"
+               puts $fd "[.tl.results.t get 0.0 end]" nonewline
+               puts $fd "#endif"
+       }
+
+       catch "flush $fd"
+       catch "close $fd"
+       catch "destroy .sv_tl"
+       catch "focus .tl.main.e1"
+}
+
+proc save_tl {} {
+       global Fname PlaceWarn
+       catch {destroy .sv_tl}
+       toplevel .sv_tl
+
+       wm title .sv_tl "Save Claim"
+       wm iconname .sv_tl "Save"
+       wm geometry .sv_tl $PlaceWarn
+
+       label  .sv_tl.msg -text "Name for LTL File: " -relief flat
+       entry  .sv_tl.ent -width 6 -relief sunken -textvariable fnm
+       button .sv_tl.b1 -text "Ok" -command { dump_tl "" }
+       button .sv_tl.b2 -text "Cancel" -command "destroy .sv_tl"
+       bind   .sv_tl.ent <Return> { dump_tl "" }
+
+       set fnm [.sv_tl.ent get]
+       if {$fnm == ""} {
+               .sv_tl.ent insert end "$Fname.ltl"
+       }
+
+       pack append .sv_tl \
+               .sv_tl.msg {top frame w} \
+               .sv_tl.ent {top frame e expand fill} \
+               .sv_tl.b1 {right frame e} \
+               .sv_tl.b2 {right frame e}
+       focus .sv_tl.ent
+}
+
+proc add_tl {} {
+       global BG FG HelvBig PlaceWarn
+       catch {destroy .warn}
+       toplevel .warn
+       set k [string first "\+" $PlaceWarn]
+       if {$k > 0} {
+               set PlaceWarn [string range $PlaceWarn $k end]
+       }
+
+       wm title .warn "Accept"
+       wm iconname .warn "Accept"
+       wm geometry .warn $PlaceWarn
+
+       message .warn.t -width 300 \
+               -background $BG -foreground $FG -font $HelvBig \
+               -text " \
+Instructions:
+
+1. Save the Never Claim in a file, \
+for instance a file called 'never', \
+using the <Save> button.
+
+2. Insert the line
+
+#include \"never\"
+
+(the name of the file with the claim) \
+at the end of the main specification.
+
+3. Insert macro definitions (#define's) for all \
+propositional symbols used in the formula.
+
+For instance, with LTL formula
+'[] p -> <> q'  add the macro defs:
+
+#define p      (cnt == 1)
+#define q      (cnt > 1)
+
+These macros must be defined just above the line \
+with the #include \"never\" directive
+
+4. Perform the verification, and make sure that \
+the box 'Apply Never Claim' is checked in the \
+Verification Panel (or else the claim is ignored).
+You can have a library of claim files that you can \
+choose from for verification, by changing only the \
+name of the include file.
+
+5. Never claims have no effect during simulation runs.
+
+6. See the HELP->LTL menu for more information.
+
+"
+       button .warn.b -text "Ok" \
+               -command {set PlaceWarn [wm geometry .warn]; destroy .warn}
+       pack append .warn .warn.t {top expand fill}
+       pack append .warn .warn.b {right frame e}
+}
+
+proc roadmap4 {} {
+       global FG BG
+
+       catch {destroy .h}
+       toplevel .h
+
+       wm title .h "LTL Help"
+       wm iconname .h "Help"
+       frame .h.z
+       scrollbar .h.z.s -command ".h.z.t yview"
+       text .h.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".h.z.s set" \
+               -setgrid 1 -width 60 -height 30 -wrap word
+       pack append .h.z \
+               .h.z.s {left filly} \
+               .h.z.t {left expand fill}
+       .h.z.t insert end "GUIDELINES:
+You can load an LTL template or a previously saved LTL
+formula from a file via the LOAD button on the upper
+right of the LTL Property Manager panel.
+
+Define a new LTL formula using lowercase names for the
+propositional symbols, for instance:
+       [] (p U q)
+The formula expresses either a positive (desired) or a
+negative (undesired) property of the model.  A positive
+property is negated automatically by the translator to
+convert it in a never claim (which expresses the
+corresponding negative property (the undesired behavior
+that is claimed 'never' to occur).
+
+When you type a <Return> or hit the <Generate> button,
+the formula is translated into an equivalent never-claim.
+
+You must add a macro-definition for each propositional
+symbol used in the LTL formula.  Insert these definitions
+in the symbols window of the LTL panel, they will be
+remembered together with the annotations and verification
+result if the formula is saved in an .ltl file.
+Enclose the symbol definitions in braces, to secure correct
+operator precedence, for instance:
+
+#define p      (a > b)
+#define q      (len(q) < 5)
+
+Valid temporal logic operators are:
+       \[\]  Always (no space between \[ and \])
+       <>  Eventually (no space between < and >)
+       U   (Strong) Until
+       V   The Dual of Until: (p V q) == !(!p U !q)
+
+       All operators are left-associative (incl. U and V).
+
+Boolean Operators:
+       &&  Logical And (alternative form: /\\, no spaces)
+       !   Logical Negation
+       ||  Logical Or  (alternative form: \\/, no spaces)
+       ->  Logical Implication
+       <-> Logical Equivalence
+
+Boolean Predicates:
+       true, false
+       any name that starts with a lowercase letter
+
+Examples:
+       \[\] p
+       !( <> !q )
+       p U q
+       p U (\[\] (q U r))
+
+Generic properties/Templates:
+       Invariance: \[\] p
+       Response:   p -> \<\> q
+       Precedence: p -> (q U r)
+       Objective:  p -> \<\> (q || r)
+
+       Each of the above 4 generic types of properties
+       can (and will generally have to) be prefixed by
+       temporal operators such as
+               \[\], \<\>, \[\]\<\>, \<\>\[\]
+       The last (objective) property can be read to mean
+       that 'p' is a trigger, or 'enabling' condition that
+       determines when the requirement becomes applicable
+       (e.g. the sending of a new data message); then 'q'
+       can be the fullfillment of the requirement (e.g.
+       the arrival of the matching acknowledgement), and
+       'r' could be a discharging condition that voids the
+       applicability of the check (an abort condition).
+"
+       button .h.b -text "Ok" -command {destroy .h}
+       pack append .h .h.z {top expand fill}
+       pack append .h .h.b {top}
+       .h.z.t configure -state disabled 
+       .h.z.t yview -pickplace 1.0      
+       focus .h.z.t
+}
+
+
+
+# Specific Help
+
+proc roadmap1 {} {
+       global FG BG
+
+       catch {destroy .road1}
+       toplevel .road1
+
+       wm title .road1 "Help with Simulation"
+       wm iconname .road1 "SimHelp"
+       frame .road1.z
+       scrollbar .road1.z.s -command ".road1.z.t yview"
+       text .road1.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road1.z.s set" \
+               -setgrid 1 -width 60 -height 30 -wrap word
+       pack append .road1.z \
+               .road1.z.s {left filly} \
+               .road1.z.t {left expand fill}
+       .road1.z.t insert end "GUIDELINES:
+0.  Always use a Syntax Check before running simulations.\
+It shakes out the more obvious flaws in the model.
+
+1.  Random simulation option is used to debug a model.\
+Other than assert statements, no correctness requirements\
+are checked during simulation runs. All nondeterministic\
+decisions are resolved randomly.  You can of course still\
+force a selection to go into a specific direction by \
+modifying the model.\
+A random run is repeated precisely if the Seed Value\
+for the random number generator is kept the same.
+
+2.  Interactive simulation can be used to force the\
+execution towards a known point.  The user is prompted\
+at every point in the execution where a nondeterministic\
+choice has to be resolved.
+
+3.  A guided simulation is used to follow an error-trail that was\
+produced by the verifier.  If the trail gets to be thousands of execution\
+steps long, this can be time-consuming. \
+You can skip the initial portion of such a long trail by typing\
+a number in  the 'Steps Skipped' box in the Simulation Panel .
+
+4. The options in the Simulations Panel allow you to enable or\
+disable types of displays that are maintained during simulation\
+runs.  Usually, it is not necessary to look at all possible display panels.\
+Experiment to see which displays you find most useful.
+
+5. To track the value changes of Selected variables, in the\
+Message Sequence Chart and in the Variable Values Panel, add a prefix\
+'show ' to the declaration of the selected variables in the Promela\
+specification, e.g. use 'show byte cnt;' instead of 'byte cnt;'"
+
+       button .road1.b -text "Ok" -command {destroy .road1}
+       pack append .road1 .road1.z {top expand fill}
+       pack append .road1 .road1.b {top}
+       .road1.z.t configure -state disabled 
+       .road1.z.t yview -pickplace 1.0      
+       focus .road1.z.t
+}
+
+proc roadmap2a {} {
+       global FG BG
+
+       catch {destroy .road2}
+       toplevel .road2
+
+       wm title .road2 "Help with Verification Parameters"
+       wm iconname .road2 "ValHelp"
+       frame .road2.z
+       scrollbar .road2.z.s -command ".road2.z.t yview"
+       text .road2.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road2.z.s set" \
+               -setgrid 1 -width 60 -height 18 -wrap word
+       pack append .road2.z \
+               .road2.z.s {left filly} \
+               .road2.z.t {left expand fill}
+       .road2.z.t insert end "Physical Memory Available:
+Set this number to amount of physical (not virtual)
+memory in your system, in MegaBytes, and leave it there for all runs.
+
+When the limit is reached, the verification is stopped to
+avoid trashing.
+
+The number entered here is the number of MegaBytes directly
+(not a power of two, as in previous versions of xspin).
+
+If an exhaustive verification cannot be completed due to
+lack of memory, use compression, or switch to a
+supertrace/bitstate run under basic options."
+
+       button .road2.b -text "Ok" -command {destroy .road2}
+       pack append .road2 .road2.z {top expand fill}
+       pack append .road2 .road2.b {top}
+       .road2.z.t configure -state disabled 
+       .road2.z.t yview -pickplace 1.0      
+       focus .road2.z.t
+}
+proc roadmap2b {} {
+       global FG BG
+
+       catch {destroy .road2}
+       toplevel .road2
+
+       wm title .road2 "Help with Verification"
+       wm iconname .road2 "ValHelp"
+       frame .road2.z
+       scrollbar .road2.z.s -command ".road2.z.t yview"
+       text .road2.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road2.z.s set" \
+               -setgrid 1 -width 60 -height 15 -wrap word
+       pack append .road2.z \
+               .road2.z.s {left filly} \
+               .road2.z.t {left expand fill}
+       .road2.z.t insert end "Estimated State Space Size:
+This parameter is used to calculate the size of the
+hash-table. It results in a selection of a numeric argument
+for the -w flag of the verifier. Setting it too high may
+cause an out-of-memory error with zero states reached
+(meaning that the verification could not be started).
+Setting it too low can cause inefficiencies due to
+hash collisions.
+
+In Bitstate runs begin with the default estimate for
+this parameter.  After a run completes successfully,
+double the estimate, and see if the number of reached
+stated changes much.  Continue to do this until
+it stops changing, or until you overflow the memory
+bound and run out of memory.
+
+The closest power of two is taken by xspin to set the
+true number used for the number of reachable states.
+(The selected power of two is visible as the number that
+follow the -w flag in the run-line that xspin generates).
+
+To set a specific -w parameter, use the Extra Run-Time Option
+Field. If, for instance, -w32 is specified there, it will
+override the value computed from the Estimated State Space Size."
+
+       button .road2.b -text "Ok" -command {destroy .road2}
+       pack append .road2 .road2.z {top expand fill}
+       pack append .road2 .road2.b {top}
+       .road2.z.t configure -state disabled 
+       .road2.z.t yview -pickplace 1.0      
+       focus .road2.z.t
+}
+proc roadmap2c {} {
+       global FG BG
+
+       catch {destroy .road2}
+       toplevel .road2
+
+       wm title .road2 "Help with Verification"
+       wm iconname .road2 "ValHelp"
+       frame .road2.z
+       scrollbar .road2.z.s -command ".road2.z.t yview"
+       text .road2.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road2.z.s set" \
+               -setgrid 1 -width 60 -height 20 -wrap word
+       pack append .road2.z \
+               .road2.z.s {left filly} \
+               .road2.z.t {left expand fill}
+       .road2.z.t insert end "Maximum Search Depth:
+This number determines the size of the depth-first
+search stack that is used during the verification.
+The stack uses memory, so a larger number increases
+the memory requirements, and a lower number decreases
+it.  In a tight spot, when there seems not to be
+sufficient memory for the search depth needed, you
+can reduce the estimated state space size to free some
+more memory for the stack.
+
+If you hit the maximum search depth during a verification
+(noted as 'Search not completed' or 'Search Truncated'
+in the verification output) without finding an error,
+double the search depth parameter and repeat the run."
+
+       button .road2.b -text "Ok" -command {destroy .road2}
+       pack append .road2 .road2.z {top expand fill}
+       pack append .road2 .road2.b {top}
+       .road2.z.t configure -state disabled 
+       .road2.z.t yview -pickplace 1.0      
+       focus .road2.z.t
+}
+
+proc roadmap2k {} {
+       global FG BG
+
+       catch {destroy .road2}
+       toplevel .road2
+
+       wm title .road2 "Help with Verification"
+       wm iconname .road2 "ValHelp"
+       frame .road2.z
+       scrollbar .road2.z.s -command ".road2.z.t yview"
+       text .road2.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road2.z.s set" \
+               -setgrid 1 -width 60 -height 10 -wrap word
+       pack append .road2.z \
+               .road2.z.s {left filly} \
+               .road2.z.t {left expand fill}
+       .road2.z.t insert end "Number of hash functions:
+This number determines how many bits are set per
+state when in Bitstate verification mode. The default is 2.
+At the end of a Bitstate verification run, the verifier
+can issue a recommendation for a different setting of
+this flag (which is the -k flag), it a change can be
+predicted to lead to better coverage."
+
+       button .road2.b -text "Ok" -command {destroy .road2}
+       pack append .road2 .road2.z {top expand fill}
+       pack append .road2 .road2.b {top}
+       .road2.z.t configure -state disabled 
+       .road2.z.t yview -pickplace 1.0      
+       focus .road2.z.t
+}
+
+proc roadmap2d {} {
+       global FG BG
+
+       catch {destroy .road2}
+       toplevel .road2
+
+       wm title .road2 "Help with Verification"
+       wm iconname .road2 "ValHelp"
+       frame .road2.z
+       scrollbar .road2.z.s -command ".road2.z.t yview"
+       text .road2.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road2.z.s set" \
+               -setgrid 1 -width 60 -height 26 -wrap word
+       pack append .road2.z \
+               .road2.z.s {left filly} \
+               .road2.z.t {left expand fill}
+       .road2.z.t insert end "GENERAL GUIDELINES:
+=> When just starting out, it is safe to leave all parameters in the\
+Verification Options Panel set at their initial value and to simply\
+push the Run button in the Basic Options Panel for a default\
+exhaustive verification.\
+If you run out of memory, adjust the parameter settings as \
+indicated under the 'explain' options.
+
+=> If an error is found, first try to reduce the search depth to \
+find a shorter equivalent.  Once you're content with the length,\
+move on to a guided simulation to inspect the error-trail in detail.\
+Optionally, use the Find Shortest Trail option, but note that this\
+can increase runtime and memory use. So: do not use this option until\
+you are certain that an error exists -- leave it turned off by default).\
+If you are verifying a Safety Property, try the Breadth-First Search\
+mode to find the shortest counter-example. It may run out of memory\
+sooner than the default depth-first search mode, but it often works.
+
+=> It is always safe to leave the Partial Order Reduction option enabled.\
+Turn it off only for debugging purposes, or when warned to do so by the \
+verifier itself.  The Profiling option gathers statistics about the \
+verification hot-spots in the model.
+
+=> If you save all error-trails, you have to copy the one you are\
+interested in inspecting with a guided simulation onto the file\
+pan_in.trail manually (outside xspin) after the run completes.\
+The trails are numbered in order of discovery."
+
+       button .road2.b -text "Ok" -command {destroy .road2}
+       pack append .road2 .road2.z {top expand fill}
+       pack append .road2 .road2.b {top}
+       .road2.z.t configure -state disabled 
+       .road2.z.t yview -pickplace 1.0      
+       focus .road2.z.t
+}
+
+proc roadmap2e {} {
+       global FG BG
+
+       catch {destroy .road2}
+       toplevel .road2
+
+       wm title .road2 "Help with Verification"
+       wm iconname .road2 "ValHelp"
+       frame .road2.z
+       scrollbar .road2.z.s -command ".road2.z.t yview"
+       text .road2.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road2.z.s set" \
+               -setgrid 1 -width 60 -height 25 -wrap word
+       pack append .road2.z \
+               .road2.z.s {left filly} \
+               .road2.z.t {left expand fill}
+       .road2.z.t insert end "BASIC GUIDELINES:
+When just starting out, it is safe to leave all parameters\
+at their initial value and to push the Run button for a\
+default exhaustive verification.\
+If you run out of memory, adjust the parameter settings\
+under Advanced Options.
+
+=> Safety properties are properties of single states (like\
+deadlocks = invalid endstates, or assertion violations).
+
+=> Liveness properties are properties of sequences of\
+states (typically: infinite sequences, i.e., cycles).\
+There are two types of cycles: non-progress (not passing\
+through any state marked with a 'progress' label) and\
+acceptance (passing infinitely often through a state\
+marked with an 'accept' label).
+
+=> Use the Weak Fairness option only when really necessary,\
+to avoid unwated error reports.  It can increase the CPU-time\
+requirements by a factor roughly equal to twice the number of\
+active processes.
+
+=> It is safe to leave the Reduced Search option enabled.\
+Turn it off only for debugging purposes, or when warned to do so by the \
+verifier itself.   The Profiling option gathers statistics about the \
+verification hot-spots in the model.
+
+=> You can apply a Never Claim even when checking Safety Properties\
+when you want to restrict the search to the sequences that are\
+matched by the claim (a user-guided search pruning technique)."
+
+       button .road2.b -text "Ok" -command {destroy .road2}
+       pack append .road2 .road2.z {top expand fill}
+       pack append .road2 .road2.b {top}
+       .road2.z.t configure -state disabled 
+       .road2.z.t yview -pickplace 1.0      
+       focus .road2.z.t
+}
+
+proc roadmap2f {} {
+       global FG BG
+
+       catch {destroy .road2}
+       toplevel .road2
+
+       wm title .road2 "Help with Verification"
+       wm iconname .road2 "ValHelp"
+       frame .road2.z
+       scrollbar .road2.z.s -command ".road2.z.t yview"
+       text .road2.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road2.z.s set" \
+               -setgrid 1 -width 60 -height 15 -wrap word
+       pack append .road2.z \
+               .road2.z.s {left filly} \
+               .road2.z.t {left expand fill}
+       .road2.z.t insert end "GUIDELINES:
+This will run a verification for the specific LTL property\
+that was defined in the LTL options panel that brought you\
+here.  The claim was placed in a separate .ltl\
+file, not included in the main specification.\
+(It will be picked up in the verification automatically.)\
+The separate .ltl file combines the notes, formula,\
+macros, results, etc., for easier tracking.
+
+On a first run, leave all choices at their initial\
+value and push the Run button for a default verification.\
+If you run out of memory, adjust the parameter settings\
+under Advanced Options.
+
+Use the Weak Fairness option only when really necessary,\
+to avoid unwated error reports.  It can increase the CPU-time\
+requirements by a factor roughly equal to twice the number of\
+active processes."
+
+       button .road2.b -text "Ok" -command {destroy .road2}
+       pack append .road2 .road2.z {top expand fill}
+       pack append .road2 .road2.b {top}
+       .road2.z.t configure -state disabled 
+       .road2.z.t yview -pickplace 1.0      
+       focus .road2.z.t
+}
+
+proc roadmap2 {} {
+       global FG BG
+
+       catch {destroy .road2}
+       toplevel .road2
+
+       wm title .road2 "Help with Verification"
+       wm iconname .road2 "ValHelp"
+       frame .road2.z
+       scrollbar .road2.z.s -command ".road2.z.t yview"
+       text .road2.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road2.z.s set" \
+               -setgrid 1 -width 60 -height 20 -wrap word
+       pack append .road2.z \
+               .road2.z.s {left filly} \
+               .road2.z.t {left expand fill}
+       .road2.z.t insert end "GUIDELINES:
+When just starting out, it is safe to leave all
+verification parameters set at their initial values
+and to Run a default verification.
+If you run out of memory, or encounter other problems,
+look at the specific help options in the verification
+settings panel.
+One parameter is important to set correctly right from
+the start: the physical memory size of your system.
+It is by default set to 64 Mbytes.  Set it once to the
+true amount of physical memory on your system, in Megabytes,
+and never change it again (unless you buy more physical
+memory for your machine of course).
+You can find this parameter under advanced options in the
+verification parameters panel.
+Bitstate/Supertrace verifications are approximate, and
+only used for models too large to verify exhaustively.
+This option allows you to get at least an approximate
+answer to the correctness of models that could otherwise
+not be verified by a finite state system."
+
+       button .road2.b -text "Ok" -command {destroy .road2}
+       pack append .road2 .road2.z {top expand fill}
+       pack append .road2 .road2.b {top}
+       .road2.z.t configure -state disabled 
+       .road2.z.t yview -pickplace 1.0      
+       focus .road2.z.t
+}
+
+proc roadmap3 {} {
+       global FG BG
+
+       catch {destroy .road3}
+       toplevel .road3
+
+       wm title .road3 "Reducing Complexity"
+       wm iconname .road3 "CompHelp"
+       frame .road3.z
+       scrollbar .road3.z.s -command ".road3.z.t yview"
+       text .road3.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road3.z.s set" \
+               -setgrid 1 -width 60 -height 30 -wrap word
+       pack append .road3.z \
+               .road3.z.s {left filly} \
+               .road3.z.t {left expand fill}
+       .road3.z.t insert end "
+When a verification cannot be completed because of\
+computational complexity; here are some strategies that\
+can be applied to combat this problem.
+
+0. Run the Slicing Algorithm (in the Run Menu) to find\
+potential redundancy in your model for the stated properties.
+
+1. Try to make the model more general, more abstract.\
+Remember that you are constructing a verification model and not\
+an implementation.  SPIN's strength is in proving properties of\
+*interactions* in a distributed system (the implicit assumptions\
+that processes make about each other) -- it's strength is not in\
+proving things about local *computations*, data dependencies etc.
+
+2. Remove everything that is not directly related to the property\
+you are trying to prove: redundant computations, redundant data. \
+*Avoid counters*; avoid incrementing variables that are used for\
+only book-keeping purposes.
+The Syntax Check option will warn about the gravest offenses.
+
+3. Asynchronous channels are a significant source of complexity in\
+verification.  Use a synchronous channel where possible.  Reduce the\
+number of slots in asynchronous channels to a minimum (use 2, or 3\
+slots to get started).
+
+4. Look for processes that merely transfer messages. Consider if\
+you can remove processes that only copy incoming messages from\
+one channel into another, by letting the sender generate the\
+final message right away.  If the intermediate process makes\
+choices (e.g., to delete or duplicate, etc.), let the sender\
+make that choice, rather than the intermediate process.
+
+5. Combine local computations into atomic, or d_step, sequences.
+
+6. Avoid leaving scratch data around in variables.  You can reduce\
+the number of states by, for instance, resetting local variables\
+that are used inside atomic sequences to zero at the end of those\
+sequences; so that the scratch values aren't visible outside the\
+sequence.  Alternatively: introduce some extra global 'hidden'\
+variables for these purposes (see the WhatsNew.html document).
+Use the predefined variable \"_\" as a write-only scratch variable\
+wherever possible.
+
+7. If possible to do so: combine the behavior of two processes into\
+a single one.  Generalize behavior;  focus on coordination aspects\
+(i.e., the interfaces between processes, rather than the local\
+computation inside processes).
+
+8. Try to exploit the partial order reduction strategies.\
+Use the xr and xs assertions (see WhatsNew.html); avoid sharing\
+channels between multiple receivers or multiple senders.\
+Avoid merging independent data-streams into a single shared channel."
+
+       button .road3.b -text "Ok" -command {destroy .road3}
+       pack append .road3 .road3.z {top expand fill}
+       pack append .road3 .road3.b {top}
+       .road3.z.t configure -state disabled 
+       .road3.z.t yview -pickplace 1.0      
+       focus .road3.z.t
+}
+
+proc roadmap5 {} {
+       global FG BG
+
+       catch {destroy .road5}
+       toplevel .road5
+
+       wm title .road5 "Spin Automata"
+       wm iconname .road5 "FsmHelp"
+       frame .road5.z
+       scrollbar .road5.z.s -command ".road5.z.t yview"
+       text .road5.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road5.z.s set" \
+               -setgrid 1 -width 60 -height 30 -wrap word
+       pack append .road5.z \
+               .road5.z.s {left filly} \
+               .road5.z.t {left expand fill}
+       .road5.z.t insert end "
+The Spin Automata view option give a view of the
+structure of the automata models that Spin uses in
+the verification process.
+Each proctype is represented by a unique automaton.
+
+Chosing this option (in the Run menu) will cause Spin to
+first generate a verifier, compile it, and then run it
+(as pan -d) to obtain a description of the proctype
+names and the corresponding automata.
+
+After selecting (double-clicking) the proctype name desired,
+the graph will be produced.  The default graph layout
+algorithm is small and a self-contained part of Xspin,
+but also rather crude.  Be on guard, therefore, for edges
+that overlap (a typical case, for instance, is a backedge
+that hides behind a series of forward edges. Use DOT
+(see the README.html file on Spin) when possible for much
+better graph layout.
+
+In the default layout, the following button actions are
+defined (the first one is not needed when using DOT):
+
+1. Moving Nodes: either Button-1 or Button-2.
+2. Displaying Edge Labels: hold Button-1 down on the edge.
+3. Cross-References: Move the cursor over a Node to see the
+   corresponding line in the Promela source, in the main
+   Xspin window.
+
+If labels look bad -- try changing the font definitions at
+the start of the xspin.tcl file (hints are given there).
+"
+       button .road5.b -text "Ok" -command {destroy .road5}
+       pack append .road5 .road5.z {top expand fill}
+       pack append .road5 .road5.b {top}
+       .road5.z.t configure -state disabled 
+       .road5.z.t yview -pickplace 1.0      
+       focus .road5.z.t
+}
+
+proc roadmap6 {} {
+       global FG BG
+
+       catch {destroy .road6}
+       toplevel .road6
+
+       wm title .road6 "Optional Compiler Directives"
+       wm iconname .road6 "Optional"
+       frame .road6.z
+       scrollbar .road6.z.s -command ".road6.z.t yview"
+       text .road6.z.t -relief raised -bd 2 \
+               -background $BG -foreground $FG \
+               -yscrollcommand ".road6.z.s set" \
+               -setgrid 1 -width 80 -height 30 -wrap word
+       pack append .road6.z \
+               .road6.z.s {left filly} \
+               .road6.z.t {left expand fill}
+       .road6.z.t insert end "
+               Use only when prompted:
+
+NFAIR=N                size memory used for enforcing weak fairness (default N=2)
+VECTORSZ=N     allocates memory (in bytes) for state vector (default N=1024)
+
+               Related to partial order reduction:
+
+CTL            limit p.o.reduction to subset consistent with branching time logic
+GLOB_ALPHA     consider process death a global action
+XUSAFE         disable validity checks of xr/xs assertions
+
+               Speedups:
+
+NOBOUNDCHECK   don't check array bound violations
+NOCOMP         don't compress states with fullstate storage (uses more memory)
+NOSTUTTER      disable stuttering rules (warning: changes semantics)
+
+               Memory saving (slower):
+
+MA=N           use a minimized DFA encoding for state vectors up to N bytes
+
+               Experimental:
+
+BCOMP          when in BITSTATE mode, computes hash over compressed state-vector
+NIBIS          apply a small optimization of partial order reduction
+NOVSZ          risky - removes 4 bytes from state vector - its length field.
+PRINTF         enables printfs during verification runs
+RANDSTORE=N    in BITSTATE mode, -DRANDSTORE=33 lowers prob of storing a state to 33%
+W_XPT=N                with MA, write checkpoint files every multiple of N states stored
+R_XPT          with MA, restart run from last checkpoint file written
+
+               Debugging:
+
+SDUMP          with CHECK: adds ascii dumps of state vectors
+SVDUMP         add run option -pN to write N-byte state vectors into file sv_dump
+
+               Already set by the other xspin options:
+
+BITSTATE       use supertrace/bitstate instead of exhaustive exploration
+HC             use hash-compact instead of exhaustive exploration
+COLLAPSE       collapses state vector size by up to 80% to 90%
+MEMCNT=N       set upperbound of 2^N bytes to memory that can be allocated
+MEMLIM=N       set upperbound of N Mbytes to memory that can be allocated
+NOCLAIM                exclude never claim from the verification, if present
+NOFAIR         disable the code for weak-fairness (is faster)
+NOREDUCE       disables the partial order reduction algorithm
+NP             enable non-progress cycle detection (option -l, replacing -a),
+PEG            add complexity profiling (transition counts)
+REACH          guarantee absence of errors within the -m depth-limit
+SAFETY         optimize for the case where no cycle detection is needed
+VAR_RANGES     compute the effective value range of byte variables
+CHECK          generate debugging information (see also below)
+VERBOSE                elaborate debugging printouts
+"
+       button .road6.b -text "Ok" -command {destroy .road6}
+       pack append .road6 .road6.z {top expand fill}
+       pack append .road6 .road6.b {top}
+       .road6.z.t configure -state disabled 
+       .road6.z.t yview -pickplace 1.0      
+       focus .road6.z.t
+}
+
+
+# simulation options panel
+
+set s_options  ""
+set v_options  ""
+set a_options  ""
+set c_options  ""
+
+set Blue       "blue";         #"yellow"
+set Yellow     "yellow";       #"red"
+set White      "white";        #"yellow"
+set Red                "red";          #"yellow"
+set Green      "green";        #"green"
+
+set fd         0
+set Depth      0
+set Seq(0)     0
+set Sdbox      0
+set Spbox(0)   0
+set sbox       0
+
+set simruns    0
+set stepper    0
+set stepped    0
+set VERBOSE    0
+set SYMBOLIC   0
+set howmany    0
+set Choice(1)  0
+set Sticky(0)  0
+set SparseMsc  1
+set showvars   1
+set vv         1
+set qv         1
+set gvars      1
+set lvars      0
+set hide_q1    ""
+set hide_q2    ""
+set hide_q3    ""
+set PlaceSim   "+200+100"
+
+proc simulation_old {} {
+       global s_typ l_typ showvars qv PlaceSim
+       global fvars gvars lvars SparseMsc HelvBig
+       global msc ebc tsc vv svars rvars seed jumpsteps
+       global hide_q1 hide_q2 hide_q3
+
+       catch { .menu.run.m entryconfigure 5 -state normal }
+
+       catch {destroy .s}
+       toplevel .s
+       set k [string first "\+" $PlaceSim]
+       if {$k > 0} {
+               set PlaceSim [string range $PlaceSim $k end]
+       }
+
+       wm title .s "Simulation Options"
+       wm iconname .s "SIM"
+       wm geometry .s $PlaceSim
+
+       frame .s.opt -relief flat
+
+       mkpan_in
+
+       frame .s.opt.mode -relief raised -borderwidth 1m
+       label .s.opt.mode.fld0 \
+               -font $HelvBig \
+               -text "Display Mode" \
+               -relief sunken -borderwidth 1m
+
+       checkbutton .s.opt.mode.fld4b -text "Time Sequence Panel - with:" \
+               -variable tsc \
+               -relief flat
+       frame .s.opt.mode.flds
+       radiobutton .s.opt.mode.flds.fld3 \
+               -text "    Interleaved Steps" \
+               -variable m_typ -value 2 \
+               -relief flat
+       radiobutton .s.opt.mode.flds.fld1 \
+               -text "    One Window per Process" \
+               -variable m_typ -value 0 \
+               -relief flat
+       radiobutton .s.opt.mode.flds.fld2 \
+               -text "    One Trace per Process" \
+               -variable m_typ -value 1 \
+               -relief flat
+       frame .s.opt.mode.flds.fld0 -width 15
+       pack append .s.opt.mode.flds \
+               .s.opt.mode.flds.fld0 {left frame w}\
+               .s.opt.mode.flds.fld3 {top frame w}\
+               .s.opt.mode.flds.fld1 {top frame w}\
+               .s.opt.mode.flds.fld2 {top frame w}
+
+       checkbutton .s.opt.mode.fld4a -text "MSC Panel - with:" \
+               -variable msc \
+               -relief flat
+       frame .s.opt.mode.steps
+       radiobutton .s.opt.mode.steps.fld5 -text "    Step Number Labels" \
+               -variable SYMBOLIC -value 0 \
+               -relief flat
+       radiobutton .s.opt.mode.steps.fld6 -text "    Source Text Labels" \
+               -variable SYMBOLIC -value 1 \
+               -relief flat
+       radiobutton .s.opt.mode.steps.fld7 -text "    Normal Spacing" \
+               -variable SparseMsc -value 1 \
+               -relief flat
+       radiobutton .s.opt.mode.steps.fld8 -text "    Condensed Spacing" \
+               -variable SparseMsc -value 0 \
+               -relief flat
+       frame .s.opt.mode.steps.fld0 -width 15
+       pack append .s.opt.mode.steps \
+               .s.opt.mode.steps.fld0 {left frame w}\
+               .s.opt.mode.steps.fld5 {top frame w}\
+               .s.opt.mode.steps.fld6 {top frame w}\
+               .s.opt.mode.steps.fld7 {top frame w}\
+               .s.opt.mode.steps.fld8 {top frame w}
+
+       checkbutton .s.opt.mode.fld4c -text "Execution Bar Panel" \
+               -variable ebc \
+               -relief flat
+       checkbutton .s.opt.mode.fld4d -text "Data Values Panel" \
+               -variable vv \
+               -relief flat
+
+       frame .s.opt.mode.vars
+
+       checkbutton .s.opt.mode.vars.fld4c -text "    Track Buffered Channels" \
+               -variable qv \
+               -relief flat
+       checkbutton .s.opt.mode.vars.fld4d -text "    Track Global Variables" \
+               -variable gvars \
+               -relief flat
+       checkbutton .s.opt.mode.vars.fld4e -text "    Track Local Variables" \
+               -variable lvars \
+               -relief flat
+
+       checkbutton .s.opt.mode.vars.fld4f \
+               -text "    Display vars marked 'show' in MSC" \
+               -variable showvars \
+               -relief flat
+       frame .s.opt.mode.vars.fld0 -width 15
+       pack append .s.opt.mode.vars \
+               .s.opt.mode.vars.fld0 {left frame w}\
+               .s.opt.mode.vars.fld4c {top frame w}\
+               .s.opt.mode.vars.fld4d {top frame w}\
+               .s.opt.mode.vars.fld4e {top frame w}\
+               .s.opt.mode.vars.fld4f {top frame w}
+
+       pack append .s.opt.mode .s.opt.mode.fld0 {top pady 4 frame w fillx}
+
+       pack append .s.opt.mode .s.opt.mode.fld4a {top pady 4 frame w}
+       pack append .s.opt.mode .s.opt.mode.steps {top frame w}
+
+       pack append .s.opt.mode .s.opt.mode.fld4b {top pady 4 frame w}
+       pack append .s.opt.mode .s.opt.mode.flds  {top frame w}
+
+       pack append .s.opt.mode .s.opt.mode.fld4d {top pady 4 frame w}
+       pack append .s.opt.mode .s.opt.mode.vars {top frame w}
+
+       pack append .s.opt.mode .s.opt.mode.fld4c {top pady 4 frame w}
+
+       pack append .s.opt .s.opt.mode {left frame n}
+
+       frame .s.opt.mesg -relief raised -borderwidth 1m
+       label .s.opt.mesg.loss0 \
+               -font $HelvBig \
+               -text "A Full Queue" \
+               -relief sunken -borderwidth 1m
+       radiobutton .s.opt.mesg.loss1 -text "Blocks New Msgs" \
+               -variable l_typ -value 0 \
+               -relief flat
+       radiobutton .s.opt.mesg.loss2 -text "Loses New Msgs" \
+               -variable l_typ -value 1 \
+               -relief flat
+       pack append .s.opt.mesg .s.opt.mesg.loss0 {top pady 4 frame w fillx}
+       pack append .s.opt.mesg .s.opt.mesg.loss1 {top pady 4 frame w}
+       pack append .s.opt.mesg .s.opt.mesg.loss2 {top pady 4 frame w}
+
+       frame .s.opt.hide -relief raised -borderwidth 1m
+       label .s.opt.hide.txt  \
+               -font $HelvBig \
+               -text "Hide Queues in MSC" \
+               -relief sunken -borderwidth 1m
+       pack append .s.opt.hide .s.opt.hide.txt {top pady 4 frame w fillx }
+
+       for {set i 1} {$i < 4} {incr i} {
+               frame .s.opt.hide.q$i
+               label .s.opt.hide.q$i.qno \
+                       -font $HelvBig \
+                       -text "Queue nr:"
+               entry .s.opt.hide.q$i.entry \
+                       -relief sunken -width 8
+               pack append .s.opt.hide.q$i .s.opt.hide.q$i.qno {left pady 4 frame n }
+               pack append .s.opt.hide.q$i .s.opt.hide.q$i.entry {left pady 4 frame n}
+               pack append .s.opt.hide .s.opt.hide.q$i {top pady 4 frame w fillx}
+       }
+       frame .s.opt.lframe -relief raised -borderwidth 1m
+       label .s.opt.lframe.tl \
+               -font $HelvBig \
+               -text "Simulation Style" \
+               -relief sunken -borderwidth 1m
+       radiobutton .s.opt.lframe.is -text "Interactive" \
+               -variable s_typ -value 2 \
+               -relief flat
+       radiobutton .s.opt.lframe.gs -text "Guided (using pan.trail)" \
+               -variable s_typ -value 1 \
+               -relief flat
+       frame .s.opt.lframe.b
+       entry .s.opt.lframe.b.entry -relief sunken -width 8 
+       label .s.opt.lframe.b.label \
+               -font $HelvBig \
+               -text "Steps Skipped"
+       pack append .s.opt.lframe.b \
+               .s.opt.lframe.b.label {left} \
+               .s.opt.lframe.b.entry {left}
+
+       radiobutton .s.opt.lframe.rs -text "Random (using seed)" \
+               -variable s_typ -value 0 \
+               -relief flat
+       frame .s.opt.lframe.s
+       entry .s.opt.lframe.s.entry -relief sunken -width 8 
+       label .s.opt.lframe.s.label \
+               -font $HelvBig \
+               -text "Seed Value"
+       pack append .s.opt.lframe.s \
+               .s.opt.lframe.s.label {left} \
+               .s.opt.lframe.s.entry {left}
+
+       pack append .s.opt.lframe .s.opt.lframe.tl {top pady 4 frame w fillx} \
+               .s.opt.lframe.rs {top pady 4 frame w} \
+               .s.opt.lframe.s  {top pady 4 frame e} \
+               .s.opt.lframe.gs {top pady 4 frame w} \
+               .s.opt.lframe.b  {top pady 4 frame e} \
+               .s.opt.lframe.is {top pady 4 frame w}
+
+       pack append .s.opt .s.opt.lframe {top frame n}
+       pack append .s.opt .s.opt.mesg {top frame n fillx}
+       pack append .s.opt .s.opt.hide {top frame n expand fillx filly}
+
+       pack append .s .s.opt { top frame n }
+
+       pack append .s [button .s.rewind -text "Start" \
+               -command "Rewind"  ] {right frame e}
+       pack append .s [button .s.exit -text "Cancel" \
+               -command "Stopsim" ] {right frame e}
+       pack append .s [button .s.help -text "Help" -fg red \
+               -command "roadmap1" ] {right frame e}
+
+       .s.opt.lframe.s.entry  insert end $seed
+       .s.opt.lframe.b.entry insert end $jumpsteps
+
+       .s.opt.hide.q1.entry insert end $hide_q1
+       .s.opt.hide.q2.entry insert end $hide_q2
+       .s.opt.hide.q3.entry insert end $hide_q3
+
+       raise .s
+}
+
+
+proc simulation {} {
+       global s_typ l_typ showvars qv PlaceSim
+       global fvars gvars lvars SparseMsc HelvBig
+       global msc ebc tsc vv svars rvars seed jumpsteps
+       global hide_q1 hide_q2 hide_q3
+       global whichsim
+
+       catch { .menu.run.m entryconfigure 5 -state normal }
+
+       catch {destroy .s}
+       toplevel .s
+               catch {rmfile pan_in9999999.trail}
+               debug {about to remove pan_in9999999.trail}
+               rmfile pan_in9999999.trail
+       set k [string first "\+" $PlaceSim]
+       if {$k > 0} {
+               set PlaceSim [string range $PlaceSim $k end]
+       }
+
+       wm title .s "Simulation Options"
+       wm iconname .s "SIM"
+       wm geometry .s $PlaceSim
+
+       mkpan_in
+
+       # lower frame with 'start', 'cancel' and 'help' buttons
+       frame .s.l -relief flat
+       pack .s.l -side bottom -fill both
+
+         pack [button .s.l.rewind -text " Start " \
+               -command "Rewind"  ] -side right -fill y -padx 4
+         pack [button .s.l.exit -text "Cancel" \
+               -command "
+                       Stopsim;
+                       catch {rmfile pan_in9999999.trail}
+                       "
+               ] -side right -fill y -padx 4
+         pack [button .s.l.help -text " Help " -fg red \
+               -command "roadmap1" ]  -side right -fill y -padx 4
+
+       # upper frame with modes and options
+       frame .s.u -relief flat
+       pack .s.u -side top -fill both
+
+         frame .s.u.mode -relief raised -borderwidth 1m
+         pack .s.u.mode -side left -fill both -expand 1
+
+           frame .s.u.mode.fdis -relief flat
+           pack .s.u.mode.fdis -side top -fill x -expand 1
+
+             label .s.u.mode.fdis.fld0 \
+               -font $HelvBig \
+               -text "Display Mode" \
+               -relief sunken -borderwidth 1m
+             pack .s.u.mode.fdis.fld0 -side top -fill x
+
+#MSC Panel
+
+           frame .s.u.mode.fmsc -relief flat
+           pack  .s.u.mode.fmsc -side top -fill x
+
+             checkbutton .s.u.mode.fmsc.fld4a -text "MSC Panel - with:" \
+                 -variable msc \
+                 -relief flat
+             pack .s.u.mode.fmsc.fld4a -side left
+
+           frame .s.u.mode.msc -relief flat
+           pack  .s.u.mode.msc -side top -fill x
+
+             frame .s.u.mode.msc.lab -relief flat
+             pack  .s.u.mode.msc.lab -side top -fill x
+
+               frame .s.u.mode.msc.lab.dummy -width 18 -relief flat
+               pack .s.u.mode.msc.lab.dummy -side left -fill y
+
+               frame .s.u.mode.msc.lab.radios -relief flat
+               pack .s.u.mode.msc.lab.radios -side left -fill x
+       
+                 frame .s.u.mode.msc.lab.radios.fnum -relief flat
+                 pack .s.u.mode.msc.lab.radios.fnum -side top -fill x
+
+                   radiobutton .s.u.mode.msc.lab.radios.fnum.fld5 \
+                         -text "    Step Number Labels" \
+                         -variable SYMBOLIC -value 0 \
+                         -relief flat
+                   pack .s.u.mode.msc.lab.radios.fnum.fld5 -side left
+
+                 frame .s.u.mode.msc.lab.radios.ftext -relief flat
+                 pack .s.u.mode.msc.lab.radios.ftext -side top -fill x
+
+                   radiobutton .s.u.mode.msc.lab.radios.ftext.fld6 \
+                       -text "    Source Text Labels" \
+                       -variable SYMBOLIC -value 1 \
+                       -relief flat
+                   pack .s.u.mode.msc.lab.radios.ftext.fld6 -side left
+
+               frame .s.u.mode.msc.lab.bracket
+               pack .s.u.mode.msc.lab.bracket -side left -fill y
+               
+                 canvas .s.u.mode.msc.lab.bracket.c -width 10 -height 40
+                 pack .s.u.mode.msc.lab.bracket.c -side top
+                   .s.u.mode.msc.lab.bracket.c create line 5 15 10 15 10 38 5 38
+
+             frame .s.u.mode.msc.space -relief flat
+             pack  .s.u.mode.msc.space -side top -fill x
+
+               frame .s.u.mode.msc.space.dummy -width 18 -relief flat
+               pack .s.u.mode.msc.space.dummy -side left -fill y
+
+               frame .s.u.mode.msc.space.radios -relief flat
+               pack  .s.u.mode.msc.space.radios -side left -fill x
+       
+                 frame .s.u.mode.msc.space.radios.fnorm -relief flat
+                 pack  .s.u.mode.msc.space.radios.fnorm -side top -fill x
+
+                   radiobutton .s.u.mode.msc.space.radios.fnorm.fld7 \
+                       -text "    Normal Spacing" \
+                       -variable SparseMsc -value 1 \
+                       -relief flat
+                   pack .s.u.mode.msc.space.radios.fnorm.fld7 -side left
+
+                 frame .s.u.mode.msc.space.radios.fcond -relief flat
+                 pack  .s.u.mode.msc.space.radios.fcond -side top -fill x
+
+                   radiobutton .s.u.mode.msc.space.radios.fcond.fld8 \
+                       -text "    Condensed Spacing" \
+                       -variable SparseMsc -value 0 \
+                       -relief flat
+                   pack .s.u.mode.msc.space.radios.fcond.fld8 -side left
+
+               frame .s.u.mode.msc.space.bracket
+               pack .s.u.mode.msc.space.bracket -side left -fill y
+               
+                 canvas .s.u.mode.msc.space.bracket.c -width 10 -height 40
+                 pack .s.u.mode.msc.space.bracket.c -side top
+                   .s.u.mode.msc.space.bracket.c create line 5 15 10 15 10 38 5 38
+
+# Time Sequence Panel
+
+           frame .s.u.mode.ftsp -relief flat 
+           pack  .s.u.mode.ftsp -side top -fill x
+
+             checkbutton .s.u.mode.ftsp.fld4b \
+               -text "Time Sequence Panel - with:" \
+               -variable tsc \
+               -relief flat
+             pack .s.u.mode.ftsp.fld4b -side left
+
+           frame .s.u.mode.tsp
+           pack  .s.u.mode.tsp -side top -fill x
+
+             frame .s.u.mode.tsp.proc
+             pack  .s.u.mode.tsp.proc -side top -fill x
+
+               frame .s.u.mode.tsp.proc.dummy -width 18
+               pack  .s.u.mode.tsp.proc.dummy -side left -fill y
+
+               frame .s.u.mode.tsp.proc.radios -relief flat
+               pack  .s.u.mode.tsp.proc.radios -side left -fill y
+
+                 frame .s.u.mode.tsp.proc.radios.is
+                 pack  .s.u.mode.tsp.proc.radios.is -side top -fill x
+
+                   radiobutton .s.u.mode.tsp.proc.radios.is.fld3 \
+                           -text "    Interleaved Steps" \
+                           -variable m_typ -value 2 \
+                           -relief flat
+                   pack .s.u.mode.tsp.proc.radios.is.fld3 -side left
+
+                 frame .s.u.mode.tsp.proc.radios.1win -relief flat
+                 pack .s.u.mode.tsp.proc.radios.1win -side top -fill x
+
+                   radiobutton .s.u.mode.tsp.proc.radios.1win.fld1 \
+                       -text "    One Window per Process" \
+                       -variable m_typ -value 0 \
+                       -relief flat
+                   pack .s.u.mode.tsp.proc.radios.1win.fld1 -side left
+
+                 frame .s.u.mode.tsp.proc.radios.1trace -relief flat
+                 pack  .s.u.mode.tsp.proc.radios.1trace -side top -fill x
+
+                   radiobutton .s.u.mode.tsp.proc.radios.1trace.fld2 \
+                       -text "    One Trace per Process" \
+                       -variable m_typ -value 1 \
+                       -relief flat
+                   pack .s.u.mode.tsp.proc.radios.1trace.fld2 -side left
+
+               frame .s.u.mode.tsp.proc.bracket
+               pack .s.u.mode.tsp.proc.bracket -side left -fill y
+
+               set y 13
+                 canvas .s.u.mode.tsp.proc.bracket.c -width 10 -height 66
+                 pack .s.u.mode.tsp.proc.bracket.c -side top
+                   .s.u.mode.tsp.proc.bracket.c create line    5  [expr 0 + $y] \
+                                                               10 [expr 0 + $y] \
+                                                               10 [expr 25 + $y] \
+                                                               5  [expr 25 + $y] \
+                                                               10 [expr 25 + $y] \
+                                                               10 [expr 50 + $y] \
+                                                               5  [expr 50 + $y]
+
+       frame .s.u.mode.fdvp -relief flat
+       pack .s.u.mode.fdvp -side top -fill x
+
+         checkbutton .s.u.mode.fdvp.fld4d -text "Data Values Panel" \
+               -variable vv \
+               -relief flat
+         pack .s.u.mode.fdvp.fld4d -side left
+
+       frame .s.u.mode.vars
+       pack .s.u.mode.vars -side top -fill x
+
+         frame .s.u.mode.vars.dummy -width 18
+         pack .s.u.mode.vars.dummy -side left -fill y
+
+         frame .s.u.mode.vars.chks -relief flat
+         pack  .s.u.mode.vars.chks -side left -fill y
+           
+           frame .s.u.mode.vars.chks.ftbc
+           pack  .s.u.mode.vars.chks.ftbc -side top -fill x
+
+             checkbutton .s.u.mode.vars.chks.ftbc.fld4c -text "    Track Buffered Channels" \
+               -variable qv \
+               -relief flat
+             pack .s.u.mode.vars.chks.ftbc.fld4c -side left
+
+           frame .s.u.mode.vars.chks.ftgv
+           pack  .s.u.mode.vars.chks.ftgv -side top -fill x
+
+             checkbutton .s.u.mode.vars.chks.ftgv.fld4d -text "    Track Global Variables" \
+               -variable gvars \
+               -relief flat
+             pack .s.u.mode.vars.chks.ftgv.fld4d -side left
+
+           frame .s.u.mode.vars.chks.ftlv
+           pack  .s.u.mode.vars.chks.ftlv -side top -fill x
+
+             checkbutton .s.u.mode.vars.chks.ftlv.fld4e -text "    Track Local Variables" \
+               -variable lvars \
+               -relief flat
+             pack .s.u.mode.vars.chks.ftlv.fld4e -side left
+
+           frame .s.u.mode.vars.chks.fshow
+           pack  .s.u.mode.vars.chks.fshow -side top -fill x
+
+             checkbutton .s.u.mode.vars.chks.fshow.fld4f \
+               -text "    Display vars marked 'show' in MSC" \
+               -variable showvars \
+               -relief flat
+
+             pack .s.u.mode.vars.chks.fshow.fld4f -side left
+
+       frame .s.u.mode.fexecbar -relief flat
+       pack .s.u.mode.fexecbar -side top -fill x
+
+         checkbutton .s.u.mode.fexecbar.fld4c -text "Execution Bar Panel" \
+               -variable ebc \
+               -relief flat
+          pack .s.u.mode.fexecbar.fld4c -side left
+
+#Right upper frame
+       frame .s.u.r -relief flat
+       pack .s.u.r -side right -fill y -expand 1
+
+#Simulation Style
+         frame .s.u.r.sim -relief raised -borderwidth 1m
+         pack .s.u.r.sim -side top -fill both -expand 1
+
+           frame .s.u.r.sim.flab -relief sunken
+           pack .s.u.r.sim.flab -side top -fill x
+
+             label .s.u.r.sim.flab.tl \
+               -font $HelvBig \
+               -text "Simulation Style" \
+               -relief sunken -borderwidth 1m
+             pack .s.u.r.sim.flab.tl -side top -fill x
+
+           frame .s.u.r.sim.random
+           pack .s.u.r.sim.random -side top -fill x
+
+               radiobutton .s.u.r.sim.random.rs -text "Random (using seed)" \
+               -variable s_typ -value 0 \
+               -relief flat \
+               -command "enable_disable_sub_buttons"
+               pack .s.u.r.sim.random.rs -side left
+
+           frame .s.u.r.sim.seedvalue
+           pack .s.u.r.sim.seedvalue -side top -fill x
+
+             frame .s.u.r.sim.seedvalue.dummy -width 18
+             pack .s.u.r.sim.seedvalue.dummy -side left -fill y
+
+             label .s.u.r.sim.seedvalue.label \
+               -font $HelvBig \
+               -text "Seed Value"
+             pack .s.u.r.sim.seedvalue.label -side left
+
+             entry .s.u.r.sim.seedvalue.entry -relief sunken -width 8
+             pack .s.u.r.sim.seedvalue.entry -side left
+
+           frame .s.u.r.sim.guided
+           pack .s.u.r.sim.guided -side top -fill x
+
+               radiobutton .s.u.r.sim.guided.gs -text "Guided" \
+                  -variable s_typ -value 1 \
+                  -relief flat \
+                  -command "enable_disable_sub_buttons"
+               pack .s.u.r.sim.guided.gs -side left
+               
+               frame .s.u.r.sim.guided_type
+               pack .s.u.r.sim.guided_type -side top -fill x
+
+                 frame .s.u.r.sim.guided_type.dummy -width 18
+                 pack .s.u.r.sim.guided_type.dummy -side left -fill y
+
+                   frame .s.u.r.sim.guided_type.radios
+                   pack .s.u.r.sim.guided_type.radios -side left
+
+                     frame .s.u.r.sim.guided_type.radios.pan_trail
+                     pack  .s.u.r.sim.guided_type.radios.pan_trail -side top -fill x
+
+                       radiobutton .s.u.r.sim.guided_type.radios.pan_trail.rb \
+                               -text "Using pan_in.trail" \
+                               -variable whichsim -value 0 \
+                               -relief flat
+                       pack .s.u.r.sim.guided_type.radios.pan_trail.rb -side left
+
+                     frame .s.u.r.sim.guided_type.radios.trail_other
+                     pack  .s.u.r.sim.guided_type.radios.trail_other -side top -fill x
+
+                       radiobutton .s.u.r.sim.guided_type.radios.trail_other.rb \
+                               -text "Use" \
+                               -variable whichsim -value 1 \
+                               -relief flat
+                       pack .s.u.r.sim.guided_type.radios.trail_other.rb -side left
+
+                       entry .s.u.r.sim.guided_type.radios.trail_other.entry \
+                               -width 20
+                       pack .s.u.r.sim.guided_type.radios.trail_other.entry -side left
+
+                       button .s.u.r.sim.guided_type.radios.trail_other.button -text "Browse" \
+                               -command select_trail_file
+                       pack .s.u.r.sim.guided_type.radios.trail_other.button -side left          
+
+           frame .s.u.r.sim.skipstep
+           pack  .s.u.r.sim.skipstep -side top -fill x
+
+             label .s.u.r.sim.skipstep.label \
+               -font $HelvBig \
+               -text "Steps Skipped"
+             pack .s.u.r.sim.skipstep.label -side left
+
+             entry .s.u.r.sim.skipstep.entry -relief sunken -width 8
+             pack .s.u.r.sim.skipstep.entry -side left
+
+           frame .s.u.r.sim.interactive
+           pack .s.u.r.sim.interactive -side top -fill x
+
+               radiobutton .s.u.r.sim.interactive.is -text "Interactive" \
+                       -variable s_typ -value 2 \
+                       -relief flat \
+               -command "enable_disable_sub_buttons"
+               pack .s.u.r.sim.interactive.is -side left
+
+#A Full Queue
+         frame .s.u.r.fq -relief raised -borderwidth 1m
+         pack .s.u.r.fq -side top -fill both -expand 1
+
+           frame .s.u.r.fq.label -relief sunken
+           pack .s.u.r.fq.label -side top -fill x
+
+             label .s.u.r.fq.label.loss0 \
+               -font $HelvBig \
+               -text "A Full Queue" \
+               -relief sunken -borderwidth 1m
+             pack .s.u.r.fq.label.loss0 -side top -fill x
+
+           frame .s.u.r.fq.block
+           pack .s.u.r.fq.block -side top -fill x
+
+             radiobutton .s.u.r.fq.block.loss1 -text "Blocks New Msgs" \
+               -variable l_typ -value 0 \
+               -relief flat
+             pack .s.u.r.fq.block.loss1 -side left
+
+           frame .s.u.r.fq.lose
+           pack .s.u.r.fq.lose -side top -fill x
+
+             radiobutton .s.u.r.fq.lose.loss2 -text "Loses New Msgs" \
+               -variable l_typ -value 1 \
+               -relief flat
+             pack .s.u.r.fq.lose.loss2 -side left
+
+#Hide Queues in MSC
+         frame .s.u.r.hq -relief raised -borderwidth 1m
+         pack .s.u.r.hq -side top -fill both -expand 1
+
+           frame .s.u.r.hq.flabel -relief sunken
+           pack .s.u.r.hq.flabel -side top -fill x
+
+               label .s.u.r.hq.flabel.txt  \
+                 -font $HelvBig \
+                 -text "Hide Queues in MSC" \
+                 -relief sunken -borderwidth 1m
+           pack .s.u.r.hq.flabel.txt -side top -fill x
+
+       for {set i 1} {$i < 4} {incr i} {
+               frame .s.u.r.hq.q$i
+               pack .s.u.r.hq.q$i -side top -fill x
+               label .s.u.r.hq.q$i.qno \
+                       -font $HelvBig \
+                       -text "Queue nr:"
+               pack .s.u.r.hq.q$i.qno -side left
+               entry .s.u.r.hq.q$i.entry \
+                       -relief sunken -width 8
+               pack .s.u.r.hq.q$i.entry -side left
+       }
+
+       .s.u.r.sim.seedvalue.entry insert end $seed
+       .s.u.r.sim.skipstep.entry insert end $jumpsteps
+
+       .s.u.r.hq.q1.entry insert end $hide_q1
+       .s.u.r.hq.q2.entry insert end $hide_q2
+       .s.u.r.hq.q3.entry insert end $hide_q3
+       enable_disable_sub_buttons
+
+       tkwait visibility .s
+       raise .s
+}
+
+proc enable_disable_sub_buttons {} {
+       global s_typ
+       switch -regexp $s_typ {
+               0|2 { .s.u.r.sim.guided_type.radios.pan_trail.rb configure -state disabled
+                     .s.u.r.sim.guided_type.radios.trail_other.rb configure -state disabled
+                     .s.u.r.sim.guided_type.radios.trail_other.button configure -state disabled
+                   }
+               1   { .s.u.r.sim.guided_type.radios.pan_trail.rb configure -state normal
+                     .s.u.r.sim.guided_type.radios.trail_other.rb configure -state normal
+                     .s.u.r.sim.guided_type.radios.trail_other.button configure -state normal
+                     .s.u.r.sim.guided_type.radios.pan_trail.rb select
+                   }
+
+       }
+}
+
+proc select_trail_file {} {
+       global Trail_filename
+       .s.u.r.sim.guided_type.radios.trail_other.rb select
+       # try to use the predefined file selection dialog
+       switch [info commands tk_getOpenFile] "" {
+               # some old version of Tk so use our own file selection dialog
+               set fileselect "FileSelect open"
+       } default {
+               set fileselect "tk_getOpenFile"
+       }
+       set init_dir [pwd]
+       # get the file (return if the file selection dialog canceled)
+       switch -- [set file [eval $fileselect -initialdir { { $init_dir } } ]] "" return
+       .s.u.r.sim.guided_type.radios.trail_other.entry insert end $file
+       raise .s
+       
+}
+
+proc bld_s_options {} {
+       global fvars gvars lvars svars qv
+       global rvars l_typ showvars vv
+       global s_typ seed jumpsteps s_options
+       global hide_q1 hide_q2 hide_q3 ival whichsim trail_file trail_num
+
+       set s_options "-X -p -v $ival(5)"
+
+       if {$showvars && $gvars == 0 && $lvars == 0} {
+               catch { tk_messageBox -icon info \
+               -message "Display variables marked 'show' selected, \
+               but no local or global vars are being tracked"
+       }       }
+       if {$showvars==1} { set s_options [format "%s -Y" $s_options] }
+       if {$s_typ==2} { set s_options [format "%s -i" $s_options] }
+       if {$vv && $gvars} { set s_options [format "%s -g" $s_options] }
+       if {$vv && $lvars} { set s_options [format "%s -l" $s_options] }
+       if {$svars} { set s_options [format "%s -s" $s_options] }
+       if {$rvars} { set s_options [format "%s -r" $s_options] }
+       if {$l_typ} { set s_options [format "%s -m" $s_options] }
+       if {$hide_q1 != ""} { set s_options [format "%s -q%s" $s_options $hide_q1] }
+       if {$hide_q2 != ""} { set s_options [format "%s -q%s" $s_options $hide_q2] }
+       if {$hide_q3 != ""} { set s_options [format "%s -q%s" $s_options $hide_q3] }
+       if {$s_typ==1} then {
+               set trail_num ""
+               #Guided
+               if {$whichsim == 1} {
+                       #using user specified file
+                       if ![file exists $trail_file] {
+                               catch { tk_messageBox -icon info \
+                                       -message "Trail file $trail_file does not exist."
+                               }
+                               return 0
+                       }
+                       # see if file is in current directory. if not, copy to 
+                       # pan_in9999999.trail in current directory
+                       set ind [string last "\/" $trail_file]
+                       if {$ind > -1} {
+                               if {[pwd] != [string range $trail_file 0 [expr $ind - 1]]} { 
+                                       cpfile $trail_file pan_in9999999.trail
+                                       set trail_file "pan_in9999999.trail"
+                               } else {
+                                       #strip off path
+                                       set trail_file [string range $trail_file \
+                                               [expr $ind + 1] \
+                                               [expr [string length $trail_file] - 1]]
+                               }
+                       }       
+                       #see if it's a 'pan_in<#>.trail' file
+                       set is_pan_in_trail_file 0
+                       if {[string range $trail_file 0 5] == "pan_in"} {
+                               set l [string length $trail_file]
+
+                               if {[string range $trail_file \
+                                       [expr $l-6] [expr $l-1]] == ".trail"} {
+                                       set num [string range $trail_file 6 [expr $l-7]]
+                                       if [string is integer $num] {
+                                               set trail_num $num
+                                               set is_pan_in_trail_file 1
+                       }       }       }
+                       if !($is_pan_in_trail_file) {
+                               # not a 'pan_in<#>.trail' file - copy file to pan_in9999999.trail
+                               # in current directory
+                               cpfile $trail_file pan_in9999999.trail
+                               if [file exists pan_in9999999.trail] {
+                                       set trail_num 9999999
+                               } else {
+                                       catch {tk_messageBox -icon info \
+                                               -message "Unable to create input file in $pwd \
+                                                       check write permissions."
+                                       }
+                                       return 0
+                               }
+                       }
+               } else {
+                       if {![file exists pan_in.trail] && ![file exists pan_in.tra]} {
+                               catch { tk_messageBox -icon info \
+                                       -message "Trail file \'pan_in.tra(il)\' does not exist."
+                               }
+                               return 0
+                       }
+               }
+                       
+               set s_options [format "%s -t%s" $s_options $trail_num]
+       } else {
+               if {[string length $seed] > 0} {
+                       set s_options [format "%s -n%s" $s_options $seed]
+       }       }
+       if {$s_typ!=2} then {
+               if {[string length $jumpsteps] > 0} {
+                       set s_options [format "%s -j%s" $s_options $jumpsteps]
+       }       }
+       return 1
+}
+
+proc Stopsim {} {
+       global stop dbox2 Sticky PlaceSim PlaceCanvas
+       global stepper stepped howmany fd
+
+       set stop 1
+       set stepped 0
+       set stepper 0
+       add_log "<stop simulation>"
+       if {[winfo exists .s]} {
+               set PlaceSim [wm geometry .s]
+               destroy .s
+       }
+       catch {set howmany 0}
+       catch {stopbar}
+       catch { if {$Sticky($dbox2) == 0} {
+                       set PlaceCanvas(msc) [wm geometry .f$dbox2]
+                       destroy .f$dbox2
+       }       }
+       catch {
+               puts $fd "q"
+               flush $fd
+       }
+       update
+}
+
+proc Step_forw {} {
+       global stepper stepped sbox simruns PlaceSim
+
+       set stepped 1
+       set stepper 1
+       if {$simruns == 0} {
+               if {[winfo exists .s]} {
+                       set PlaceSim [wm geometry .s]
+                       destroy .s
+               }
+               runsim
+       } else {
+               catch { .c$sbox.run configure \
+               -text "Run" -command "Runsim" }
+       }
+}
+
+proc Rewind {} {
+       global Depth s_typ whichsim trail_file
+       global Sdbox Spbox
+       global seed jumpsteps simruns
+       global hide_q1 hide_q2 hide_q3 trail_file
+
+       catch { set jumpsteps [.s.u.r.sim.skipstep.entry get] }
+       catch { set hide_q1 [.s.u.r.hq.q1.entry get] }
+       catch { set hide_q2 [.s.u.r.hq.q2.entry get] }
+       catch { set hide_q3 [.s.u.r.hq.q3.entry get] }
+
+       if {$s_typ == 0} {
+               catch { set seed [.s.u.r.sim.seedvalue.entry get] }
+       }
+       if {$s_typ == 1} {
+               #Guided
+               set Depth 0
+               catch {
+                       foreach el [array names Spbox] {
+                               set Sdbox $Spbox($el)
+                               .c$Sdbox.z.t tag remove Rev 1.0 end
+               }       }
+               if {$whichsim == 1} {
+                       set trail_file ""
+                       catch {set trail_file [.s.u.r.sim.guided_type.radios.trail_other.entry get]}
+               }
+       }
+
+       set simruns 0
+
+       Step_forw
+}
+
+proc Runsim {} {
+       global stepper stepped sbox
+
+       catch { .c$sbox.run configure \
+               -text "Suspend" -command "Step_forw" }
+       set stepper 1
+       set stepped 0
+}
+
+proc BreakPoint {} {
+       global stepped sbox
+
+       set stepped 1
+       catch { .c$sbox.run configure \
+               -text "BreakPoint" -command "Runsim" }
+}
+
+proc runsim {} {
+       global Unix SPIN tk_major
+       global s_options s_typ dbox2
+       global stepper stepped
+       global simruns m_typ
+       global gvars lvars
+       global fd stop Depth Seq
+       global Sdbox Spbox pbox howmany Choice
+       global sbox VERBOSE SYMBOLIC msc ebc vv tsc
+       global Blue Yellow White Red Green
+       global SmallFont BigFont Sticky SparseMsc
+       global FG BG qv gvars lvars PlaceBox
+       global dbox Vvbox 
+       global whichsim trail_num
+
+       set simruns 1
+       set Vvbox 0
+       set pno 0
+       set Varnm("") ""
+       set Queues("")  ""
+       set Depth 0
+       set Seq(0) 0
+       set Pstp 1
+       set Seenpno 1
+       set Banner "Select"
+
+#      catch { unset Spbox(0) }
+       catch {
+               foreach el [array names pbox] {
+                       catch { destroy .c$pbox($el) }
+                       catch { unset pbox($el) }
+               }
+               foreach el [array names Spbox] {
+                       catch { destroy .c$Spbox($el) }
+                       catch { unset Spbox($el) }
+               }
+       }
+       if ![bld_s_options] {
+               return
+       }
+
+       add_log "<starting simulation>"
+       add_log "$SPIN $s_options pan_in"
+       update
+       set s_options [format "%s pan_in" $s_options]
+
+       mkpan_in
+
+       set sbox [mkbox "Simulation Output" "SimOut" "sim.out" 71 11 100 100]
+
+       pack append .c$sbox [button .c$sbox.stepf -text "Single Step" \
+               -command "Step_forw" ] {left frame w}
+       pack append .c$sbox [button .c$sbox.run -text "Run" \
+               -command "Runsim" ] {left frame w}
+
+       .c$sbox.b configure -text "Cancel" -command "Stopsim"
+
+       raise .c$sbox
+
+       set YSZ 12
+       set XSZ 84
+       set YNR 60
+       set NPR 10
+       set SMX 250
+       set Easy 1
+       set HAS 0
+       set HAS_CYCLE 0
+       set dontwait 0
+       set notexecutable 0
+       set lastexecutable 0
+
+       if {$m_typ == 2} {
+               if {$tsc} {
+               set pbox(0) \
+               [mkbox "Time Sequence" "Sequence" "seq.out" 80 10 100 325]
+               set dbox $pbox(0)
+       }       }
+       if {$msc} {
+               if {[hasWord "!!"] || [hasWord "\\?\\?"]} {
+                       set Easy 0
+               }
+
+               set maxx [expr [winfo screenwidth .]  - 400]    ;# button widths
+               set maxh [expr [winfo screenheight .] - (5+120)]        ;# borders+buttons
+               set dbox2 \
+               [mkcanvas "Sequence Chart" "msc" $maxx 5 1]
+               .f$dbox2.c configure -height $maxh \
+                       -scrollregion "[expr -$XSZ/2] 0 \
+                               [expr $NPR*$XSZ] [expr 100+$SMX*$YSZ]"
+
+               raise .f$dbox2
+       }
+
+       raise .c$sbox
+
+       set stop 0
+       set good_trail 0
+       if {$s_typ == 1} {
+               if $whichsim {
+                       set filen "pan_in${trail_num}.trail"
+                       if [file exists $filen] {
+                               set good_trail 1
+                       }
+               } else {
+                       if {[file exists pan_in.trail] || [file exists pan_in.tra]} {
+                               set good_trail 1
+                       }
+               } 
+               if $good_trail {
+                       catch { .c$sbox.z.t insert end "preparing trail, please wait..." }
+                       update
+                       rmfile trail.out
+                       catch {eval exec $SPIN $s_options >&trail.out} errmsg
+               } else {
+                       set errmsg "error: no trail file for guided simulation"
+                       return
+               }
+               if {[string length $errmsg]>0} {
+                       add_log "$errmsg"
+                       catch {
+                       tk_messageBox -icon info -message $errmsg
+                       }
+                       catch {
+                               set fd [open trail.out r]
+                               while {[gets $fd line] > -1} {
+                                       add_log "$line"
+                               }
+                               close $fd
+                       }
+                       Stopsim
+                       catch { destroy .c$sbox }
+                       catch { destroy .c$dbox }
+                       set simruns 0
+                       update
+                       return
+               }
+               set fd [open trail.out r]
+               catch { .c$sbox.z.t insert end "done\n" }
+       } else {
+               update
+               set fd [open "|$SPIN $s_options" r+]
+               catch "flush $fd"
+               update
+       }
+
+       if {$s_typ == 2} {
+               Runsim
+       }
+
+       if {$ebc} { startbar "Xspin Bar Chart" }
+
+       set pstp -1
+       set bailout 0
+       set realstring ""
+
+       update
+       raise .c$sbox
+       lower .
+
+       while {$stop == 0 && [eof $fd] == 0} {
+       if {$bailout == 0 && [gets $fd line] > -1} {
+               set pln 0
+               set syntax 0
+               set isvar 0
+               set pname ""
+               set i 0
+               set VERBOSE 0
+               set Fnm "pan_in"
+
+               raise .c$sbox
+
+               if {$Unix == 0} {
+                       if {[string first "processes created" $line] > 0} {
+                               set bailout 1
+               }       }
+               if {[string first "type return to proceed" $line] > 0} {
+                       puts $fd ""
+                       flush $fd
+                       update
+                       continue
+               }
+
+               set i [string first "<merge" $line]
+               if {$i > 0} {
+                       set line [string range $line 0 $i]
+               }
+
+               set lastpstp $pstp
+               set pmtch [scan $line \
+                       "%d: proc %d (%s line %d \"%s\" " \
+                       pstp pno pname pln Fnm]
+               incr pmtch -1
+               set i [string first "\[" $line]
+               if {$i > 0} {
+                       set i [expr $i + 1]
+                       set j [string length $line]
+                       set j [expr $j - 2]
+                       set stmnt [string range $line $i $j]
+               } else {
+                       set stmnt "-"
+               }
+               if {$pmtch != 4} {
+                       set pmtch [scan $line \
+                               "       proc %d (%s line %d \"%s\" " \
+                               pno pname pln Fnm]
+               }
+               if {$pmtch != 4} {
+                       if {[string first "spin: line" $line] == 0 } {
+                               scan $line "spin: line %d \"%s\" " pln Fnm
+                               if {[string first "pan_in" $Fnm] >= 0} {
+                               .inp.t tag add Rev $pln.0 $pln.end
+                               .inp.t tag configure Rev \
+                                       -background $FG -foreground $BG
+                               .inp.t yview -pickplace $pln.0
+                               }
+                               if {[string first "assertion viol" $line] < 0} {
+                                       set syntax 1
+                               }
+                       }
+                       if {[string first "Error: "   $line] >= 0 \
+                       ||  [string first "warning: " $line] >= 0 } {
+                               set syntax 1
+                       }
+               }
+               if {$pmtch != 4 && $syntax == 0} {
+                       set pmtch [scan $line \
+                               "%d: proc - (%s line %d \"%s\" " \
+                               pstp pname pln Fnm]
+                       if { $pmtch == 4 } {
+                               set pno -1
+                       }
+               }
+               #       set Fnm [string trim $Fnm "\""]
+               set pname [string trim $pname "()"]
+
+               if {[string first "TRACK" $pname] >= 0} {
+                       set nwcol([expr $pno+1]) 1
+               } elseif {[string length $pname] > 0} {
+                       if {[info exists nwcol([expr $pno+1])] \
+                       &&  $nwcol([expr $pno+1])} {
+                               unset Plabel($pno)
+##
+                               set TMP1 [expr ($pno + 1)*$XSZ]
+                               set TMP2 [expr $Pstp*$YSZ]
+                               .f$dbox2.c create line \
+                                       [expr $TMP1 - 20] $TMP2 \
+                                       [expr $TMP1 + 20] $TMP2 \
+                                       -width 2 \
+                                       -fill $Red
+                               incr TMP2 4
+                               .f$dbox2.c create line \
+                                       [expr $TMP1 - 20] $TMP2 \
+                                       [expr $TMP1 + 20] $TMP2 \
+                                       -width 2 \
+                                       -fill $Red
+##
+                       }
+                       set nwcol([expr $pno+1]) 0
+               }
+               if {$pmtch == 4 && $syntax == 0} {
+                       if {$ebc} {
+                               if {[string first "values:" $line] < 0} {
+                                       stepbar $pno $pname
+                       }       }
+                       if {$m_typ == 1 && $tsc} {
+                               if { [info exists pbox($pno)] == 0 } {
+                                       set pbox($pno) [mkbox \
+                                               "Proc $pno ($pname)" \
+                                               "Proc$pno" "proc.$pno.out" \
+                                               60 10 \
+                                               [expr 100+$pno*25] \
+                                               [expr 325+$pno*35] ]
+                               }
+                               set dbox $pbox($pno)
+                       } elseif {$m_typ == 0 && $tsc} {
+                               if { [info exists Spbox($pno)] == 0 } {
+                                       set Spbox($pno) \
+                                               [mkbox "$pname (proc $pno)" \
+                                               "$pname" "" \
+                                               60 10 \
+                                               [expr 100+$pno*25] \
+                                               [expr 325+$pno*35] ]
+                                       readinfile .c$Spbox($pno).z.t "pan_in"
+                               }
+                               set Sdbox $Spbox($pno)
+                       }
+               } elseif { [string first "..." $line] > 0 && \
+                          [regexp "^\\\t*MSC: (.*)" $line] == 0 } {
+                       set $line ""
+                       set syntax 1
+                       set pln 0
+               } elseif {$s_typ == 2 \
+                     && [string first "Select " $line] == 0 } {
+                       set Banner $line
+                       set pln 0
+                       set notexecutable 0
+                       set lastexecutable 0
+                       set has_timeout 0
+               } elseif {$s_typ == 2 \
+                     && [string first "choice" $line] >= 0 } {
+                       scan $line "    choice %d" howmany
+                       set NN [string first ":" $line]; incr NN 2
+                       set Choice($howmany) [string range $line $NN end]
+                       if {[string first "timeout" $Choice($howmany)] > 0} {
+                               set has_timeout 1
+                       }
+                       if {[string first "unexecutable," $line] >= 0} {
+                               incr notexecutable
+                       } else {
+                               set lastexecutable $howmany
+                       }
+                       set pln 0
+               } elseif {$s_typ == 2 \
+                     && [string first "Make Selection" $line] >= 0 } {
+                       scan $line "Make Selection %d" howmany
+                       if {$notexecutable == $howmany-1 && $has_timeout == 0} {
+                               set howmany $lastexecutable
+                               add_log "selected: $howmany (forced)"
+                               catch {
+                                       foreach el [array names Choice] {
+                                       unset Choice($el)
+                               } }
+                       } else {
+                               pickoption $Banner
+                               add_log "selected: $howmany"
+                       }
+                       puts $fd $howmany
+                       catch "flush $fd"
+                       set dontwait 1
+                       set pln 0
+               } elseif { [regexp "^\\\t*MSC: (.*)" $line mch rstr] != 0 } {
+                       if {$realstring != ""} {
+                       set realstring "$realstring $rstr"
+                       } else {
+                       set realstring $rstr
+                       }
+                       # picked up in next cycle
+               } elseif { [string first "processes" $line] > 0 \
+                     ||   [string first "timeout" $line]  == 0 \
+                     ||   [string first "=s==" $line]  > 0 \
+                     ||   [string first "=r==" $line]  > 0 } {
+
+                       if { $m_typ == 1 && $tsc} {
+                               set dbox $pbox(0)
+                       } elseif { $m_typ == 0 && $tsc} {
+                               if { [info exists Spbox($pno)] == 0 } {
+                                       set Spbox($pno) \
+                                               [mkbox "$pname (proc $pno)" \
+                                               "$pname" "" \
+                                               60 10 \
+                                               [expr 100+$pno*25] \
+                                               [expr 325+$pno*35] ]
+                                       readinfile .c$Spbox($pno).z.t "pan_in"
+                               }
+                               set Sdbox $Spbox($pno)
+                       }
+                       set pln 0;      # prevent tag update
+               } elseif {$syntax == 0 && [string first " = " $line] > 0 } {
+                               set isvar [string first "=" $line]
+                               set isvar [expr $isvar + 1]
+                               set varvl [string range $line $isvar end]
+                               set isvar [expr $isvar - 2]
+                               set varnm [string range $line 0 $isvar]
+                               set varnm [string trim $varnm " "]
+                               set Varnm($varnm) $varvl
+                               set isvar 1
+               } elseif { [scan $line " %s %d " varnm qnr] == 2} {
+                       if {$syntax == 0 &&  [string compare $varnm "queue"] == 0} {
+                               set isvar [string last ":" $line]
+                               set isvar [expr $isvar + 1]
+                               set varvl [string range $line $isvar end]
+                               set XX [string first "(" $line]
+                               set YY [string last  ")" $line]
+                               set ZZ [string range $line $XX $YY]
+                               set Queues($qnr) $varvl
+                               if {[info exists Alias($qnr)]} {
+                               if {[string first $ZZ $Alias($qnr)] < 0} {
+                                       set Alias($qnr) "$Alias($qnr), $ZZ"
+                               }
+                               } else {
+                                       set Alias($qnr) $ZZ
+                               }
+                               set isvar 1
+                       }
+               } elseif {[string length $line] == 0} {
+                       if {$dontwait == 0} { set stepper 0 }
+                       set pln 0
+                       set Depth [expr $Depth + 1]
+                       set Seq($Depth) [tell $fd]
+                       set dontwait 0
+               }
+
+
+       if {$syntax == 0} {
+               if {[string first "terminates" $line] > 0} {
+                       set pln -1
+                       set stmnt "<stop>"
+               }
+##NEW
+               if {$pln > 0 && [string first "pan_in" $Fnm] >= 0} {
+                       .inp.t tag remove hilite 0.0 end
+                       src_line $pln
+               }
+##END
+               if {$m_typ == 0} {
+                       if {$pln > 0 && [string first "pan_in" $Fnm] >= 0} {
+                               catch {
+                               .c$Sdbox.z.t yview -pickplace $pln.0
+                               .c$Sdbox.z.t tag remove Rev 1.0 end
+                               .c$Sdbox.z.t tag add Rev $pln.0 $pln.end
+                               .c$Sdbox.z.t tag configure Rev \
+                                       -background $FG -foreground $BG
+                       }       }
+               } elseif {$m_typ == 1} {
+                       if { [info exists pbox($pno)] == 0 } {
+                               set pbox($pno) [mkbox \
+                                       "Proc $pno ($pname)" \
+                                       "Proc$pno" "proc.$pno.out" \
+                                       60 10 \
+                                       [expr 100+$pno*25] \
+                                       [expr 325+$pno*35] ]
+                       }
+                       set dbox $pbox($pno)
+                       catch {
+                               .c$dbox.z.t yview -pickplace end
+                               .c$dbox.z.t insert end "$line\n"
+                       }
+               } elseif {$m_typ == 2 && $pln != 0 \
+               &&  [string first "unexecutable, " $line] < 0} {
+                       catch { .c$dbox.z.t yview -pickplace end }
+                       catch { .c$dbox.z.t insert end "$pno:$pln" }
+                       for {set i $pno} {$i > 0} {incr i -1} {
+                               catch { .c$dbox.z.t insert end "\t|" }
+                       }
+                       catch { .c$dbox.z.t insert end "\t|>$stmnt\n" }
+               }
+               if {$msc && $pln != 0} {
+                       set Mcont "--"
+                       set HAS 0
+                       if { [scan $stmnt "values: %d!%d" inq inp1] == 2 \
+                       ||   [scan $stmnt "values: %d!%s" inq inp2] == 2 } {
+                               set HAS   [string first "!" $stmnt]
+                               incr HAS
+                               set Mcont [string range $stmnt $HAS end]
+                               set HAS 1
+                       } elseif { [scan $stmnt "values: %d?%d" inq inp1] == 2 \
+                       || [scan $stmnt "values: %d?%s" inq inp2] == 2 } {
+                               set HAS   [string first "?" $stmnt]
+                               incr HAS
+                               set Mcont [string range $stmnt $HAS end]
+                               set HAS 2
+                       } elseif { [string first "-" $stmnt] == 0} {
+                               set HAS 3
+                               if {$HAS_CYCLE} {
+                                       set stmnt [format "Cycle>>"]
+                               } else {
+                                       set stmnt [format "<waiting>"]
+                               }
+                       } elseif { [string first "<stop>" $stmnt] == 0} {
+                               set HAS 3
+                               set stmnt [format "<stopped>"]
+                       }
+                       if {$pno+1 > $Seenpno} { set Seenpno [expr $pno+1] }
+                       set XLOC [expr (1+$pno)*$XSZ]
+                       set YLOC [expr $Pstp*$YSZ]
+                       if {[string first "printf('MSC: " $stmnt] == 0} {
+                               set VERBOSE 1
+                               set stmnt $realstring
+                               if {[string first "BREAK" $realstring] >= 0} {
+                                       BreakPoint
+                               }
+                               set realstring ""
+                       } else {
+                               set VERBOSE 0
+                       }
+                       catch {
+                       if {$VERBOSE \
+                       ||  $HAS != 0 \
+                       ||  [info exists R($pstp,$pno)]} {
+
+                               if { $SparseMsc == 1 \
+                               ||   [info exists Plabel($pno)] == 0 \
+                               ||   ([info exists R($pstp,$pno)] == 0 \
+                               &&   ($HAS != 1 \
+                               ||   [info exists HasBox($YLOC,[expr 1+$pno])])) } {
+                                       incr Pstp
+                                       for     {set i 1} \
+                                               {$Pstp > 1 && $i <= $Seenpno} \
+                                               {incr i} {
+                                               if {[info exists HasBox($YLOC,$i)]} {
+                                                       continue
+                                               }
+                                               set TMP1 [expr $i*$XSZ]
+                                               set lncol $Blue
+                                               set lnwdt 1
+                                               catch {
+                                                       if {$nwcol($i)} {
+                                                               set lncol "gray"
+                                                               set lnwdt 15
+                                               }       }
+                                               .f$dbox2.c create line \
+                                               $TMP1 $YLOC $TMP1 \
+                                               [expr $YLOC+$YSZ] \
+                                               -width $lnwdt \
+                                               -fill $lncol
+                                       }
+                                       if {[info exists HasBox($YLOC,[expr 1+$pno])]} {
+                                               set YLOC [expr $Pstp*$YSZ]
+                               }       }
+                               if {$HAS == 1 || $HAS == 2} {
+                                       set stmnt [string range $stmnt 8 end]
+                               }
+                               if { [info exists Plabel($pno)] == 0} {
+                                       set Plabel($pno) 0
+                                       if {$SparseMsc == 0} {
+                                               set HasBox($YLOC,[expr 1+$pno]) 1
+                                       }
+                                       .f$dbox2.c create rectangle \
+                                               [expr $XLOC-20] $YLOC \
+                                               [expr $XLOC+20] \
+                                               [expr $YLOC+$YSZ] \
+                                               -outline $Red -fill $Yellow
+
+                                               if {$pname != "TRACK"} {
+                                                       .f$dbox2.c create text $XLOC \
+                                                               [expr $YLOC+$YSZ/2] \
+                                                               -font $SmallFont \
+                                                               -text "$pname:$pno"
+                                               } else {
+                                                       .f$dbox2.c create text $XLOC \
+                                                               [expr $YLOC+$YSZ/2] \
+                                                               -font $SmallFont \
+                                                               -text "<show>"
+                                               }
+
+                                       set YLOC [expr $Pstp*$YSZ]
+                                       incr Pstp
+                                       for     {set i 1} \
+                                               {$Pstp > 1 && $i <= $Seenpno} \
+                                               {incr i} {
+                                               set TMP1 [expr $i*$XSZ]
+                                               set lncol $Blue
+                                               set lnwdt 1
+                                               catch {
+                                                       if {$nwcol($i)} {
+                                                               set lncol "gray"
+                                                               set lnwdt 15
+                                               }       }
+                                               .f$dbox2.c create line \
+                                               $TMP1 $YLOC $TMP1 \
+                                               [expr $YLOC+$YSZ] \
+                                               -width $lnwdt \
+                                               -fill $lncol
+                                       }
+                               }
+                               if {(1+$pno) > $NPR} {
+                                       set NPR [expr $pno+2]
+                                       .f$dbox2.c configure \
+                                        -scrollregion \
+                                        "[expr -$XSZ/2] 0 \
+                                         [expr $NPR*$XSZ] [expr $SMX*$YSZ]"
+                               }
+                               if {$Pstp > $SMX-2} {
+                                       set SMX [expr 2*$SMX]
+                                       .f$dbox2.c configure \
+                                        -scrollregion \
+                                        "[expr -$XSZ/2] 0 \
+                                         [expr $NPR*$XSZ] [expr $SMX*$YSZ]"
+                               }
+
+                               if { [info exists R($pstp,$pno)] == 0 } {
+                                       if {$VERBOSE == 1} {
+                                               if {[string first "~W " $stmnt] == 0} {
+                                                       set BoxFil $White
+                                                       set stmnt [string range $stmnt 3 end] 
+                                               } else { if {[string first "~G " $stmnt] == 0} {
+                                                       set BoxFil $Green
+                                                       set stmnt [string range $stmnt 3 end]
+                                               } else { if {[string first "~R " $stmnt] == 0} {
+                                                       set BoxFil $Red
+                                                       set stmnt [string range $stmnt 3 end]
+                                               } else { if {[string first "~B " $stmnt] == 0} {
+                                                       set BoxFil $Blue
+                                                       set stmnt [string range $stmnt 3 end]
+                                               } else { set BoxFil $Yellow } } } }
+                                               set BoxLab $stmnt
+                                               if {[string first "line " $stmnt] == 0} {
+                                                       scan $stmnt "line %d" pln
+                                                       set Fnm "pan_in"        ;# not necessarily right...
+                                               }
+                                       } else {
+                                               set BoxLab $pstp
+                                               set BoxFil $White
+                                       }
+                                       if {$SparseMsc == 0} {
+                                               set HasBox($YLOC,[expr 1+$pno]) 1
+                                       }
+                                       set R($pstp,$pno) \
+                                               [.f$dbox2.c create rectangle \
+                                                [expr $XLOC-20] $YLOC \
+                                                [expr $XLOC+20] \
+                                                [expr $YLOC+$YSZ] \
+                                                -outline $Blue -fill $BoxFil]
+                                       set T($pstp,$pno) \
+                                               [.f$dbox2.c create text \
+                                                $XLOC \
+                                                [expr $YLOC+$YSZ/2] \
+                                               -font $SmallFont \
+                                               -text $BoxLab]
+                                       #if {$Pstp > $YNR-2} {
+                                       #       .f$dbox2.c yview \
+                                       #        [expr ($Pstp-$YNR)]
+                                       #}
+                               }
+                               if { $HAS == 3 } {
+                                       .f$dbox2.c itemconfigure \
+                                        $R($pstp,$pno) \
+                                        -outline $Red -fill $Yellow
+                               }
+
+                               if {$SYMBOLIC} {
+                                       .f$dbox2.c itemconfigure $T($pstp,$pno) \
+                                               -font $SmallFont -text "$stmnt"
+                               } else {
+                                       if {$VERBOSE == 0 } {
+                                               .f$dbox2.c bind $T($pstp,$pno) <Any-Enter> "
+                                               .f$dbox2.c itemconfigure $T($pstp,$pno) \
+                                                       -font $BigFont -text {$stmnt}
+                                               .inp.t tag remove hilite 0.0 end
+                                               if {[string first "pan_in" $Fnm] >= 0} {
+                                                       src_line $pln
+                                               }
+                                               "
+                                               .f$dbox2.c bind $T($pstp,$pno) <Any-Leave> "
+                                               .f$dbox2.c itemconfigure $T($pstp,$pno) \
+                                                       -font $SmallFont -text {$pstp}
+                                               "
+                                       } else {
+                                               .f$dbox2.c bind $T($pstp,$pno) <Any-Enter> "
+                                               .inp.t tag remove hilite 0.0 end
+                                               if {[string first "pan_in" $Fnm] >= 0} {
+                                                       src_line $pln
+                                               }
+                                               "
+                                       }
+                               }
+                       }
+
+                       set YLOC [expr $YLOC+$YSZ/2]
+                       if {$HAS == 1} {
+                               if { [info exists Q_add($inq)] == 0 } {
+                                       set Q_add($inq) 0
+                                       set Q_del($inq) 0
+                               }
+                               set Slot $Q_add($inq)
+                               incr Q_add($inq) 1
+
+                               set Mesg_y($inq,$Slot) $YLOC
+                               set Mesg_x($inq,$Slot) $XLOC
+                               set Q_val($inq,$Slot) $Mcont
+                       
+                               set Rem($inq,$Slot) \
+                                       [.f$dbox2.c create text \
+                                       [expr $XLOC-40] $YLOC \
+                                       -font $SmallFont -text $stmnt]
+                       } elseif { $HAS == 2 } {
+                               if {$Easy} {
+                                       set Slot $Q_del($inq)
+                                       incr Q_del($inq) 1
+                               } else {
+                                       for {set Slot $Q_del($inq)} \
+                                               {$Slot < $Q_add($inq)} \
+                                               {incr Slot} {
+                                       if {$Q_val($inq,$Slot) == "_X_"} {
+                                                       incr Q_del($inq) 1
+                                               } else {
+                                                       break
+                                       }       }
+
+                                       for {set Slot $Q_del($inq)} \
+                                               {$Slot < $Q_add($inq)} \
+                                               {incr Slot} {
+                                       if {$Mcont == $Q_val($inq,$Slot)} {
+                                               set Q_val($inq,$Slot) "_X_"
+                                               break
+                                       }       }
+                               }
+                               if {$Slot >= $Q_add($inq)} {
+                                       add_log "<<error: cannot match $stmnt>>"
+                               } else {
+                                       set TMP1 $Mesg_x($inq,$Slot)
+                                       set TMP2 $Mesg_y($inq,$Slot)
+                                       if {$XLOC < $TMP1} {
+                                               set Delta -20
+                                       } else {
+                                               set Delta 20
+                                       }
+                                       .f$dbox2.c create line \
+                                               [expr $TMP1+$Delta] $TMP2 \
+                                               [expr $XLOC-$Delta] $YLOC \
+                                               -fill $Red -width 2 \
+                                               -arrow last -arrowshape {5 5 5}
+
+                                       if {$SparseMsc == 0} {
+                                               set TMP3 5
+                                       } else {
+                                               set TMP3 0
+                                       }
+
+                                       .f$dbox2.c coords $Rem($inq,$Slot) \
+                                               [expr ($TMP1 + $XLOC)/2] \
+                                               [expr ($TMP2 + $YLOC)/2 - $TMP3]
+                                       .f$dbox2.c raise $Rem($inq,$Slot)
+                               }
+                       } }
+               }
+               if {$pln == 0 && ($gvars || $lvars || $qv)} {
+                       if {$Vvbox == 0} {
+                               if {$vv} { set Vvbox [mkbox "Data Values" \
+                                       "Vars" "var.out" 71 19 100 350] }
+                       } else {
+                               catch { .c$Vvbox.z.t delete 0.0 end }
+                       }
+                       if {$vv} {
+                               if {$gvars || $lvars} {
+                                       raise .c$Vvbox
+                                       foreach el [lsort [array names Varnm]] {
+                                       if {[string length $Varnm($el)] > 0} {
+                                       catch { .c$Vvbox.z.t insert \
+                                               end "$el = $Varnm($el)\n" }
+                                       }       }
+                               }
+                               if {$qv} {
+                                       foreach el [lsort [array names Queues]] {
+                                       catch {
+                                       .c$Vvbox.z.t insert end "queue $el ($Alias($el))\n"
+                                       .c$Vvbox.z.t insert end "       $Queues($el)\n"
+                                       }       }
+                       }       }
+               }
+       } else {
+                       set stepper 0
+       }
+               if {$isvar == 0} {
+                       if {$syntax == 1} {
+                               if {[string first "..." $line] < 0} {
+                                       add_log "$line"
+                               catch { .c$sbox.z.t insert end "$line\n" }
+                               catch { .c$sbox.z.t yview -pickplace end }
+                               }
+                       } else {
+                               if {[string length $line] > 0} {
+                               catch { .c$sbox.z.t insert end "$line\n" }
+                               catch { .c$sbox.z.t yview -pickplace end }
+                               }
+                               if {$m_typ == 2 && \
+                                       [string first "START OF CYCLE" $line] > 0} {
+                                       catch { .c$dbox.z.t yview -pickplace end }
+                                       catch { .c$dbox.z.t insert end "$line\n" }
+                                       catch {
+                                       set XLOC [expr $Seenpno*$XSZ+$XSZ/2]
+                                       set YLOC [expr $Pstp*$YSZ+$YSZ/2]
+
+                                       .f$dbox2.c create text \
+                                               [expr $XLOC+$XSZ] $YLOC \
+                                               -font $SmallFont \
+                                               -text "Cycle/Waiting" \
+                                               -fill $Red
+
+                                       .f$dbox2.c create line \
+                                               $XLOC $YLOC \
+                                               [expr $XLOC+$XSZ/2] $YLOC \
+                                               -fill $Red \
+                                               -arrow first -arrowshape {5 5 5}
+                                       }
+                                       set HAS_CYCLE [expr $YLOC+1]
+                               }
+                               if {$m_typ == 2 && $HAS == 3 && $HAS_CYCLE != 0} {
+                                       catch {
+                                       set YLOC [expr $Pstp*$YSZ+$YSZ/2]
+                                       set XLOC0 [expr $pno*$XSZ+$XSZ]
+                                       set XLOC [expr $Seenpno*$XSZ+$XSZ]
+                                       .f$dbox2.c create line \
+                                               $XLOC0 [expr $YLOC-$YSZ/2] \
+                                               $XLOC0 $YLOC \
+                                               -fill $Red
+                                       .f$dbox2.c create line \
+                                               $XLOC0 $YLOC $XLOC $YLOC \
+                                               -fill $Red
+
+                                       set XLOC [expr $Seenpno*$XSZ+$XSZ]
+
+                                       .f$dbox2.c create line \
+                                               $XLOC $YLOC $XLOC \
+                                               [expr $HAS_CYCLE-1] \
+                                               -fill $Red
+               }       }       }       }
+               # mystery update:
+               if {$tk_major >= 4 || $m_typ != 1} {
+                       update  ;# tk 3.x can crash on this
+               }
+
+               if {$syntax == 0 \
+               &&  $stop == 0 \
+               &&  $stepped == 1 \
+               &&  $stepper == 0 \
+               &&  $dontwait == 0} {
+                       update  ;# here it is harmless also with tk 3.x
+                       tkwait variable stepper
+               }
+       } else {
+               if {$s_typ == 0 || $s_typ == 2} {
+                       add_log "<at end of run>"
+               } else {
+                       add_log "<at end of trail>"
+               }
+               catch { addscales $dbox2 }
+               if {$ebc} { barscales }
+               update
+               tkwait variable stepper
+       }
+       }
+       # end of guided trail
+
+       while {$stepper == 1} {
+               tkwait variable stepper
+       }
+       teardown
+       
+       catch "close $fd"
+       add_log "<done>"
+
+       update
+}
+
+proc teardown {} {
+       global m_typ pbox sbox dbox Spbox Vvbox
+       global simruns stop stepped stepper howmany
+
+       set simruns 0
+       set stop 1
+       set stepped 0
+       set stepper 0
+       catch { set howmany 0 }
+       catch {
+               if { $m_typ == 1 } {
+                       foreach el [array names pbox] {
+                               catch { destroy .c$pbox($el) }
+                               catch { unset pbox($el) }
+                       }
+               } elseif { $m_typ == 0 } {
+                       foreach el [array names Spbox] {
+                               catch { destroy .c$Spbox($el) }
+                               catch { unset Spbox($el) }
+               }       }
+       }
+       if {[winfo exists .c$sbox]} {
+               set x "Simulation Output"
+               set PlaceBox($x) [wm geometry .c$sbox]
+               set k [string first "\+" $PlaceBox($x)]
+               if {$k > 0} {
+                       set PlaceBox($x) [string range $PlaceBox($x) $k end]
+               }
+               destroy .c$sbox
+       }
+       catch { destroy .c$dbox }
+       if {[winfo exists .c$Vvbox]} {
+               set x "Data Values"
+               set PlaceBox($x) [wm geometry .c$Vvbox]
+               set k [string first "\+" $PlaceBox($x)]
+               if {$k > 0} {
+                       set PlaceBox($x) [string range $PlaceBox($x) $k end]
+               }
+               destroy .c$Vvbox
+       }
+}
+
+set PlaceMenu  "+150+150"
+
+proc pickoption {nm} {
+       global howmany Choice PlaceMenu
+
+       catch {destroy .prompt}
+       toplevel .prompt
+       wm title .prompt "Select"
+       wm iconname .prompt "Select"
+       wm geometry .prompt $PlaceMenu
+
+       text .prompt.t -relief raised -bd 2 \
+               -width [string length $nm] -height 1 \
+               -setgrid 1
+       pack append .prompt .prompt.t { top expand fillx }
+       .prompt.t insert end "$nm"
+       for {set i 0} {$i <= $howmany} {incr i} {
+               if {[info exists Choice($i)] \
+               &&  $Choice($i) != 0 \
+               &&  [string first "outside range" $Choice($i)] < 0 \
+               &&  [string first "unexecutable," $Choice($i)] <= 0} {
+                       pack append .prompt \
+                         [button .prompt.b$i -text "$i: $Choice($i)" \
+                         -anchor w \
+                         -command "set howmany $i" ] \
+                         {top expand fillx}
+
+                       set j [string first "line " $Choice($i)]
+                       if {$j > 0} {
+                         set k [string range $Choice($i) $j end]
+                         scan $k "line %d" k
+                         bind .prompt.b$i <Enter> "report $k"
+                         bind .prompt.b$i <Leave> "report 0"
+                         bind .prompt.b$i <ButtonRelease-1> "set howmany $i"
+       }       }       }
+       tkwait variable howmany
+       set PlaceMenu [wm geometry .prompt]
+       set k [string first "\+" $PlaceMenu]
+       if {$k > 0} {
+               set PlaceMenu [string range $PlaceMenu $k end]
+       }
+       catch { foreach el [array names Choice]  { unset Choice($el) } }
+       destroy .prompt
+}
+
+proc report {n} {
+       .inp.t tag remove hilite 0.0 end
+       if {$n > 0} { src_line $n }
+}
+
+# validation options panel
+
+set an_typ -1; set cp_typ 0; set cyc_typ 0
+set as_typ -1;  set ie_typ 1; set ebc 0
+set ct_typ 0;  set et_typ 1
+set st_typ 0;  set se_typ 0; set bf_typ 0
+set oct_typ -1;        # remembers last setting used for compilation
+set nv_typ 1
+set po_typ -1; set cm_typ 0; set vb_typ 0
+set pr_typ 0;  set where 0
+set vr_typ 0;  set xu_typ -1
+set ur_typ 1;  set vbox 0
+set killed 0;  set Job_Done 0; set tcnt 0
+set waitwhat "none"
+set not_warned_yet 1
+
+set LastGenerate       ""
+set LastCompile        ""
+set NextCompile        ""
+
+proc syntax_check {a T} {
+       global SPIN BG FG
+
+       mkpan_in
+       add_log "$SPIN $a pan_in"
+       catch {exec $SPIN $a pan_in >&pan.tmp} err ;# added -v
+       set cnt 0
+       set maxln 50
+       set ef [open pan.tmp r]
+       .inp.t tag remove hilite 0.0 end
+       .inp.t tag remove sel 0.0 end
+       set pln 0
+       set allmsg ""
+       while {[gets $ef line] > -1} {
+               add_log "$line"
+               set allmsg "$allmsg\n$line"
+               if {[string first "spin: line" $line] >= 0} {
+                       scan $line "spin: line %d" pln
+                       src_line $pln
+               }
+               if {[string first "spin: warning, line" $line] >= 0} {
+                       scan $line "spin: warning, line %d" pln
+                       src_line $pln
+               }
+               incr cnt
+       }
+       close $ef
+       if {$cnt == 0} { add_log "no syntax errors" } else {
+               warner $T "$allmsg" 800
+       }
+       update
+}
+
+proc prescan {} {
+       global an_typ cp_typ nv_typ po_typ
+       global xu_typ as_typ ie_typ
+
+       mkpan_in
+
+       if {$an_typ == -1} {
+               set an_typ 0
+               set nv_typ [hasWord "never"]
+               if {[hasWord "accept.*:"]} {
+                       set an_typ 1
+                       set cp_typ 2
+               } elseif {[hasWord "progress.*:"]} {
+                       set an_typ 1
+                       set cp_typ 1
+               }
+       }
+       if {$po_typ == -1} {
+               if {[hasWord "_last"] \
+               ||  [hasWord "provided.*\\("] \
+               ||  [hasWord "enabled\\("]} {
+                       set po_typ 0
+               } else {
+                       set po_typ 1
+               }
+       }
+       if {$xu_typ == -1} {
+               if {[hasWord "xr"] || [hasWord "xs"]} {
+                       set xu_typ 1
+               } else {
+                       set xu_typ 0
+               }
+       }
+       if {$as_typ == -1} {
+               if {$an_typ == 0} {
+                       set as_typ [hasWord "assert"]
+                       set ie_typ 1
+               } else {
+                       set as_typ 0
+                       set ie_typ 0
+               }
+       }
+}
+
+proc basicval2 {} {
+       global e ival expl HelvBig PlaceSim
+       global an_typ cp_typ nv_typ firstime
+       global cyc_typ ct_typ lt_typ
+       global et_typ st_typ se_typ bf_typ stop
+       global vb_typ pr_typ vr_typ ur_typ xu_typ
+
+       set nv_typ 1
+       set an_typ 1
+       set cp_typ 2
+
+       dump_tl "pan.ltl"
+
+       catch { .menu.run.m entryconfigure 8 -state normal }
+       catch { .tl.results.top.rv configure -state normal }
+       set stop 0
+       set firstime 0
+       set lt_typ 1
+
+       catch {destroy .v}
+       toplevel .v
+
+       set k [string first "\+" $PlaceSim]
+       if {$k > 0} {
+               set PlaceSim [string range $PlaceSim $k end]
+       }
+
+       wm title .v "LTL Verification Options"
+       wm iconname .v "VAL"
+       wm geometry .v $PlaceSim
+
+       prescan
+
+       frame .v.correct -relief flat -borderwidth 1m
+       frame .v.cframe  -relief raised -borderwidth 1m
+
+       set z .v.correct
+
+       frame $z.rframe  -relief raised -borderwidth 1m
+
+       label $z.rframe.lb \
+               -font $HelvBig \
+               -text "Options" \
+               -relief sunken -borderwidth 1m
+
+       checkbutton $z.rframe.fc -text "With Weak Fairness" \
+               -variable cyc_typ \
+               -relief flat 
+       checkbutton $z.rframe.xu -text "Check xr/xs Assertions" \
+               -variable xu_typ \
+               -relief flat
+
+       pack append $z.rframe \
+               $z.rframe.lb {top pady 4 frame w fillx} \
+               $z.rframe.fc {top pady 4 frame w} \
+               $z.rframe.xu {top pady 4 frame w filly}
+
+       pack append $z $z.rframe {top frame nw filly}
+
+       label .v.cframe.lb \
+               -font $HelvBig \
+               -text "Verification" \
+               -relief sunken -borderwidth 1m
+
+       radiobutton .v.cframe.ea -text "Exhaustive" \
+               -variable ct_typ -value 0 \
+               -relief flat 
+       radiobutton .v.cframe.sa -text "Supertrace/Bitstate" \
+               -variable ct_typ -value 1 \
+               -relief flat 
+       radiobutton .v.cframe.hc -text "Hash-Compact" \
+               -variable ct_typ -value 2 \
+               -relief flat 
+
+       pack append .v.cframe .v.cframe.lb {top pady 4 frame nw fillx} \
+               .v.cframe.ea {top pady 4 frame nw} \
+               .v.cframe.sa {top pady 4 frame nw} \
+               .v.cframe.hc {top pady 4 frame nw}
+
+       frame .v.pf -relief raised -borderwidth 1m
+       frame .v.pf.mesg -borderwidth 1m
+       
+       label .v.pf.mesg.loss0 \
+               -font $HelvBig \
+               -text "A Full Queue" \
+               -relief sunken -borderwidth 1m
+       radiobutton .v.pf.mesg.loss1 -text "Blocks New Msgs" \
+               -variable l_typ -value 0 \
+               -relief flat
+       radiobutton .v.pf.mesg.loss2 -text "Loses New Msgs" \
+               -variable l_typ -value 1 \
+               -relief flat
+       pack append .v.pf.mesg \
+               .v.pf.mesg.loss0 {top pady 4 frame w expand fillx} \
+               .v.pf.mesg.loss1 {top pady 4 frame w} \
+               .v.pf.mesg.loss2 {top pady 4 frame w}
+       pack append .v.pf \
+               .v.pf.mesg   {left frame w expand fillx}
+
+       pack append .v \
+               .v.cframe  {top frame w fill}\
+               .v.correct {top frame w fill}\
+               .v.pf {top frame w expand fill}
+
+       pack append .v [button .v.adv -text "\[Set Advanced Options]" \
+               -command "advanced_val" ] {top fillx}
+       pack append .v [button .v.run -text "Run" \
+               -command {runval ".tl.results.t"} ] {right frame se}
+       pack append .v [button .v.exit -text "Cancel" \
+               -command "set PlaceSim [wm geometry .v]; \
+               set stop 1; destroy .v"] {right frame se}
+       pack append .v [button .v.help -text "Help" -fg red \
+               -command "roadmap2f" ] {right frame se}
+
+       tkwait visibility .v
+       raise .v
+}
+
+set PlaceBasic "+200+10"
+set PlaceAdv   "+150+10"
+
+proc basicval {} {
+       global e ival expl HelvBig PlaceBasic
+       global an_typ nv_typ firstime as_typ ie_typ
+       global cyc_typ ct_typ lt_typ as_typ ie_typ
+       global et_typ st_typ se_typ bf_typ stop
+       global vb_typ pr_typ vr_typ ur_typ xu_typ
+
+       catch { .menu.run.m entryconfigure 8 -state normal }
+       catch { .tl.results.top.rv configure -state normal }
+       set stop 0
+       set firstime 0
+       set lt_typ 0
+
+       catch {destroy .v}
+       toplevel .v
+
+       wm title .v "Basic Verification Options"
+       wm iconname .v "VAL"
+       wm geometry .v $PlaceBasic
+
+       prescan
+
+       frame .v.correct -relief flat -borderwidth 1m
+       frame .v.cframe  -relief raised -borderwidth 1m
+
+       set z .v.correct
+
+       frame $z.rframe  -relief raised -borderwidth 1m
+
+       label $z.rframe.lb \
+               -font $HelvBig \
+               -text "Correctness Properties" \
+               -relief sunken -borderwidth 1m
+       radiobutton $z.rframe.sp -text "Safety (state properties)" \
+               -variable an_typ -value 0 \
+               -relief flat \
+               -command { set cyc_typ 0; set cp_typ 0
+                       if {$an_typ == 0} {
+                               set as_typ [hasWord "assert"]
+                               set ie_typ 1
+                       }
+                }
+       frame $z.rframe.sf
+       checkbutton $z.rframe.sf.as -text "Assertions" \
+               -variable as_typ \
+               -relief flat \
+               -command {
+                       set an_typ 0
+                       if {![hasWord "assert"] && $as_typ==1} then {
+                               complain6
+                       }
+                }
+       checkbutton $z.rframe.sf.ie -text "Invalid Endstates" \
+               -variable ie_typ \
+               -relief flat \
+               -command { set an_typ 0 }
+
+       frame $z.rframe.sf.fill -width 15
+       pack append $z.rframe.sf \
+               $z.rframe.sf.fill {left frame w} \
+               $z.rframe.sf.as {top pady 4 frame w} \
+               $z.rframe.sf.ie {top pady 4 frame w}
+
+       radiobutton $z.rframe.cp -text "Liveness (cycles/sequences)" \
+               -variable an_typ -value 1 \
+               -relief flat \
+               -command {
+                       set as_typ 0; set ie_typ 0
+                       if {[hasWord "accept"]} then { set cp_typ 2 }\
+                       elseif {[hasWord "progress"]} then { set cp_typ 1 } \
+                       else complain5
+               }
+
+       frame $z.rframe.sub
+       radiobutton $z.rframe.sub.np -text "Non-Progress Cycles" \
+               -variable cp_typ -value 1 \
+               -relief flat \
+               -command {
+                       set an_typ 1
+                       if {![hasWord "progress"] && $cp_typ==1} then {
+                               complain4
+                       }
+                }
+       radiobutton $z.rframe.sub.ac -text "Acceptance Cycles" \
+               -variable cp_typ -value 2 \
+               -relief flat \
+               -command {
+                       set an_typ 1
+                       if {![hasWord "accept"] && $cp_typ==2} then {
+                               complain1
+                       }
+               }
+       checkbutton $z.rframe.sub.fc -text "With Weak Fairness" \
+               -variable cyc_typ \
+               -relief flat  \
+               -command { if {$an_typ==0} then "set cyc_typ 0; complain3" }
+
+       checkbutton $z.rframe.nv -text "Apply Never Claim (If Present)" \
+               -variable nv_typ \
+               -relief flat \
+               -command { if {![hasWord "never"] && $nv_typ==1} then "complain2" }
+       checkbutton $z.rframe.ur -text "Report Unreachable Code" \
+               -variable ur_typ \
+               -relief flat
+       checkbutton $z.rframe.xu -text "Check xr/xs Assertions" \
+               -variable xu_typ \
+               -relief flat
+
+       frame $z.rframe.sub.fill -width 15
+       pack append $z.rframe.sub \
+               $z.rframe.sub.fill {left frame w} \
+               $z.rframe.sub.np {top pady 4 frame w} \
+               $z.rframe.sub.ac {top pady 4 frame w} \
+               $z.rframe.sub.fc {top pady 4 frame w}
+
+       pack append $z.rframe \
+               $z.rframe.lb {top pady 4 frame w fillx} \
+               $z.rframe.sp {top pady 4 frame w} \
+                       $z.rframe.sf {top pady 4 frame w} \
+               $z.rframe.cp {top pady 4 frame w} \
+                       $z.rframe.sub {top pady 4 frame w} \
+               $z.rframe.nv {top pady 4 frame w} \
+               $z.rframe.ur {top pady 4 frame w} \
+               $z.rframe.xu {top pady 4 frame w filly}
+
+       pack append $z $z.rframe {top frame nw filly}
+
+       label .v.cframe.lb \
+               -font $HelvBig \
+               -text "Search Mode" \
+               -relief sunken -borderwidth 1m
+
+       radiobutton .v.cframe.ea -text "Exhaustive" \
+               -variable ct_typ -value 0 \
+               -relief flat 
+       radiobutton .v.cframe.sa -text "Supertrace/Bitstate" \
+               -variable ct_typ -value 1 \
+               -relief flat 
+       radiobutton .v.cframe.hc -text "Hash-Compact" \
+               -variable ct_typ -value 2 \
+               -relief flat 
+
+       pack append .v.cframe .v.cframe.lb {top pady 4 frame nw fillx} \
+               .v.cframe.ea {top pady 4 frame nw} \
+               .v.cframe.sa {top pady 4 frame nw} \
+               .v.cframe.hc {top pady 4 frame nw}
+
+       frame .v.pf -relief raised -borderwidth 1m
+       frame .v.pf.mesg -borderwidth 1m
+       
+       label .v.pf.mesg.loss0 \
+               -font $HelvBig \
+               -text "A Full Queue" \
+               -relief sunken -borderwidth 1m
+       radiobutton .v.pf.mesg.loss1 -text "Blocks New Msgs" \
+               -variable l_typ -value 0 \
+               -relief flat
+       radiobutton .v.pf.mesg.loss2 -text "Loses New Msgs" \
+               -variable l_typ -value 1 \
+               -relief flat
+       pack append .v.pf.mesg \
+               .v.pf.mesg.loss0 {top pady 4 frame w fillx} \
+               .v.pf.mesg.loss1 {top pady 4 frame w} \
+               .v.pf.mesg.loss2 {top pady 4 frame w}
+       pack append .v.pf \
+               .v.pf.mesg {left frame nw expand fill}
+
+       pack append .v \
+               .v.correct {left} \
+               .v.cframe  {top frame n expand fill}\
+               .v.pf {top frame n expand fill}
+
+       pack append .v [button .v.nvr -text "\[Add Never Claim from File]" \
+               -command "call_nvr" ] {top fillx}
+       pack append .v [button .v.ltl -text "\[Verify an LTL Property]" \
+               -command "destroy .v; call_tl" ] {top fillx}
+       pack append .v [button .v.adv -text "\[Set Advanced Options]" \
+               -command "advanced_val" ] {top fillx}
+       pack append .v [button .v.run -text "Run" \
+               -command {set PlaceBasic [wm geometry .v]; runval "0"} ] {right frame se}
+       pack append .v [button .v.exit -text "Cancel" \
+               -command {set PlaceBasic [wm geometry .v]; \
+               set stop 1; destroy .v}] {right frame se}
+       pack append .v [button .v.help -text "Help" -fg red \
+               -command "roadmap2e" ] {right frame se}
+
+       tkwait visibility .v
+       raise .v
+}
+
+set HasNever ""
+
+proc call_nvr {} {
+       global HasNever
+       global xversion Fname nv_typ
+
+       switch [info commands tk_getOpenFile] "" {
+               set fileselect "FileSelect open"
+       } default {
+               set fileselect "tk_getOpenFile \
+                       -filetypes { \
+                               { { Aut files }  .aut } \
+                               { { Nvr files }  .nvr } \
+                               { { All Files }   *   } \
+                               }"
+       }
+
+       set HasNever [eval $fileselect]
+
+       if {$HasNever == ""} {
+               wm title . "SPIN CONTROL $xversion -- File: $Fname"
+               set nv_typ 0
+       } else {
+               set nv_typ 1
+               set z [string last "\/" $HasNever]
+               if {$z > 0} {
+                       incr z
+                       set HsN [string range $HasNever $z end]
+               } else {
+                       set HsN $HasNever
+               }
+               wm title . "SPIN CONTROL $xversion -- File: $Fname  Claim: $HsN"
+       }
+}
+
+proc advanced_val {} {
+       global e ival expl HelvBig
+       global nv_typ firstime PlaceAdv
+       global cyc_typ ct_typ
+       global et_typ st_typ se_typ bf_typ stop po_typ cm_typ
+       global vb_typ pr_typ vr_typ ur_typ xu_typ
+
+       catch { .menu.run.m entryconfigure 8 -state normal }
+       catch { .tl.results.top.rv configure -state normal }
+       set stop 0
+       set firstime 0
+
+       catch {destroy .av}
+       toplevel .av
+
+       wm title .av "Advanced Verification Options"
+       wm iconname .av "VAL"
+       wm geometry .av $PlaceAdv
+
+       frame .av.pans
+       frame .av.pans.correct -relief flat
+       frame .av.memopts -relief flat;         # memory options panel
+       frame .av.oframe  -relief raised -borderwidth 1m ;# error trail options
+       frame .av.recomp  -relief raised -borderwidth 1m ;# recompilation
+
+       prescan
+
+       for {set x 0} {$x<=2} {incr x} {
+               frame .av.memopts.choice$x -relief flat
+               entry .av.memopts.choice$x.e1 -relief sunken -width 20
+               label .av.memopts.choice$x.e2 -text $e($x) -relief flat
+               .av.memopts.choice$x.e1 insert end $ival($x)
+
+               pack append .av.memopts.choice$x \
+                       .av.memopts.choice$x.e2 {left  frame w fillx} \
+                       [button .av.memopts.choice$x.e3 -text $expl($x) \
+                       -command "d_list $x" ] {right frame e} \
+                       .av.memopts.choice$x.e1 {right frame e fillx}
+
+               pack append .av.memopts \
+                       .av.memopts.choice$x { top frame w pady 5 fillx}
+       }
+       for {set x 7} {$x<=7} {incr x} {
+               frame .av.memopts.choice$x -relief flat
+               entry .av.memopts.choice$x.e1 -relief sunken -width 20
+               label .av.memopts.choice$x.e2 -text $e($x) -relief flat
+               .av.memopts.choice$x.e1 insert end $ival($x)
+
+               pack append .av.memopts.choice$x \
+                       .av.memopts.choice$x.e2 {left  frame w fillx} \
+                       [button .av.memopts.choice$x.e3 -text $expl($x) \
+                       -command "d_list $x" ] {right frame e} \
+                       .av.memopts.choice$x.e1 {right frame e fillx}
+
+               pack append .av.memopts \
+                       .av.memopts.choice$x { top frame w pady 5 fillx}
+       }
+       for {set x 3} {$x<=5} {incr x} {
+               frame .av.memopts.choice$x -relief flat
+               entry .av.memopts.choice$x.e1 -relief sunken -width 20
+               label .av.memopts.choice$x.e2 -text $e($x) -relief flat
+               .av.memopts.choice$x.e1 insert end $ival($x)
+
+               pack append .av.memopts.choice$x \
+                       .av.memopts.choice$x.e2 {left  frame w fillx} \
+                       [button .av.memopts.choice$x.e3 -text $expl($x) \
+                       -command "d_list $x" ] {right frame e} \
+                       .av.memopts.choice$x.e1 {right frame e fillx}
+
+               pack append .av.memopts \
+                       .av.memopts.choice$x { top frame w pady 5 fillx}
+       }
+       set z .av.pans.correct
+       frame $z.rframe  -relief raised -borderwidth 1m
+       label $z.rframe.lb3 \
+               -font $HelvBig \
+               -text "   Error Trapping   " \
+               -relief sunken -borderwidth 1m
+       radiobutton $z.rframe.c0 -text "Don't Stop at Errors" \
+               -variable et_typ -value 0 \
+               -relief flat 
+       checkbutton $z.rframe.c0a -text "Save All Error-trails" \
+               -variable st_typ \
+               -relief flat 
+       checkbutton $z.rframe.c0b -text "Find Shortest Trail (iterative)" \
+               -variable se_typ \
+               -relief flat
+       checkbutton $z.rframe.c0c -text "Use Breadth-First Search" \
+               -variable bf_typ \
+               -relief flat
+       frame  $z.rframe.basic1 
+
+       frame $z.rframe.cc
+       radiobutton $z.rframe.cc.c1 -text "Stop at Error Nr:" \
+               -variable et_typ -value 1 \
+               -relief flat 
+       entry $z.rframe.cc.c2 -relief sunken -width 8
+       $z.rframe.cc.c2 insert end "$ival(6)"
+       pack append $z.rframe.cc \
+               $z.rframe.cc.c1 {left}\
+               $z.rframe.cc.c2 {right expand fillx}
+
+       pack append $z.rframe \
+               $z.rframe.lb3 { top expand fillx frame nw} \
+               $z.rframe.cc  {top pady 4 frame w} \
+               $z.rframe.c0  {top pady 4 frame w} \
+               $z.rframe.c0a {top pady 4 frame w} \
+               $z.rframe.c0b {top pady 4 frame w} \
+               $z.rframe.c0c {top pady 4 frame w} \
+               $z.rframe.basic1 {top frame w}
+       pack append $z $z.rframe {top frame nw expand fill}
+
+       frame .av.pans.pf -relief flat
+       set z .av.pans.pf
+       frame $z.mesg -relief raised -borderwidth 1m;           # queue loss options
+       frame $z.pframe -relief raised -borderwidth 1m
+       label $z.pframe.lb2 \
+               -font $HelvBig \
+               -text "   Type of Run   " \
+               -relief sunken -borderwidth 1m
+       checkbutton $z.pframe.po -text "Use Partial Order Reduction" \
+               -variable po_typ \
+               -relief flat 
+       checkbutton $z.pframe.cm -text "Use Compression" \
+               -variable cm_typ \
+               -relief flat 
+#      checkbutton $z.pframe.vb -text "Verbose (For Debugging Only)" \
+#              -variable vb_typ \
+#              -relief flat
+       checkbutton $z.pframe.pr -text "Add Complexity Profiling" \
+               -variable pr_typ \
+               -relief flat
+       checkbutton $z.pframe.vr -text "Compute Variable Ranges" \
+               -variable vr_typ \
+               -relief flat
+
+       pack append $z.pframe \
+               $z.pframe.lb2 {top fillx pady 4 frame w} \
+               $z.pframe.po {top pady 4 frame w} \
+               $z.pframe.cm {top pady 4 frame w} \
+               $z.pframe.pr  {top pady 4 frame w} \
+               $z.pframe.vr  {top pady 4 frame w}
+
+       pack append .av.pans.pf \
+               .av.pans.pf.pframe  {top frame nw expand fill}
+       pack append .av.pans \
+               .av.pans.correct {left frame nw expand fillx}\
+               .av.pans.pf {left frame nw expand fillx}
+
+       button .av.help -text "Help" -fg red -command "roadmap2d"
+       button  .av.basic1 -text "Set" -fg red -command "stopval 1" 
+       button  .av.basic0 -text "Cancel" -command "stopval 0" 
+
+       pack append .av \
+               .av.memopts {top frame w} \
+               .av.pans {top fillx} \
+               .av.help  {left frame w} \
+               .av.basic1 {right frame e} \
+               .av.basic0 {right frame e}
+
+       raise .av
+}
+
+proc g_list {} {
+       global FG BG
+
+       catch {destroy .r}
+       toplevel .r
+
+       wm title .r "Options"
+       wm iconname .r "Options"
+
+       frame .r.top
+               listbox .r.top.list -width  6 -height 3 -relief raised
+               listbox .r.top.expl -width 40 -height 3  -relief flat
+       pack append .r.top \
+               .r.top.list {left}\
+               .r.top.expl {left}
+       frame .r.bot
+               text .r.bot.text -width 40 -height 1 -relief flat
+               .r.bot.text insert end "(Double-Click option or Cancel)"
+               button .r.bot.quit -text "Cancel" -command "destroy .r"
+       pack append .r.bot \
+               .r.bot.text {top}\
+               .r.bot.quit {frame s}
+
+       frame .r.caps
+               text .r.caps.cap1 -width 6 -height -1 -fg blue
+               text .r.caps.cap2 -width 30 -height -1 -fg blue
+               .r.caps.cap1 insert end "Option:"
+               .r.caps.cap2 insert end "Meaning:"
+       pack append .r.caps \
+               .r.caps.cap1 {left} \
+               .r.caps.cap2 {left}
+
+       pack append .r \
+               .r.caps  {frame w}\
+               .r.top {top expand} \
+               .r.bot {bottom expand}
+
+       foreach i { "-o1" "-o2" "-o3" } {
+               .r.top.list insert end $i
+       }
+       foreach i { \
+               "disable dataflow-optimizations" \
+               "disable dead variables elimination" \
+               "disable statement merging" } {
+               .r.top.expl insert end $i
+       }
+       bind .r.top.list <Double-Button-1> {
+               set extra [selection get]
+               .av.memopts.choice5.e1 insert end " $extra"
+               destroy .r
+       }
+}
+
+proc r_list {} {
+       global FG BG
+
+       catch {destroy .r}
+       toplevel .r
+
+       wm title .r "Options"
+       wm iconname .r "Options"
+
+       frame .r.top
+               listbox .r.top.list -width  6 -height 8 -relief raised
+               listbox .r.top.expl -width 40 -height 8  -relief flat
+       pack append .r.top \
+               .r.top.list {left}\
+               .r.top.expl {left}
+       frame .r.bot
+               text .r.bot.text -width 40 -height 1 -relief flat
+               .r.bot.text insert end "(Double-Click option or Cancel)"
+               button .r.bot.quit -text "Cancel" -command "destroy .r"
+       pack append .r.bot \
+               .r.bot.text {top}\
+               .r.bot.quit {frame s}
+
+       frame .r.caps
+               text .r.caps.cap1 -width 6 -height -1 -fg blue
+               text .r.caps.cap2 -width 30 -height -1 -fg blue
+               .r.caps.cap1 insert end "Option:"
+               .r.caps.cap2 insert end "Meaning:"
+       pack append .r.caps \
+               .r.caps.cap1 {left} \
+               .r.caps.cap2 {left}
+
+       pack append .r \
+               .r.caps  {frame w}\
+               .r.top {top expand} \
+               .r.bot {bottom expand}
+
+       foreach i { "-d" "-q" "-I" "-h?" "-s" "-A" "-E" "-w?" } {
+               .r.top.list insert end $i
+       }
+       foreach i { \
+               "print state tables and stop" \
+               "require all chans to be empty in valid endstates" \
+               "try to find shortest trail" \
+               "choose another seed for hash 1..32 (default 1)" \
+               "use 1-bit hashing (default is 2-bit)" \
+               "ignore assertion violation errors" \
+               "ignore invalid endstate errors" \
+               "set explicit -w parameter" \
+               "" } {
+               .r.top.expl insert end $i
+       }
+       bind .r.top.list <Double-Button-1> {
+               set extra [selection get]
+               .av.memopts.choice4.e1 insert end " $extra"
+               destroy .r
+       }
+}
+
+proc d_list {nr} {
+
+       if {$nr == 0} { roadmap2a; return }
+       if {$nr == 1} { roadmap2b; return }
+       if {$nr == 2} { roadmap2c; return }
+       if {$nr == 4} { r_list; return }
+       if {$nr == 5} { g_list; return }
+       if {$nr == 7} { roadmap2k; return }
+#      if {$nr != 3} { roadmap2; return }
+
+       catch {destroy .b}
+       toplevel .b
+
+       wm title .b "Options"
+       wm iconname .b "Options"
+
+       frame .b.top
+               scrollbar .b.top.scroll -command ".b.top.list yview"
+               listbox   .b.top.list -yscroll ".b.top.scroll set" -relief raised
+       pack append .b.top \
+               .b.top.scroll {right filly}\
+               .b.top.list {left expand}
+
+       frame .b.bot
+               text .b.bot.text -width 21 -height 1 -relief flat
+               .b.bot.text insert end "(Double-Click option)"
+               button .b.bot.quit -text "Cancel" -command "destroy .b"
+               button .b.bot.expl -text "Explanations" -command "roadmap6"
+       pack append .b.bot \
+               .b.bot.text {top frame nw}\
+               .b.bot.expl {left}\
+               .b.bot.quit {left}
+
+
+       pack append .b \
+               .b.top {top frame nw expand} \
+               .b.bot {bottom}
+
+       foreach i { \
+               "-DBCOMP" \
+               "-DCTL" \
+               "-DGLOB_ALPHA" \
+               "-DMA=?" \
+               "-DNFAIR=?" \
+               "-DNIBIS" \
+               "-DNOBOUNDCHECK" \
+               "-DNOREDUCE" \
+               "-DNOCOMP" \
+               "-DNOSTUTTER" \
+               "-DNOVSZ" \
+               "-DPRINTF" \
+               "-DRANDSTORE=?" \
+               "-DR_XPT" \
+               "-DSDUMP" \
+               "-DSVDUMP" \
+               "-DVECTORSZ=?" \
+               "-DW_XPT=?" \
+               "-DXUSAFE" \
+               } {
+               .b.top.list insert end $i
+       }
+       bind .b.top.list <Double-Button-1> {
+               set directive [selection get]
+               .av.memopts.choice3.e1 insert end " $directive"
+               destroy .b
+       }
+}
+
+proc complain1 {} {
+       set m "warning: there are no accept labels"
+       add_log $m
+       catch { tk_messageBox -icon info -message $m }
+}
+
+proc complain2 {} {
+       set m "warning: there is no never claim"
+       add_log $m
+       catch { tk_messageBox -icon info -message $m }
+}
+
+proc complain3 {} {
+       set m "weak fairness is irrelevant to state properties"
+       add_log $m
+       catch { tk_messageBox -icon info -message $m }
+}
+
+proc complain4 {} {
+       set m "warning: there are no progress labels"
+       add_log $m
+       catch { tk_messageBox -icon info -message $m }
+}
+
+proc complain5 {} {
+       global an_typ
+       set m "warning: there are neither accept nor progress labels"
+       add_log $m
+       set an_typ 0
+       catch { tk_messageBox -icon info -message $m }
+}
+
+proc complain6 {} {
+       set m "warning: there are no assert statements in the spec"
+       add_log $m
+       catch { tk_messageBox -icon info -message $m }
+}
+
+proc complain7 {} {
+       set m "warning: Breadth-First Search implies a restriction to Safety properties"
+       add_log $m
+       catch { tk_messageBox -icon info -message $m }
+}
+
+proc complain8 {} {
+       set m "error: cannot combine -DMA and -DBITSTATE"
+       add_log $m
+       catch { tk_messageBox -icon info -message $m }
+}
+
+proc stopval {how} {
+       global stop ival PlaceAdv
+
+       if {$how} {
+       set ival(0) "[.av.memopts.choice0.e1 get]"
+       set ival(1) "[.av.memopts.choice1.e1 get]"
+       set ival(2) "[.av.memopts.choice2.e1 get]"
+       set ival(3) "[.av.memopts.choice3.e1 get]"
+       set ival(4) "[.av.memopts.choice4.e1 get]"
+       set ival(5) "[.av.memopts.choice5.e1 get]"
+       set ival(7) "[.av.memopts.choice7.e1 get]"
+       set ival(6) "[.av.pans.correct.rframe.cc.c2 get]"
+       }
+       set stop 1
+       if {[winfo exists .av]} {
+               set PlaceAdv [wm geometry .av]
+               set k [string first "\+" $PlaceAdv]
+               if {$k > 0} {
+                       set PlaceAdv [string range $PlaceAdv $k end]
+               }
+               destroy .av
+       }
+}
+
+proc log {n} {
+       set m 1
+       set cnt 0
+       while {$m<$n} {
+               set m [expr $m*2]
+               incr cnt
+       }
+       return $cnt
+}
+
+proc bld_v_options {} {
+       global an_typ cp_typ cyc_typ as_typ ie_typ
+       global et_typ st_typ se_typ l_typ bf_typ
+       global ct_typ ival v_options a_options
+       global c_options po_typ cm_typ vb_typ
+       global pr_typ vr_typ ur_typ xu_typ
+       global ol_typ oct_typ nv_typ lt_typ
+
+       set ol_typ $l_typ
+       set oct_typ $ct_typ
+
+       set a_options "-a -X"
+       if {$l_typ==1}  { set a_options [format "%s -m" $a_options] }
+       if {$lt_typ==1} { set a_options [format "%s -N pan.ltl" $a_options] }
+
+       set Mbytes $ival(0)
+       catch { set Mbytes [.av.memopts.choice0.e1 get] }
+
+       # the Mstate scale resolution is in thousands: 2^10
+       set Mstate [expr 10+[log $ival(1)]]
+       catch { set Mstate [expr 10+[log [.av.memopts.choice1.e1 get]]] }
+       set Mdepth $ival(2)
+       catch { set Mdepth [.av.memopts.choice2.e1 get] }
+       catch { set ival(0) "[.av.memopts.choice0.e1 get]" }
+       catch { set ival(1) "[.av.memopts.choice1.e1 get]" }
+       catch { set ival(2) "[.av.memopts.choice2.e1 get]" }
+       catch { set ival(3) "[.av.memopts.choice3.e1 get]" }
+       catch { set ival(4) "[.av.memopts.choice4.e1 get]" }
+       catch { set ival(5) "[.av.memopts.choice5.e1 get]" }
+       catch { set ival(7) "[.av.memopts.choice7.e1 get]" }
+
+       if {$ct_typ == 2} {     ;# hash-compact
+               set c_options [format "-DHC -DMEMLIM=%d" $Mbytes]
+
+               # in exhaustive mode: #hashtable ~~ #states
+
+               set v_options "-X -m$Mdepth -w$Mstate"
+
+               if {$Mstate >= $Mbytes} {
+               catch {
+               tk_messageBox -icon info \
+                       -message "The Estimated Statespace size exceeds \
+the maximum that the Memory limit you set would allow."
+               }
+                       return 0
+               }
+       } elseif {$ct_typ==1}   {
+               set c_options [format "-DBITSTATE -DMEMLIM=%d" $Mbytes]
+
+               # in supertrace mode: #bits ~~ 128x #states
+               # (effectively the #bytes will be ~~ 16x #states)
+
+               set Mstate [expr 7+$Mstate]
+               set v_options "-X -m$Mdepth -w$Mstate"
+
+               if {$Mstate-3 >= $Mbytes} {
+               catch {
+               tk_messageBox -icon info \
+                       -message "The Estimated Statespace size exceeds \
+maximum allowed by the Memory limit that you set would allow."
+               }
+                       return 0
+               }
+       } else {
+               set c_options [format "-DMEMLIM=%d" $Mbytes]
+
+               # in exhaustive mode: #hashtable ~~ #states
+
+               set v_options "-X -m$Mdepth -w$Mstate"
+
+               if {$Mstate >= $Mbytes} {
+               catch {
+               tk_messageBox -icon info \
+                       -message "The Estimated Statespace size exceeds \
+the maximum that the Physical Memory limit allows."
+               }
+                       return 0
+               }
+       }
+       set c_options [format "-D_POSIX_SOURCE %s" $c_options]
+       if {$an_typ==0} { set c_options [format "%s -DSAFETY" $c_options] }
+       if {$an_typ==1 && $cp_typ==1}   { set c_options [format "%s -DNP" $c_options] }
+       if {$po_typ==0} { set c_options [format "%s -DNOREDUCE" $c_options] }
+       if {$cm_typ==1 && $ct_typ!=1}   { set c_options [format "%s -DCOLLAPSE" $c_options] }
+       if {$vb_typ==1} { set c_options [format "%s -DCHECK" $c_options] }
+       if {$nv_typ==0} { set c_options [format "%s -DNOCLAIM" $c_options] }
+       if {$se_typ!=0} { set c_options [format "%s -DREACH" $c_options] }
+       if {$bf_typ!=0} {
+               if {$an_typ != 0} {
+                       complain7
+                       set c_options [format "%s -DBFS -DSAFETY" $c_options]
+               } else {
+                       set c_options [format "%s -DBFS" $c_options]
+       }       }
+       if {$xu_typ==0 && $po_typ!=0}   { set c_options [format "%s -DXUSAFE" $c_options] }
+       if {$pr_typ==1} { set c_options [format "%s -DPEG" $c_options] }
+       if {$vr_typ==1} { set c_options [format "%s -DVAR_RANGES" $c_options] }
+       if {$cyc_typ==1}        {
+               set c_options [format "%s -DNFAIR=3" $c_options]
+       } else {
+               set c_options [format "%s -DNOFAIR" $c_options]
+       }
+       set foo $ival(3)
+       catch { set foo [.av.memopts.choice3.e1 get] }
+
+       if {[string first "-DBITSTATE" $c_options] > 0 && [string first "-DMA" $foo] > 0} {
+               complain8
+       }
+       set c_options [format "%s %s" $c_options $foo ]
+
+       set foo $ival(4)
+       catch { set foo [.av.memopts.choice4.e1 get] }
+       set v_options [format "%s %s" $v_options $foo ] 
+
+       set foo $ival(5)
+       catch { set foo [.av.memopts.choice.5.e1 get] }
+       set a_options [format "%s %s" $a_options $foo ]
+
+       if {$an_typ==0 && $as_typ==0} { set v_options [format "%s -A" $v_options] }
+       if {$an_typ==0 && $ie_typ==0} { set v_options [format "%s -E" $v_options] }
+       if {$an_typ==1 && $cp_typ==1} { set v_options [format "%s -l" $v_options] }
+       if {$an_typ==1 && $cp_typ==2} { set v_options [format "%s -a" $v_options] }
+       if {$cyc_typ==1} { set v_options [format "%s -f" $v_options] }
+       if {$ur_typ==0} { set v_options [format "%s -n" $v_options] }
+       if {$st_typ==1} { set v_options [format "%s -e" $v_options] }
+       if {$se_typ!=0} { set v_options [format "%s -i" $v_options] }
+       if {$et_typ==0} { set v_options [format "%s -c0" $v_options] }
+       if {$et_typ==1} { set v_options [format "%s -c%s" $v_options $ival(6)] }
+       if {$ct_typ==1 && $ival(7) != 2} { set v_options [format "%s -k%s" $v_options $ival(7)] }
+       return 1
+}
+
+set mt 0
+set skipmax 10
+
+proc runval {havedest} {
+       global Unix CC SPIN Fname PlaceSim
+       global v_options a_options notignored
+       global c_options Job_Done mt skipmax
+       global stop s_typ vbox waitwhat not_warned_yet
+       global LastGenerate LastCompile NextCompile
+
+       set stop 0
+       if {[bld_v_options] == 0} {
+               advanced_val
+               return
+       }
+       if {[winfo exists .v]} {
+               set PlaceSim [wm geometry .v]
+               destroy .v
+       }
+       catch {destroy .av}
+       if {[string first "\?" $c_options] > 0} {
+               add_log "error: undefined '?' in optional compiler directives"
+               return
+       }
+       if {[string first "\?" $v_options] > 0} {
+               add_log "error: undefined '?' in extra runtime options"
+               return
+       }
+       add_log "<starting verification>"
+       if {$havedest != "0"} {
+               $havedest insert end "<starting verification>\n"
+       }
+
+       set nochange [no_change]
+       if {$nochange == 0} { set LastGenerate "" }
+
+       if {$LastGenerate == $a_options} {
+               add_log "<no code regeneration necessary>"
+               if {$havedest != "0"} {
+                       $havedest insert end "<no code regeneration necessary>\n"
+               }
+               set errmsg 0
+       } else {
+               set LastCompile ""
+               add_log "$SPIN $a_options pan_in"; update
+               if {$havedest != "0"} {
+                       $havedest insert end "$SPIN $a_options pan_in\n"
+               }
+               if {$Unix} {
+                       catch {eval exec $SPIN $a_options pan_in} errmsg
+               } else {
+                       catch {eval exec $SPIN $a_options pan_in >&pan.tmp}
+                       set errmsg [msg_file pan.tmp 0]
+               }
+               if {[string length $errmsg]>0} {
+                       set foo [string first "Exit-Status 0" $errmsg]
+                       if {$foo<0} {
+                               add_log "$errmsg"
+                               if {$havedest != "0"} {
+                                       $havedest insert end "$errmsg\n"
+                               }
+                               update
+                               return
+                       }
+                       incr foo -2
+                       set errmsg [string range $errmsg 0 $foo]
+                       add_log "$errmsg"
+                       if {$havedest != "0"} {
+                               $havedest insert end "$errmsg\n"
+                       }
+       }       }
+       set LastGenerate $a_options
+
+       set NextCompile "$CC -o pan $c_options pan.c"
+
+       if {$havedest != "0"} {
+               catch { $havedest yview -pickplace end }
+       }
+       if {$LastCompile == $NextCompile && [file exists pan]} {
+               add_log "<no recompilation necessary>"
+               if {$havedest != "0"} {
+                       $havedest insert end "<no recompilation necessary>\n"
+               }
+               set errmsg 0
+       } else {
+               add_log $NextCompile
+               if {$havedest != "0"} {
+                       $havedest insert end "$NextCompile\n"
+               }
+               catch {
+                       warner "Compiling" "Please wait until compilation of the \
+executable produced by spin completes." 300
+               }
+               update
+               if {$Unix} {
+                       rmfile "./pan"
+                       catch {eval exec $NextCompile >pan.tmp 2>pan.err}
+               } else {
+                       rmfile "pan.exe"
+                       catch {eval exec $NextCompile >pan.tmp 2>pan.err}
+               }
+
+               set errmsg [msg_file pan.tmp 0]
+               if {[string length $errmsg] == 0} {
+                       set errmsg [msg_file pan.err 0]
+               } else {
+                       set errmsg "$errmsg\n[msg_file pan.err 0]"
+               }
+
+               catch {destroy .warn}
+
+               auto_reset
+               if {$Unix} {
+                       if {[auto_execok "./pan"] == "" \
+                       ||  [auto_execok "./pan"] == 0} {
+                               add_log "$errmsg"
+                               add_log "compilation failed"
+                               if {$havedest != "0"} {
+                                       $havedest insert end "<compilation failed>\n"
+                               }
+                               update
+                               return
+                       }
+               } else {
+                       if {[auto_execok "pan"] == "" \
+                       ||  [auto_execok "pan"] == 0} {
+                               add_log "$errmsg"
+                               add_log "compilation failed"
+                               if {$havedest != "0"} {
+                                       $havedest insert end "<compilation failed>\n"
+                               }
+                               update
+                               return
+       }       }       }
+
+       set LastCompile $NextCompile
+       set NextCompile ""
+
+       if {$Unix} {
+               set PREFIX "time ./pan -v"
+       } else {
+               set PREFIX "pan -v"
+       }
+       add_log "$PREFIX $v_options"; update
+       if {$havedest != "0"} {
+               $havedest insert end "$PREFIX $v_options\n"
+               catch { $havedest yview -pickplace end }
+       }
+       set errmsg ""
+       update
+       rmfile pan.out
+       set errmsg [catch {eval exec $PREFIX $v_options >&pan.out &}]
+       if {$errmsg} {
+               add_log "$errmsg"
+               add_log "could not run verification"
+               if {$havedest != "0"} {
+                       $havedest insert end "<could not run verification>\n"
+               }
+               update
+               return
+       }
+
+       set not_warned_yet 1
+       if {$havedest != "0"} {
+               set vbox $havedest
+       } else {
+               set vv [mkbox "Verification Output" "VerOut" "$Fname.out" 80 20]
+               set vbox .c$vv.z.t
+       }
+       update
+       set mt 0
+       after 5000 outcheck $vbox
+       update
+}
+
+proc outcheck {vbox} {
+       global stop where not_warned_yet runtime mt Unix Fname FG skipmax
+
+       set firstline 1
+       set have_trail 0
+       set po_red_viol 0
+
+       if {[winfo exists $vbox] == 0} {
+               add_log "<verification output panel $vbox was closed>"
+               return
+       }
+
+       set erline 0; set lnr 0
+       set nomem 0; set nerr 0
+
+       if {$stop == 0} {
+         catch { set nt [file mtime pan.out] }
+         if {$mt == $nt && $skipmax > 0} {
+               incr skipmax -1
+         } else {
+         set mt $nt
+         set skipmax 10
+         set fd [open pan.out r]
+         while {[gets $fd line] > -1} {
+               if {$firstline} {
+                       set firstline 0
+                       set nerr 0
+                       set trunc 0
+                       set nomem 0
+                       .inp.t tag remove hilite 0.0 end
+                       catch { $vbox delete 0.0 end }
+                       set lnr 0
+               }
+               catch { $vbox insert end "$line\n" }
+               incr lnr
+               catch { $vbox yview -pickplace end }
+               update
+
+               if {[string first "line" $line]>=0} {
+                       scan $line "\tline %d" where
+                       catch { src_line $where }
+               }
+               if {[string first "State-vector" $line] == 0 \
+               ||  ([string first "error:" $line] == 0 \
+               &&   [string first "error: max search depth too small" $line] != 0)} {
+                       set stop 1      ;# run must have completed
+                       set nerr [string first "errors:" $line]
+                       if {$nerr > 0} {
+                       set part [string range $line $nerr end]
+                       scan $part "errors: %d" nerr
+                       if {$nerr == 0} {
+                               catch { .tl.results.top.title configure\
+                                       -text "Verification Result: valid" -fg $FG
+                               }
+                       } else {
+                               catch { .tl.results.top.title configure\
+                                       -text "Verification Result: not valid" -fg red
+                               }
+                       }
+                       set erline $lnr
+                       incr erline -1
+                       }
+               }
+               if {[string first "search depth too small" $line]>0} {
+                       set trunc 1
+               }
+               if {[string first "wrote pan_in.trail" $line]>0} {
+                       set have_trail 1
+               }
+               if {[string first "violated: access to chan" $line]>0} {
+                       set po_red_viol 1
+               }
+               if {[string first "out of memory" $line]>0} {
+                       set nomem 1
+               }
+               if {[string first "A=atomic;" $line]>0} {
+                       set stop 1
+               }
+               update
+         }
+         catch "close $fd"
+       } }
+       if {$nomem || $po_red_viol} { set erline 0 }
+
+       if {$stop || ($have_trail && $po_red_viol==0 && ($nerr>0 || $trunc>0))} {
+               catch { $vbox yview 0.0 }
+               add_log "<verification done>"
+               if {$nerr > 0 || $trunc == 1 || $nomem == 1} {
+                       if {[file exists pan_in.trail]} {
+                               cpfile pan_in.trail $Fname.trail
+                       } elseif {[file exists pan_in.tra]} {
+                               cpfile pan_in.tra $Fname.trail
+                       }
+                       catch { repeatbox $nerr $trunc $nomem }
+               }
+       } else {
+               if {$not_warned_yet} {
+                       set runtime 0
+                       set stop 0
+                       set line "Running verification -- waiting for output"
+                       catch { $vbox insert end "$line\n" }
+                       set line "\t(kill background process 'pan' to abort run)"
+                       catch { $vbox insert end "$line\n" }
+                       if {$Unix == 0} {
+                       set line "\t(use ctl-alt-del to kill pan)"
+                       catch { $vbox insert end "$line\n" }
+                       } else {
+                       set line "\t(use /bin/ps to find pid; then: kill -2 pid)"
+                       catch { $vbox insert end "$line\n" }
+                       catch { $vbox yview -pickplace end }
+                       }
+                       set not_warned_yet 0
+               } else {
+                       incr runtime 5
+                       if {$stop} {
+                               add_log "<done>"
+                               return
+                       } else {
+                       if {$runtime%60 == 0} {
+                               set rt [expr $runtime / 60]
+                               add_log "verification now running for approx $rt min.."
+                       }}
+                       update
+               }
+               after 5000 outcheck $vbox
+       }
+}
+
+proc src_line {s} {
+       global FG BG
+       scan $s %d tgt_lnr
+
+       if {$tgt_lnr > 0} {
+       .inp.t tag add hilite $tgt_lnr.0 $tgt_lnr.end
+       .inp.t tag configure hilite -background $FG -foreground $BG
+               if {$tgt_lnr > 10} {
+       .inp.t yview -pickplace [expr $tgt_lnr-10]
+               } else {
+       .inp.t yview -pickplace [expr $tgt_lnr-1]
+               }
+       }
+}
+
+proc repeatbox { {nerr} {trunc} {nomem}} {
+       global s_typ PlaceWarn whichsim
+
+       if {$nerr <= 0 && $trunc <= 0 && $nomem <= 0} { return }
+
+       catch {destroy .rep}
+       toplevel .rep
+
+       wm title .rep "Suggested Action"
+       wm iconname .rep "Suggest"
+       wm geometry .rep $PlaceWarn
+       button .rep.b0 -text "Close" -command {destroy .rep}
+       button .rep.b1 -text "Run Guided Simulation.." \
+               -command {destroy .rep; Rewind }
+       button .rep.b2 -text "Setup Guided Simulation.." \
+               -command {destroy .rep; simulation }
+
+       if {$nerr>0} {
+               message .rep.t -width 500 -text "\
+Optionally, repeat the run with a different search\
+depth to find a shorter path to the error.
+
+Or, perform a GUIDED simulation to retrace\
+the error found in this run, and skip\
+the first series of steps if the error was\
+found at a depth greater than about 100 steps)."
+               set s_typ 1
+               set whichsim 0
+
+               pack append .rep .rep.t {top expand fill}
+               pack append .rep .rep.b0 {right}
+               pack append .rep .rep.b1 {right}
+               pack append .rep .rep.b2 {right}
+       } else {
+
+               if {$nomem>0} {
+                       message .rep.t -width 500 -text "\
+Make sure the Physical Memory parameter (under Advanced\
+Options) is set to the maximum physical memory available.\
+If not, repeat the verification with the true maximum.\
+(Don't set it higher than the physical limit though.)\
+Otherwise, use compression, or switch to a\
+Supertrace Verification."
+               } else {
+
+                       if {$trunc} {
+
+                       message .rep.t -width 500 -text "\
+If the search was incomplete (truncated)\
+because the max search depth was too small,\
+try to increase the depth limit (it is set\
+in Advanced Options of the Verification Parameters\
+Panel), and repeat the verification."
+                       }
+               }
+               pack append .rep .rep.t {top expand fill}
+               pack append .rep .rep.b0 {right}
+       }
+}
+
+# Main startup and arg processing
+# this is at the end - to make sure all
+# proc declarations were seen
+
+if {$argc == 1} {
+       set Fname "$argv"
+       wm title . "SPIN CONTROL $xversion -- File: $Fname"
+       cleanup 0
+       cpfile $argv.trail pan_in.trail
+       reopen
+
+       check_xsp $argv
+}
+
+focus .inp.t
+update
diff --git a/trunk/verif/examples/buffer.spin b/trunk/verif/examples/buffer.spin
new file mode 100644 (file)
index 0000000..41965dc
--- /dev/null
@@ -0,0 +1,289 @@
+
+// LTTng ltt-tracer.c atomic lockless buffering scheme Promela model v1
+// Created for the Spin validator.
+// Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
+// June 2008
+
+// TODO : create test cases that will generate an overflow on the offset and
+// counter type. Counter types smaller than a byte should be used.
+
+// Promela only has unsigned char, no signed char.
+// Because detection of difference < 0 depends on a signed type, but we want
+// compactness, check also for the values being higher than half of the unsigned
+// char range (and consider them negative). The model, by design, does not use
+// offsets or counts higher than 127 because we would then have to use a larger
+// type (short or int).
+#define HALF_UCHAR (255/2)
+
+// NUMPROCS 4 : causes event loss with some reader timings.
+// e.g. 3 events, 1 switch, 1 event (lost, buffer full), read 1 subbuffer
+#define NUMPROCS 4
+
+// NUMPROCS 3 : does not cause event loss because buffers are big enough.
+//#define NUMPROCS 3
+// e.g. 3 events, 1 switch, read 1 subbuffer
+
+#define NUMSWITCH 1
+#define BUFSIZE 4
+#define NR_SUBBUFS 2
+#define SUBBUF_SIZE (BUFSIZE / NR_SUBBUFS)
+
+// Writer counters
+byte write_off = 0;
+byte commit_count[NR_SUBBUFS];
+
+// Reader counters
+byte read_off = 0;
+byte retrieve_count[NR_SUBBUFS];
+
+byte events_lost = 0;
+byte refcount = 0;
+
+bool deliver = 0;
+
+// buffer slot in-use bit. Detects racy use (more than a single process
+// accessing a slot at any given step).
+bool buffer_use[BUFSIZE];
+
+// Proceed to a sub-subber switch is needed.
+// Used in a periodical timer interrupt to fill and ship the current subbuffer
+// to the reader so we can guarantee a steady flow. If a subbuffer is
+// completely empty, don't switch.
+// Also used as "finalize" operation to complete the last subbuffer after
+// all writers have finished so the last subbuffer can be read by the reader.
+proctype switcher()
+{
+  byte prev_off, new_off, tmp_commit;
+  byte size;
+
+cmpxchg_loop:
+  atomic {
+    prev_off = write_off;
+    size = SUBBUF_SIZE - (prev_off % SUBBUF_SIZE);
+    new_off = prev_off + size;
+    if
+    :: (new_off - read_off > BUFSIZE && new_off - read_off < HALF_UCHAR)
+        || size == SUBBUF_SIZE ->
+      refcount = refcount - 1;
+      goto not_needed;
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    if
+    :: prev_off != write_off -> goto cmpxchg_loop
+    :: else -> write_off = new_off;
+    fi;
+  }
+
+  atomic {
+    tmp_commit = commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] + size;
+    commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] = tmp_commit;
+    if
+    :: tmp_commit % SUBBUF_SIZE == 0 -> deliver = 1
+    :: else -> skip
+    fi;
+    refcount = refcount - 1;
+  }
+not_needed:
+  skip;
+}
+
+// tracer
+// Writes 1 byte of information in the buffer at the current
+// "write_off" position and then increment the commit_count of the sub-buffer
+// the information has been written to.
+proctype tracer()
+{
+  byte size = 1;
+  byte prev_off, new_off, tmp_commit;
+  byte i, j;
+
+cmpxchg_loop:
+  atomic {
+    prev_off = write_off;
+    new_off = prev_off + size;
+  }
+  atomic {
+    if
+    :: new_off - read_off > BUFSIZE && new_off - read_off < HALF_UCHAR ->
+      goto lost
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    if
+    :: prev_off != write_off -> goto cmpxchg_loop
+    :: else -> write_off = new_off;
+    fi;
+    i = 0;
+    do
+    :: i < size ->
+      assert(buffer_use[(prev_off + i) % BUFSIZE] == 0);
+      buffer_use[(prev_off + i) % BUFSIZE] = 1;
+      i++
+    :: i >= size -> break
+    od;
+  }
+
+  // writing to buffer...
+
+  atomic {
+    i = 0;
+    do
+    :: i < size ->
+      buffer_use[(prev_off + i) % BUFSIZE] = 0;
+      i++
+    :: i >= size -> break
+    od;
+    tmp_commit = commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] + size;
+    commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] = tmp_commit;
+    if
+    :: tmp_commit % SUBBUF_SIZE == 0 -> deliver = 1;
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    goto end;
+lost:
+    events_lost++;
+end:
+    refcount = refcount - 1;
+  }
+}
+
+// reader
+// Read the information sub-buffer per sub-buffer when available.
+//
+// Reads the information as soon as it is ready, or may be delayed by
+// an asynchronous delivery. Being modeled as a process insures all cases
+// (scheduled very quickly or very late, causing event loss) are covered.
+// Only one reader per buffer (normally ensured by a mutex). This is modeled
+// by using a single reader process.
+proctype reader()
+{
+  byte i, j;
+  byte tmp_retrieve;
+  byte lwrite_off, lcommit_count;
+
+  do
+  :: (write_off / SUBBUF_SIZE) - (read_off / SUBBUF_SIZE) > 0
+     && (write_off / SUBBUF_SIZE) - (read_off / SUBBUF_SIZE) < HALF_UCHAR
+           && commit_count[(read_off % BUFSIZE) / SUBBUF_SIZE]
+             - retrieve_count[(read_off % BUFSIZE) / SUBBUF_SIZE]
+               == SUBBUF_SIZE ->
+      atomic {
+        i = 0;
+        do
+        :: i < SUBBUF_SIZE ->
+          assert(buffer_use[(read_off + i) % BUFSIZE] == 0);
+          buffer_use[(read_off + i) % BUFSIZE] = 1;
+          i++
+        :: i >= SUBBUF_SIZE -> break
+        od;
+      }
+      // reading from buffer...
+
+      // Since there is only one reader per buffer at any given time,
+      // we don't care about retrieve_count vs read_off ordering :
+      // combined use of retrieve_count and read_off are made atomic by a
+      // mutex.
+      atomic {
+        i = 0;
+        do
+        :: i < SUBBUF_SIZE ->
+          buffer_use[(read_off + i) % BUFSIZE] = 0;
+          i++
+        :: i >= SUBBUF_SIZE -> break
+        od;
+        tmp_retrieve = retrieve_count[(read_off % BUFSIZE) / SUBBUF_SIZE]
+            + SUBBUF_SIZE;
+        retrieve_count[(read_off % BUFSIZE) / SUBBUF_SIZE] = tmp_retrieve;
+        read_off = read_off + SUBBUF_SIZE;
+      }
+  :: read_off >= (NUMPROCS - events_lost) -> break;
+  od;
+}
+
+// Waits for all tracer and switcher processes to finish before finalizing
+// the buffer. Only after that will the reader be allowed to read the
+// last subbuffer.
+proctype cleaner()
+{
+  atomic {
+    do
+    :: refcount == 0 ->
+      refcount = refcount + 1;
+      run switcher();  // Finalize the last sub-buffer so it can be read.
+      break;
+    od;
+  }
+}
+
+init {
+  byte i = 0;
+  byte j = 0;
+  byte sum = 0;
+  byte commit_sum = 0;
+
+  atomic {
+    i = 0;
+    do
+    :: i < NR_SUBBUFS ->
+      commit_count[i] = 0;
+      retrieve_count[i] = 0;
+      i++
+    :: i >= NR_SUBBUFS -> break
+    od;
+    i = 0;
+    do
+    :: i < BUFSIZE ->
+      buffer_use[i] = 0;
+      i++
+    :: i >= BUFSIZE -> break
+    od;
+    run reader();
+    run cleaner();
+    i = 0;
+    do
+    :: i < NUMPROCS ->
+      refcount = refcount + 1;
+      run tracer();
+      i++
+    :: i >= NUMPROCS -> break
+    od;
+    i = 0;
+    do
+    :: i < NUMSWITCH ->
+      refcount = refcount + 1;
+      run switcher();
+      i++
+    :: i >= NUMSWITCH -> break
+    od;
+  }
+  // Assertions.
+  atomic {
+    // The writer head must always be superior or equal to the reader head.
+    assert(write_off - read_off >= 0 && write_off - read_off < HALF_UCHAR);
+    j = 0;
+    commit_sum = 0;
+    do
+    :: j < NR_SUBBUFS ->
+      commit_sum = commit_sum + commit_count[j];
+      // The commit count of a particular subbuffer must always be higher
+      // or equal to the retrieve_count of this subbuffer.
+      assert(commit_count[j] - retrieve_count[j] >= 0 &&
+        commit_count[j] - retrieve_count[j] < HALF_UCHAR);
+      j++
+    :: j >= NR_SUBBUFS -> break
+    od;
+    // The sum of all subbuffer commit counts must always be lower or equal
+    // to the writer head, because space must be reserved before it is
+    // written to and then committed.
+    assert(write_off - commit_sum >= 0 && write_off - commit_sum < HALF_UCHAR);
+
+    // If we have less writers than the buffer space available, we should
+    // not lose events
+    assert(NUMPROCS + NUMSWITCH > BUFSIZE || events_lost == 0);
+  }
+}
diff --git a/trunk/verif/examples/buffer.spin.bkp1 b/trunk/verif/examples/buffer.spin.bkp1
new file mode 100644 (file)
index 0000000..8a0ad29
--- /dev/null
@@ -0,0 +1,154 @@
+//#define NUMPROCS 5
+#define NUMPROCS 4
+#define BUFSIZE 4
+#define NR_SUBBUFS 2
+#define SUBBUF_SIZE (BUFSIZE / NR_SUBBUFS)
+
+byte write_off = 0;
+byte read_off = 0;
+byte events_lost = 0;
+byte deliver = 0; // Number of subbuffers delivered
+byte refcount = 0;
+
+byte commit_count[NR_SUBBUFS];
+
+proctype switcher()
+{
+  int prev_off, new_off, tmp_commit;
+  int size;
+
+cmpxchg_loop:
+  atomic {
+    prev_off = write_off;
+    size = SUBBUF_SIZE - (prev_off % SUBBUF_SIZE);
+    new_off = prev_off + size;
+    if
+    :: new_off - read_off > BUFSIZE ->
+      goto not_needed;
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    if
+    :: prev_off != write_off -> goto cmpxchg_loop
+    :: else -> write_off = new_off;
+    fi;
+  }
+
+  atomic {
+    tmp_commit = commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] + size;
+    commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] = tmp_commit;
+    if
+    :: tmp_commit % SUBBUF_SIZE == 0 -> deliver++
+    :: else -> skip
+    fi;
+  }
+not_needed:
+  skip;
+}
+
+proctype tracer(byte size)
+{
+  int prev_off, new_off, tmp_commit;
+
+cmpxchg_loop:
+  atomic {
+    prev_off = write_off;
+    new_off = prev_off + size;
+  }
+  atomic {
+    if
+    :: new_off - read_off > BUFSIZE -> goto lost
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    if
+    :: prev_off != write_off -> goto cmpxchg_loop
+    :: else -> write_off = new_off;
+    fi;
+  }
+
+  atomic {
+    tmp_commit = commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] + size;
+    commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] = tmp_commit;
+    if
+    :: tmp_commit % SUBBUF_SIZE == 0 -> deliver++
+    :: else -> skip
+    fi;
+  }
+  goto end;
+lost:
+  events_lost++;
+end:
+  refcount = refcount - 1;
+}
+
+proctype reader()
+{
+    //atomic {
+    //  do
+    //  :: (deliver == (NUMPROCS - events_lost) / SUBBUF_SIZE) -> break;
+    //  od;
+    //}
+ // made atomic to use less memory. Not really true.
+ atomic {
+    do
+    :: write_off - read_off >= SUBBUF_SIZE && commit_count[(read_off % BUFSIZE) / SUBBUF_SIZE] % SUBBUF_SIZE == 0 ->
+      read_off = read_off + SUBBUF_SIZE;
+    :: read_off >= (NUMPROCS - events_lost) -> break;
+    od;
+  }
+}
+
+proctype cleaner()
+{
+  atomic {
+    do
+    :: refcount == 0 ->
+      run switcher();
+      break;
+    od;
+  }
+}
+
+init {
+  int i = 0;
+  int j = 0;
+  int sum = 0;
+  int commit_sum = 0;
+
+  atomic {
+    i = 0;
+    do
+    :: i < NR_SUBBUFS ->
+      commit_count[i] = 0;
+      i++
+    :: i >= NR_SUBBUFS -> break
+    od;
+    run reader();
+    run cleaner();
+    i = 0;
+    do
+    :: i < NUMPROCS ->
+      refcount = refcount + 1;
+      run tracer(1);
+      i++
+    :: i >= NUMPROCS -> break
+    od;
+    run switcher();
+  }
+  atomic {
+    assert(write_off - read_off >= 0);
+    j = 0;
+    commit_sum = 0;
+    do
+    :: j < NR_SUBBUFS ->
+      commit_sum = commit_sum + commit_count[j];
+      j++
+    :: j >= NR_SUBBUFS -> break
+    od;
+    assert(commit_sum <= write_off);
+    //assert(events_lost == 0);
+  }
+}
diff --git a/trunk/verif/examples/buffer.spin.bkp2 b/trunk/verif/examples/buffer.spin.bkp2
new file mode 100644 (file)
index 0000000..99779ff
--- /dev/null
@@ -0,0 +1,268 @@
+
+// does not cause event loss
+//#define NUMPROCS 3
+// e.g. 3 events, 1 switch, read 1 subbuffer
+
+// causes event loss with some reader timings,
+// e.g. 3 events, 1 switch, 1 event (lost, buffer full), read 1 subbuffer
+#define NUMPROCS 4
+
+#define NUMSWITCH 1
+#define BUFSIZE 4
+#define NR_SUBBUFS 2
+#define SUBBUF_SIZE (BUFSIZE / NR_SUBBUFS)
+
+// Writer counters
+byte write_off = 0;
+byte commit_count[NR_SUBBUFS];
+
+// Reader counters
+byte read_off = 0;
+byte retrieve_count[NR_SUBBUFS];
+
+byte events_lost = 0;
+byte refcount = 0;
+
+bool deliver = 0;
+
+// buffer slot in-use bit. Detects racy use (more than a single process
+// accessing a slot at any given step).
+bool buffer_use[BUFSIZE];
+
+// Proceed to a sub-subber switch is needed.
+// Used in a periodical timer interrupt to fill and ship the current subbuffer
+// to the reader so we can guarantee a steady flow.
+// Also used as "finalize" operation to complete the last subbuffer after
+// all writers have finished so the last subbuffer can be read by the reader.
+proctype switcher()
+{
+  byte prev_off, new_off, tmp_commit;
+  byte size;
+
+cmpxchg_loop:
+  atomic {
+    prev_off = write_off;
+    size = SUBBUF_SIZE - (prev_off % SUBBUF_SIZE);
+    new_off = prev_off + size;
+    if
+    :: new_off - read_off > BUFSIZE ->
+      refcount = refcount - 1;
+      goto not_needed;
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    if
+    :: prev_off != write_off -> goto cmpxchg_loop
+    :: else -> write_off = new_off;
+    fi;
+  }
+
+  atomic {
+    tmp_commit = commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] + size;
+    commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] = tmp_commit;
+    if
+    :: tmp_commit % SUBBUF_SIZE == 0 -> deliver = 1
+    :: else -> skip
+    fi;
+    refcount = refcount - 1;
+  }
+not_needed:
+  skip;
+}
+
+// tracer
+// Writes "size" bytes of information in the buffer at the current
+// "write_off" position and then increment the commit_count of the sub-buffer
+// the information has been written to.
+proctype tracer(byte size)
+{
+  byte prev_off, new_off, tmp_commit;
+  byte i, j;
+
+cmpxchg_loop:
+  atomic {
+    prev_off = write_off;
+    new_off = prev_off + size;
+  }
+  atomic {
+    if
+    :: new_off - read_off > BUFSIZE -> goto lost
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    if
+    :: prev_off != write_off -> goto cmpxchg_loop
+    :: else -> write_off = new_off;
+    fi;
+    i = 0;
+    do
+    :: i < size ->
+      assert(buffer_use[(prev_off + i) % BUFSIZE] == 0);
+      buffer_use[(prev_off + i) % BUFSIZE] = 1;
+      i++
+    :: i >= size -> break
+    od;
+  }
+
+  // writing to buffer...
+
+  atomic {
+    i = 0;
+    do
+    :: i < size ->
+      buffer_use[(prev_off + i) % BUFSIZE] = 0;
+      i++
+    :: i >= size -> break
+    od;
+    tmp_commit = commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] + size;
+    commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] = tmp_commit;
+    if
+    :: tmp_commit % SUBBUF_SIZE == 0 -> deliver = 1;
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    goto end;
+lost:
+    events_lost++;
+end:
+    refcount = refcount - 1;
+  }
+}
+
+// reader
+// Read the information sub-buffer per sub-buffer when available.
+//
+// Reads the information as soon as it is ready, or may be delayed by
+// an asynchronous delivery. Being modeled as a process insures all cases
+// (scheduled very quickly or very late, causing event loss) are covered.
+// Only one reader per buffer (normally ensured by a mutex). This is modeled
+// by using a single reader process.
+proctype reader()
+{
+  byte i, j;
+  byte tmp_retrieve;
+  byte lwrite_off, lcommit_count;
+
+  do
+  :: (write_off / SUBBUF_SIZE) - (read_off / SUBBUF_SIZE) > 0
+           && commit_count[(read_off % BUFSIZE) / SUBBUF_SIZE]
+             - retrieve_count[(read_off % BUFSIZE) / SUBBUF_SIZE]
+               == SUBBUF_SIZE ->
+      atomic {
+        i = 0;
+        do
+        :: i < SUBBUF_SIZE ->
+          assert(buffer_use[(read_off + i) % BUFSIZE] == 0);
+          buffer_use[(read_off + i) % BUFSIZE] = 1;
+          i++
+        :: i >= SUBBUF_SIZE -> break
+        od;
+      }
+      // reading from buffer...
+
+      // Since there is only one reader per buffer at any given time,
+      // we don't care about retrieve_count vs read_off ordering :
+      // combined use of retrieve_count and read_off are made atomic by a
+      // mutex.
+      atomic {
+        i = 0;
+        do
+        :: i < SUBBUF_SIZE ->
+          buffer_use[(read_off + i) % BUFSIZE] = 0;
+          i++
+        :: i >= SUBBUF_SIZE -> break
+        od;
+        tmp_retrieve = retrieve_count[(read_off % BUFSIZE) / SUBBUF_SIZE]
+            + SUBBUF_SIZE;
+        retrieve_count[(read_off % BUFSIZE) / SUBBUF_SIZE] = tmp_retrieve;
+        read_off = read_off + SUBBUF_SIZE;
+      }
+  :: read_off >= (NUMPROCS - events_lost) -> break;
+  od;
+}
+
+// Waits for all tracer and switcher processes to finish before finalizing
+// the buffer. Only after that will the reader be allowed to read the
+// last subbuffer.
+proctype cleaner()
+{
+  atomic {
+    do
+    :: refcount == 0 ->
+      refcount = refcount + 1;
+      run switcher();  // Finalize the last sub-buffer so it can be read.
+      break;
+    od;
+  }
+}
+
+init {
+  byte i = 0;
+  byte j = 0;
+  byte sum = 0;
+  byte commit_sum = 0;
+
+  atomic {
+    i = 0;
+    do
+    :: i < NR_SUBBUFS ->
+      commit_count[i] = 0;
+      retrieve_count[i] = 0;
+      i++
+    :: i >= NR_SUBBUFS -> break
+    od;
+    i = 0;
+    do
+    :: i < BUFSIZE ->
+      buffer_use[i] = 0;
+      i++
+    :: i >= BUFSIZE -> break
+    od;
+    run reader();
+    run cleaner();
+    i = 0;
+    do
+    :: i < NUMPROCS ->
+      refcount = refcount + 1;
+      run tracer(1);
+      i++
+    :: i >= NUMPROCS -> break
+    od;
+    i = 0;
+    do
+    :: i < NUMSWITCH ->
+      refcount = refcount + 1;
+      run switcher();
+      i++
+    :: i >= NUMSWITCH -> break
+    od;
+  }
+  // Assertions.
+  atomic {
+    // The writer head must always be superior to the reader head.
+    assert(write_off - read_off >= 0);
+    j = 0;
+    commit_sum = 0;
+    do
+    :: j < NR_SUBBUFS ->
+      commit_sum = commit_sum + commit_count[j];
+      // The commit count of a particular subbuffer must always be higher
+      // or equal to the retrieve_count of this subbuffer.
+      assert(commit_count[j] >= retrieve_count[j]);
+      j++
+    :: j >= NR_SUBBUFS -> break
+    od;
+    // The sum of all subbuffer commit counts must always be lower or equal
+    // to the writer head, because space must be reserved before it is
+    // written to and then committed.
+    assert(commit_sum <= write_off);
+    j = 0;
+
+    // If we have less writers than the buffer space available, we should
+    // not lose events
+    assert(NUMPROCS + NUMSWITCH > BUFSIZE || events_lost == 0);
+  }
+}
diff --git a/trunk/verif/examples/buffer.spin.missing_retrieve_count b/trunk/verif/examples/buffer.spin.missing_retrieve_count
new file mode 100644 (file)
index 0000000..8bec913
--- /dev/null
@@ -0,0 +1,228 @@
+//#define NUMPROCS 5
+#define NUMPROCS 4
+#define BUFSIZE 4
+#define NR_SUBBUFS 2
+#define SUBBUF_SIZE (BUFSIZE / NR_SUBBUFS)
+
+byte write_off = 0;
+byte read_off = 0;
+byte events_lost = 0;
+byte deliver = 0; // Number of subbuffers delivered
+byte refcount = 0;
+
+byte commit_count[NR_SUBBUFS];
+
+byte buffer_use_count[BUFSIZE];
+
+proctype switcher()
+{
+  int prev_off, new_off, tmp_commit;
+  int size;
+
+cmpxchg_loop:
+  atomic {
+    prev_off = write_off;
+    size = SUBBUF_SIZE - (prev_off % SUBBUF_SIZE);
+    new_off = prev_off + size;
+    if
+    :: new_off - read_off > BUFSIZE ->
+      goto not_needed;
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    if
+    :: prev_off != write_off -> goto cmpxchg_loop
+    :: else -> write_off = new_off;
+    fi;
+  }
+
+  atomic {
+    tmp_commit = commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] + size;
+    commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] = tmp_commit;
+    if
+    :: tmp_commit % SUBBUF_SIZE == 0 -> deliver++
+    :: else -> skip
+    fi;
+  }
+not_needed:
+  skip;
+}
+
+proctype tracer(byte size)
+{
+  int prev_off, new_off, tmp_commit;
+  int i;
+  int j;
+
+cmpxchg_loop:
+  atomic {
+    prev_off = write_off;
+    new_off = prev_off + size;
+  }
+  atomic {
+    if
+    :: new_off - read_off > BUFSIZE -> goto lost
+    :: else -> skip
+    fi;
+  }
+  atomic {
+    if
+    :: prev_off != write_off -> goto cmpxchg_loop
+    :: else -> write_off = new_off;
+    fi;
+    i = 0;
+    do
+    :: i < size ->
+      buffer_use_count[(prev_off + i) % BUFSIZE]
+        = buffer_use_count[(prev_off + i) % BUFSIZE] + 1;
+      i++
+    :: i >= size -> break
+    od;
+  }
+    do
+    :: j < BUFSIZE ->
+      assert(buffer_use_count[j] < 2);
+      j++
+    :: j >= BUFSIZE -> break
+    od;
+
+
+
+  // writing to buffer...
+
+  atomic {
+    i = 0;
+    do
+    :: i < size ->
+      buffer_use_count[(prev_off + i) % BUFSIZE]
+        = buffer_use_count[(prev_off + i) % BUFSIZE] - 1;
+      i++
+    :: i >= size -> break
+    od;
+    tmp_commit = commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] + size;
+    commit_count[(prev_off % BUFSIZE) / SUBBUF_SIZE] = tmp_commit;
+    if
+    :: tmp_commit % SUBBUF_SIZE == 0 -> deliver++
+    :: else -> skip
+    fi;
+  }
+  goto end;
+lost:
+  events_lost++;
+end:
+  refcount = refcount - 1;
+}
+
+proctype reader()
+{
+  int i;
+  int j;
+    //atomic {
+    //  do
+    //  :: (deliver == (NUMPROCS - events_lost) / SUBBUF_SIZE) -> break;
+    //  od;
+    //}
+  do
+  :: (write_off / SUBBUF_SIZE) - (read_off / SUBBUF_SIZE) > 0 && commit_count[(read_off % BUFSIZE) / SUBBUF_SIZE] % SUBBUF_SIZE == 0 ->
+    atomic {
+      i = 0;
+      do
+      :: i < SUBBUF_SIZE ->
+        buffer_use_count[(read_off + i) % BUFSIZE]
+          = buffer_use_count[(read_off + i) % BUFSIZE] + 1;
+        i++
+      :: i >= SUBBUF_SIZE -> break
+      od;
+    }
+    j = 0;
+    do
+    :: j < BUFSIZE ->
+      assert(buffer_use_count[j] < 2);
+      j++
+    :: j >= BUFSIZE -> break
+    od;
+
+    // reading from buffer...
+
+    atomic {
+      i = 0;
+      do
+      :: i < SUBBUF_SIZE ->
+        buffer_use_count[(read_off + i) % BUFSIZE]
+          = buffer_use_count[(read_off + i) % BUFSIZE] - 1;
+        i++
+      :: i >= SUBBUF_SIZE -> break
+      od;
+      read_off = read_off + SUBBUF_SIZE;
+    }
+  :: read_off >= (NUMPROCS - events_lost) -> break;
+  od;
+}
+
+proctype cleaner()
+{
+  atomic {
+    do
+    :: refcount == 0 ->
+      run switcher();
+      break;
+    od;
+  }
+}
+
+init {
+  int i = 0;
+  int j = 0;
+  int sum = 0;
+  int commit_sum = 0;
+
+  atomic {
+    i = 0;
+    do
+    :: i < NR_SUBBUFS ->
+      commit_count[i] = 0;
+      i++
+    :: i >= NR_SUBBUFS -> break
+    od;
+    i = 0;
+    do
+    :: i < BUFSIZE ->
+      buffer_use_count[i] = 0;
+      i++
+    :: i >= BUFSIZE -> break
+    od;
+    run reader();
+    run cleaner();
+    i = 0;
+    do
+    :: i < NUMPROCS ->
+      refcount = refcount + 1;
+      run tracer(1);
+      i++
+    :: i >= NUMPROCS -> break
+    od;
+    run switcher();
+  }
+  atomic {
+    assert(write_off - read_off >= 0);
+    j = 0;
+    commit_sum = 0;
+    do
+    :: j < NR_SUBBUFS ->
+      commit_sum = commit_sum + commit_count[j];
+      j++
+    :: j >= NR_SUBBUFS -> break
+    od;
+    assert(commit_sum <= write_off);
+    j = 0;
+    do
+    :: j < BUFSIZE ->
+      assert(buffer_use_count[j] < 2);
+      j++
+    :: j >= BUFSIZE -> break
+    od;
+
+    //assert(events_lost == 0);
+  }
+}
diff --git a/trunk/verif/examples/buffer.spin.trail b/trunk/verif/examples/buffer.spin.trail
new file mode 100644 (file)
index 0000000..93bb333
--- /dev/null
@@ -0,0 +1,102 @@
+-4:-4:-4
+1:0:120
+2:0:121
+3:0:121
+4:0:125
+5:0:131
+6:0:131
+7:0:131
+8:0:131
+9:0:134
+10:0:139
+11:0:140
+12:0:142
+13:0:144
+14:0:142
+15:0:144
+16:0:142
+17:0:144
+18:0:146
+19:0:152
+20:0:154
+21:0:156
+22:0:160
+23:6:0
+24:6:6
+25:6:7
+26:6:13
+27:6:14
+28:6:18
+29:6:20
+30:6:28
+31:6:29
+32:5:30
+33:5:35
+34:5:36
+35:5:42
+36:5:43
+37:5:47
+38:5:51
+39:5:55
+40:5:57
+41:5:58
+42:5:61
+43:5:70
+44:5:71
+45:5:75
+46:5:77
+47:5:79
+48:4:30
+49:4:35
+50:4:36
+51:4:42
+52:4:43
+53:4:47
+54:4:51
+55:4:55
+56:4:57
+57:4:58
+58:4:61
+59:4:68
+60:4:75
+61:4:77
+62:4:79
+63:3:30
+64:3:33
+65:3:76
+66:3:77
+67:3:79
+68:2:111
+69:2:113
+70:2:117
+71:3:0
+72:3:3
+73:3:28
+74:3:29
+75:2:119
+76:1:80
+77:1:81
+78:1:82
+79:1:82
+80:1:86
+81:1:90
+82:1:92
+83:1:93
+84:1:93
+85:1:96
+86:1:80
+87:1:81
+88:1:82
+89:1:82
+90:1:86
+91:1:90
+92:1:92
+93:1:93
+94:1:93
+95:1:96
+96:1:105
+97:1:110
+98:0:162
+99:0:165
+100:0:165
+101:0:169
diff --git a/trunk/verif/examples/pan b/trunk/verif/examples/pan
new file mode 100755 (executable)
index 0000000..a0356c1
Binary files /dev/null and b/trunk/verif/examples/pan differ
diff --git a/trunk/verif/examples/pan.b b/trunk/verif/examples/pan.b
new file mode 100644 (file)
index 0000000..8816afb
--- /dev/null
@@ -0,0 +1,439 @@
+       switch (t->back) {
+       default: Uerror("bad return move");
+       case  0: goto R999; /* nothing to undo */
+
+                /* PROC :init: */
+
+       case 3: /* STATE 1 */
+               ;
+               ((P4 *)this)->i = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 4: /* STATE 5 */
+               ;
+               ((P4 *)this)->i = trpt->bup.ovals[2];
+               now.retrieve_count[ Index(((P4 *)this)->i, 2) ] = trpt->bup.ovals[1];
+               now.commit_count[ Index(((P4 *)this)->i, 2) ] = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 3);
+               goto R999;
+
+       case 5: /* STATE 11 */
+               ;
+               ((P4 *)this)->i = trpt->bup.ovals[1];
+       /* 0 */ ((P4 *)this)->i = trpt->bup.ovals[0];
+               ;
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 6: /* STATE 11 */
+               ;
+               ((P4 *)this)->i = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 7: /* STATE 14 */
+               ;
+               ((P4 *)this)->i = trpt->bup.ovals[1];
+               now.buffer_use[ Index(((P4 *)this)->i, 4) ] = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 8: /* STATE 15 */
+               ;
+       /* 0 */ ((P4 *)this)->i = trpt->bup.oval;
+               ;
+               ;
+               goto R999;
+
+       case 9: /* STATE 20 */
+               ;
+               ;
+               delproc(0, now._nr_pr-1);
+               ;
+               goto R999;
+
+       case 10: /* STATE 22 */
+               ;
+               ((P4 *)this)->i = trpt->bup.oval;
+               ;
+               delproc(0, now._nr_pr-1);
+               ;
+               goto R999;
+
+       case 11: /* STATE 24 */
+               ;
+               now.refcount = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 12: /* STATE 26 */
+               ;
+               ((P4 *)this)->i = trpt->bup.oval;
+               ;
+               delproc(0, now._nr_pr-1);
+               ;
+               goto R999;
+
+       case 13: /* STATE 32 */
+               ;
+               ((P4 *)this)->i = trpt->bup.ovals[1];
+       /* 0 */ ((P4 *)this)->i = trpt->bup.ovals[0];
+               ;
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 14: /* STATE 32 */
+               ;
+               ((P4 *)this)->i = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 15: /* STATE 34 */
+               ;
+               now.refcount = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 16: /* STATE 36 */
+               ;
+               ((P4 *)this)->i = trpt->bup.oval;
+               ;
+               delproc(0, now._nr_pr-1);
+               ;
+               goto R999;
+
+       case 17: /* STATE 37 */
+               ;
+       /* 0 */ ((P4 *)this)->i = trpt->bup.oval;
+               ;
+               ;
+               goto R999;
+
+       case 18: /* STATE 45 */
+               ;
+               ((P4 *)this)->commit_sum = trpt->bup.ovals[1];
+               ((P4 *)this)->j = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 19: /* STATE 49 */
+               ;
+               ((P4 *)this)->j = trpt->bup.ovals[1];
+               ((P4 *)this)->commit_sum = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 20: /* STATE 50 */
+               ;
+       /* 0 */ ((P4 *)this)->j = trpt->bup.oval;
+               ;
+               ;
+               goto R999;
+;
+               
+       case 21: /* STATE 55 */
+               goto R999;
+
+       case 22: /* STATE 58 */
+               ;
+               p_restor(II);
+               ;
+               ;
+               goto R999;
+
+                /* PROC cleaner */
+
+       case 23: /* STATE 2 */
+               ;
+               now.refcount = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 24: /* STATE 3 */
+               ;
+               ;
+               delproc(0, now._nr_pr-1);
+               ;
+               goto R999;
+
+       case 25: /* STATE 9 */
+               ;
+               p_restor(II);
+               ;
+               ;
+               goto R999;
+
+                /* PROC reader */
+;
+               ;
+               
+       case 27: /* STATE 2 */
+               ;
+               ((P2 *)this)->i = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 28: /* STATE 6 */
+               ;
+               ((P2 *)this)->i = trpt->bup.ovals[1];
+               now.buffer_use[ Index(((now.read_off+((P2 *)this)->i)%4), 4) ] = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 29: /* STATE 7 */
+               ;
+       /* 0 */ ((P2 *)this)->i = trpt->bup.oval;
+               ;
+               ;
+               goto R999;
+
+       case 30: /* STATE 16 */
+               ;
+               ((P2 *)this)->i = trpt->bup.ovals[1];
+               now.buffer_use[ Index(((now.read_off+((P2 *)this)->i)%4), 4) ] = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 31: /* STATE 24 */
+               ;
+               now.read_off = trpt->bup.ovals[3];
+               now.retrieve_count[ Index(((now.read_off%4)/(4/2)), 2) ] = trpt->bup.ovals[2];
+               ((P2 *)this)->tmp_retrieve = trpt->bup.ovals[1];
+       /* 0 */ ((P2 *)this)->i = trpt->bup.ovals[0];
+               ;
+               ;
+               ungrab_ints(trpt->bup.ovals, 4);
+               goto R999;
+
+       case 32: /* STATE 24 */
+               ;
+               now.read_off = trpt->bup.ovals[2];
+               now.retrieve_count[ Index(((now.read_off%4)/(4/2)), 2) ] = trpt->bup.ovals[1];
+               ((P2 *)this)->tmp_retrieve = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 3);
+               goto R999;
+;
+               ;
+               
+       case 34: /* STATE 31 */
+               ;
+               p_restor(II);
+               ;
+               ;
+               goto R999;
+
+                /* PROC tracer */
+
+       case 35: /* STATE 2 */
+               ;
+               ((P1 *)this)->new_off = trpt->bup.ovals[1];
+               ((P1 *)this)->prev_off = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 36: /* STATE 4 */
+               ;
+       /* 0 */ ((P1 *)this)->new_off = trpt->bup.oval;
+               ;
+               ;
+               goto R999;
+;
+               
+       case 37: /* STATE 7 */
+               goto R999;
+
+       case 38: /* STATE 11 */
+               ;
+       /* 0 */ ((P1 *)this)->prev_off = trpt->bup.oval;
+               ;
+               ;
+               goto R999;
+
+       case 39: /* STATE 17 */
+               ;
+               ((P1 *)this)->i = trpt->bup.ovals[1];
+               now.write_off = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 40: /* STATE 17 */
+               ;
+               ((P1 *)this)->i = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 41: /* STATE 21 */
+               ;
+               ((P1 *)this)->i = trpt->bup.ovals[1];
+               now.buffer_use[ Index(((((P1 *)this)->prev_off+((P1 *)this)->i)%4), 4) ] = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 42: /* STATE 22 */
+               ;
+       /* 0 */ ((P1 *)this)->i = trpt->bup.oval;
+               ;
+               ;
+               goto R999;
+
+       case 43: /* STATE 28 */
+               ;
+               ((P1 *)this)->i = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 44: /* STATE 31 */
+               ;
+               ((P1 *)this)->i = trpt->bup.ovals[1];
+               now.buffer_use[ Index(((((P1 *)this)->prev_off+((P1 *)this)->i)%4), 4) ] = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 45: /* STATE 38 */
+               ;
+               now.commit_count[ Index(((((P1 *)this)->prev_off%4)/(4/2)), 2) ] = trpt->bup.ovals[2];
+               ((P1 *)this)->tmp_commit = trpt->bup.ovals[1];
+       /* 0 */ ((P1 *)this)->i = trpt->bup.ovals[0];
+               ;
+               ;
+               ungrab_ints(trpt->bup.ovals, 3);
+               goto R999;
+
+       case 46: /* STATE 38 */
+               ;
+               now.commit_count[ Index(((((P1 *)this)->prev_off%4)/(4/2)), 2) ] = trpt->bup.ovals[1];
+               ((P1 *)this)->tmp_commit = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 47: /* STATE 40 */
+               ;
+               deliver = trpt->bup.ovals[1];
+       /* 0 */ ((P1 *)this)->tmp_commit = trpt->bup.ovals[0];
+               ;
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+;
+               
+       case 48: /* STATE 44 */
+               goto R999;
+;
+               
+       case 49: /* STATE 42 */
+               goto R999;
+
+       case 50: /* STATE 47 */
+               ;
+               now.events_lost = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 51: /* STATE 48 */
+               ;
+               now.refcount = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 52: /* STATE 50 */
+               ;
+               p_restor(II);
+               ;
+               ;
+               goto R999;
+
+                /* PROC switcher */
+
+       case 53: /* STATE 3 */
+               ;
+               ((P0 *)this)->new_off = trpt->bup.ovals[2];
+               ((P0 *)this)->size = trpt->bup.ovals[1];
+               ((P0 *)this)->prev_off = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 3);
+               goto R999;
+
+       case 54: /* STATE 5 */
+               ;
+               now.refcount = trpt->bup.ovals[2];
+       /* 1 */ ((P0 *)this)->size = trpt->bup.ovals[1];
+       /* 0 */ ((P0 *)this)->new_off = trpt->bup.ovals[0];
+               ;
+               ;
+               ungrab_ints(trpt->bup.ovals, 3);
+               goto R999;
+;
+               
+       case 55: /* STATE 8 */
+               goto R999;
+
+       case 56: /* STATE 12 */
+               ;
+       /* 0 */ ((P0 *)this)->prev_off = trpt->bup.oval;
+               ;
+               ;
+               goto R999;
+;
+               
+       case 57: /* STATE 17 */
+               goto R999;
+
+       case 58: /* STATE 15 */
+               ;
+               now.write_off = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 59: /* STATE 20 */
+               ;
+               now.commit_count[ Index(((((P0 *)this)->prev_off%4)/(4/2)), 2) ] = trpt->bup.ovals[1];
+               ((P0 *)this)->tmp_commit = trpt->bup.ovals[0];
+               ;
+               ungrab_ints(trpt->bup.ovals, 2);
+               goto R999;
+
+       case 60: /* STATE 27 */
+               ;
+               now.refcount = trpt->bup.ovals[2];
+               deliver = trpt->bup.ovals[1];
+       /* 0 */ ((P0 *)this)->tmp_commit = trpt->bup.ovals[0];
+               ;
+               ;
+               ungrab_ints(trpt->bup.ovals, 3);
+               goto R999;
+
+       case 61: /* STATE 27 */
+               ;
+               now.refcount = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 62: /* STATE 27 */
+               ;
+               now.refcount = trpt->bup.oval;
+               ;
+               goto R999;
+
+       case 63: /* STATE 30 */
+               ;
+               p_restor(II);
+               ;
+               ;
+               goto R999;
+       }
+
diff --git a/trunk/verif/examples/pan.c b/trunk/verif/examples/pan.c
new file mode 100644 (file)
index 0000000..928afc4
--- /dev/null
@@ -0,0 +1,11530 @@
+/*** Generated by Spin Version 5.1.6 -- 9 May 2008 ***/
+/*** From source: buffer.spin ***/
+
+#ifdef SC
+#define _FILE_OFFSET_BITS      64
+#endif
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#if defined(WIN32) || defined(WIN64)
+#include <time.h>
+#else
+#include <unistd.h>
+#include <sys/times.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#define Offsetof(X, Y) ((unsigned long)(&(((X *)0)->Y)))
+#ifndef max
+#define max(a,b) (((a)<(b)) ? (b) : (a))
+#endif
+#ifndef PRINTF
+int Printf(const char *fmt, ...); /* prototype only */
+#endif
+#include "pan.h"
+#ifdef LOOPSTATE
+double cnt_loops;
+#endif
+State  A_Root; /* seed-state for cycles */
+State  now;    /* the full state-vector */
+#undef C_States
+#if defined(C_States) && defined(HAS_TRACK)
+void
+c_update(uchar *p_t_r)
+{
+#ifdef VERBOSE
+       printf("c_update %u\n", p_t_r);
+#endif
+}
+void
+c_revert(uchar *p_t_r)
+{
+#ifdef VERBOSE
+       printf("c_revert %u\n", p_t_r);
+#endif
+}
+#endif
+void
+globinit(void)
+{
+}
+void
+locinit4(int h)
+{
+}
+void
+locinit3(int h)
+{
+}
+void
+locinit2(int h)
+{
+}
+void
+locinit1(int h)
+{
+}
+void
+locinit0(int h)
+{
+}
+#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]--
+#endif
+#if !defined(SAFETY) && !defined(NOCOMP)
+#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
+#endif
+#ifdef MA
+#undef onstack_now
+#undef onstack_put
+#undef onstack_zap
+#define onstack_put()  ;
+#define onstack_zap()  gstore((char *) &now, vsize, 4)
+#else
+#if defined(FULLSTACK) && !defined(BITSTATE)
+#define onstack_put()  trpt->ostate = Lstate
+#define onstack_zap()  { \
+       if (trpt->ostate) \
+               trpt->ostate->tagged = \
+               (S_A)? (trpt->ostate->tagged&~V_A) : 0; \
+       }
+#endif
+#endif
+#ifndef NO_V_PROVISO
+#define V_PROVISO
+#endif
+#if !defined(NO_RESIZE) && !defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(SPACE) && NCORE==1
+       #define AUTO_RESIZE
+#endif
+
+struct H_el {
+       struct H_el *nxt;
+#ifdef FULLSTACK
+       unsigned int tagged;
+       #if defined(BITSTATE) && !defined(NOREDUCE) && !defined(SAFETY)
+       unsigned int proviso;
+       #endif
+#endif
+#if defined(CHECK) || (defined(COLLAPSE) && !defined(FULLSTACK))
+       unsigned long st_id;
+#endif
+#if !defined(SAFETY) || defined(REACH)
+       unsigned int D;
+#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
+       unsigned short ln;
+       #else
+       unsigned long ln;
+       #endif
+#endif
+#if defined(AUTO_RESIZE) && !defined(BITSTATE)
+       unsigned long m_K1;
+#endif
+       unsigned long state;
+} **H_tab, **S_Tab;
+
+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
+#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
+       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) || (NCORE>1)
+       struct H_el *ostate;    /* pointer to stored state */
+#endif
+#if defined(CNTRSTACK) && !defined(BFS)
+       long    j6, j7;
+#endif
+       Trans *o_t;
+#ifdef SCHED
+       /* based on Qadeer&Rehof, Tacas 2005, LNCS 3440, pp. 93-107 */
+       #if NCORE>1
+       #error "-DSCHED cannot be combined with -DNCORE (yet)"
+       #endif
+       int     sched_limit;
+#endif
+#ifdef HAS_SORTED
+       short ipt;
+#endif
+       union {
+               int oval;
+               int *ovals;
+       } bup;
+} Trail;
+Trail  *trail, *trpt;
+FILE   *efd;
+uchar  *this;
+long   maxdepth=10000;
+long   omaxdepth=10000;
+#ifdef SCHED
+int    sched_max = 10;
+#endif
+#ifdef PERMUTED
+       uchar   permuted = 1;
+#else
+       uchar   permuted = 0;
+#endif
+double quota;  /* time limit */
+#if NCORE>1
+long   z_handoff = -1;
+#endif
+#ifdef SC
+char   *stackfile;
+#endif
+uchar  *SS, *LL;
+uchar  HASH_NR = 0;
+
+double memcnt = (double) 0;
+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;
+
+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
+};
+#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;
+#if defined(ZAPH) && defined(BITSTATE)
+double zstates = 0;
+#endif
+int    c_init_run;
+#ifdef BFS
+double midrv=0, failedrv=0, revrv=0;
+#endif
+unsigned long  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;
+int    whichtrail = 0, onlyproc = -1, silent = 0;
+#endif
+int    state_tables=0, fairness=0, no_rck=0, Nr_Trails=0;
+char   simvals[128];
+#ifndef INLINE
+int    TstOnly=0;
+#endif
+unsigned long mask, nmask;
+#ifdef BITSTATE
+int    ssize=23;       /* 1 Mb */
+#else
+int    ssize=19;       /* 512K slots */
+#endif
+int    hmax=0, svmax=0, smax=0;
+int    Maxbody=0, XX;
+uchar  *noptr; /* used by macro Pptr(x) */
+#ifdef VAR_RANGES
+void logval(char *, int);
+void dumpranges(void);
+#endif
+#ifdef MA
+#define INLINE_REV
+extern void dfa_init(unsigned short);
+extern int  dfa_member(unsigned long);
+extern int  dfa_store(uchar *);
+unsigned int   maxgs = 0;
+#endif
+
+#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
+
+State  comp_msk;
+uchar  *Mask = (uchar *) &comp_msk;
+#ifdef COLLAPSE
+State  comp_tmp;
+static char    *scratch = (char *) &comp_tmp;
+#endif
+Stack  *stack;         /* for queues, processes */
+Svtack *svtack;        /* for old state vectors */
+#ifdef BITSTATE
+static unsigned int hfns = 3;  /* new default */
+#endif
+static unsigned long j1;
+static unsigned long K1, K2;
+static unsigned long j2, j3, j4;
+#ifdef BITSTATE
+static long udmem;
+#endif
+static long    A_depth = 0;
+long   depth = 0;
+#if NCORE>1
+long nr_handoffs = 0;
+#endif
+static uchar   warned = 0, iterative = 0, exclusive = 0, like_java = 0, every_error = 0;
+static uchar   noasserts = 0, noends = 0, bounded = 0;
+#if SYNC>0 && ASYNC==0
+void set_recvs(void);
+int  no_recvs(int);
+#endif
+#if SYNC
+#define IfNotBlocked   if (boq != -1) continue;
+#define UnBlock        boq = -1
+#else
+#define IfNotBlocked   /* cannot block */
+#define UnBlock        /* don't bother */
+#endif
+
+#ifdef BITSTATE
+int (*bstore)(char *, int);
+int bstore_reg(char *, int);
+int bstore_mod(char *, int);
+#endif
+void active_procs(void);
+void cleanup(void);
+void do_the_search(void);
+void find_shorter(int);
+void iniglobals(void);
+void stopped(int);
+void wrapup(void);
+int *grab_ints(int);
+void ungrab_ints(int *, int);
+#ifndef NOBOUNDCHECK
+#define Index(x, y)    Boundcheck(x, y, II, tt, t)
+#else
+#define Index(x, y)    x
+#endif
+short Air[] = {  (short) Air0, (short) Air1, (short) Air2, (short) Air3, (short) Air4, (short) Air5 };
+int
+addproc(int n)
+{      int j, h = now._nr_pr;
+#ifndef NOCOMP
+       int k;
+#endif
+       uchar *o_this = this;
+
+#ifndef INLINE
+       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)
+#endif
+       if (h >= MAXPROC)
+               Uerror("too many processes");
+       switch (n) {
+       case 0: j = sizeof(P0); break;
+       case 1: j = sizeof(P1); break;
+       case 2: j = sizeof(P2); break;
+       case 3: j = sizeof(P3); break;
+       case 4: j = sizeof(P4); break;
+       case 5: j = sizeof(P5); break;
+       default: Uerror("bad proc - addproc");
+       }
+       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
+       vsize += (int) proc_skip[h];
+       proc_offset[h] = vsize;
+#ifdef SVDUMP
+       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
+               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 */
+       }
+#endif
+       now._nr_pr += 1;
+       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",
+                       (8*NFAIR)/2 - 2, NFAIR);
+               printf("\trecompile with -DNFAIR=%d\n",
+                       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);
+       if (vsize >= VECTORSZ)
+       {       printf("pan: error, VECTORSZ too small, recompile pan.c");
+               printf(" with -DVECTORSZ=N with N>%d\n", (int) vsize);
+               Uerror("aborting");
+       }
+       memset((char *)pptr(h), 0, j);
+       this = pptr(h);
+       if (BASE > 0 && h > 0)
+               ((P0 *)this)->_pid = h-BASE;
+       else
+               ((P0 *)this)->_pid = h;
+       switch (n) {
+       case 5: /* np_ */
+               ((P5 *)pptr(h))->_t = 5;
+               ((P5 *)pptr(h))->_p = 0;
+               reached5[0] = 1;
+               accpstate[5][1] = 1;
+               break;
+       case 4: /* :init: */
+               ((P4 *)pptr(h))->_t = 4;
+               ((P4 *)pptr(h))->_p = 42; reached4[42]=1;
+               /* params: */
+               /* locals: */
+               ((P4 *)pptr(h))->i = 0;
+               ((P4 *)pptr(h))->j = 0;
+               ((P4 *)pptr(h))->sum = 0;
+               ((P4 *)pptr(h))->commit_sum = 0;
+#ifdef VAR_RANGES
+               logval(":init::i", ((P4 *)pptr(h))->i);
+               logval(":init::j", ((P4 *)pptr(h))->j);
+               logval(":init::sum", ((P4 *)pptr(h))->sum);
+               logval(":init::commit_sum", ((P4 *)pptr(h))->commit_sum);
+#endif
+#ifdef HAS_CODE
+               locinit4(h);
+#endif
+               break;
+       case 3: /* cleaner */
+               ((P3 *)pptr(h))->_t = 3;
+               ((P3 *)pptr(h))->_p = 8; reached3[8]=1;
+               /* params: */
+               /* locals: */
+#ifdef VAR_RANGES
+#endif
+#ifdef HAS_CODE
+               locinit3(h);
+#endif
+               break;
+       case 2: /* reader */
+               ((P2 *)pptr(h))->_t = 2;
+               ((P2 *)pptr(h))->_p = 28; reached2[28]=1;
+               /* params: */
+               /* locals: */
+               ((P2 *)pptr(h))->i = 0;
+               ((P2 *)pptr(h))->j = 0;
+               ((P2 *)pptr(h))->tmp_retrieve = 0;
+               ((P2 *)pptr(h))->lwrite_off = 0;
+               ((P2 *)pptr(h))->lcommit_count = 0;
+#ifdef VAR_RANGES
+               logval("reader:i", ((P2 *)pptr(h))->i);
+               logval("reader:j", ((P2 *)pptr(h))->j);
+               logval("reader:tmp_retrieve", ((P2 *)pptr(h))->tmp_retrieve);
+               logval("reader:lwrite_off", ((P2 *)pptr(h))->lwrite_off);
+               logval("reader:lcommit_count", ((P2 *)pptr(h))->lcommit_count);
+#endif
+#ifdef HAS_CODE
+               locinit2(h);
+#endif
+               break;
+       case 1: /* tracer */
+               ((P1 *)pptr(h))->_t = 1;
+               ((P1 *)pptr(h))->_p = 3; reached1[3]=1;
+               /* params: */
+               /* locals: */
+               ((P1 *)pptr(h))->size = 1;
+               ((P1 *)pptr(h))->prev_off = 0;
+               ((P1 *)pptr(h))->new_off = 0;
+               ((P1 *)pptr(h))->tmp_commit = 0;
+               ((P1 *)pptr(h))->i = 0;
+               ((P1 *)pptr(h))->j = 0;
+#ifdef VAR_RANGES
+               logval("tracer:size", ((P1 *)pptr(h))->size);
+               logval("tracer:prev_off", ((P1 *)pptr(h))->prev_off);
+               logval("tracer:new_off", ((P1 *)pptr(h))->new_off);
+               logval("tracer:tmp_commit", ((P1 *)pptr(h))->tmp_commit);
+               logval("tracer:i", ((P1 *)pptr(h))->i);
+               logval("tracer:j", ((P1 *)pptr(h))->j);
+#endif
+#ifdef HAS_CODE
+               locinit1(h);
+#endif
+               break;
+       case 0: /* switcher */
+               ((P0 *)pptr(h))->_t = 0;
+               ((P0 *)pptr(h))->_p = 11; reached0[11]=1;
+               /* params: */
+               /* locals: */
+               ((P0 *)pptr(h))->prev_off = 0;
+               ((P0 *)pptr(h))->new_off = 0;
+               ((P0 *)pptr(h))->tmp_commit = 0;
+               ((P0 *)pptr(h))->size = 0;
+#ifdef VAR_RANGES
+               logval("switcher:prev_off", ((P0 *)pptr(h))->prev_off);
+               logval("switcher:new_off", ((P0 *)pptr(h))->new_off);
+               logval("switcher:tmp_commit", ((P0 *)pptr(h))->tmp_commit);
+               logval("switcher:size", ((P0 *)pptr(h))->size);
+#endif
+#ifdef HAS_CODE
+               locinit0(h);
+#endif
+               break;
+       }
+       this = o_this;
+       return h-BASE;
+#ifndef NOBOUNDCHECK
+#undef Index
+#define Index(x, y)    Boundcheck(x, y, II, tt, t)
+#endif
+}
+
+#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; }
+#endif
+#ifndef BITSTATE
+#ifdef COLLAPSE
+long
+col_p(int i, char *z)
+{      int j, k; unsigned long ordinal(char *, long, short);
+       char *x, *y;
+       P0 *ptr = (P0 *) pptr(i);
+       switch (ptr->_t) {
+       case 0: j = sizeof(P0); break;
+       case 1: j = sizeof(P1); break;
+       case 2: j = sizeof(P2); break;
+       case 3: j = sizeof(P3); break;
+       case 4: j = sizeof(P4); break;
+       case 5: j = sizeof(P5); break;
+       default: Uerror("bad proctype - collapse");
+       }
+       if (z) x = z; else x = scratch;
+       y = (char *) ptr; k = proc_offset[i];
+       for ( ; j > 0; j--, y++)
+               if (!Mask[k++]) *x++ = *y;
+       for (j = 0; j < WS-1; j++)
+               *x++ = 0;
+       x -= j;
+       if (z) return (long) (x - z);
+       return ordinal(scratch, x-scratch, (short) (2+ptr->_t));
+}
+#endif
+#endif
+void
+run(void)
+{      /* int i; */
+       memset((char *)&now, 0, sizeof(State));
+       vsize = (unsigned long) (sizeof(State) - VECTORSZ);
+#ifndef NOVSZ
+       now._vsz = vsize;
+#endif
+/* optional provisioning statements, e.g. to */
+/* set hidden variables, used as constants */
+#ifdef PROV
+#include PROV
+#endif
+       settable();
+       Maxbody = max(Maxbody, ((int) sizeof(P0)));
+       Maxbody = max(Maxbody, ((int) sizeof(P1)));
+       Maxbody = max(Maxbody, ((int) sizeof(P2)));
+       Maxbody = max(Maxbody, ((int) sizeof(P3)));
+       Maxbody = max(Maxbody, ((int) sizeof(P4)));
+       Maxbody = max(Maxbody, ((int) sizeof(P5)));
+       reached[0] = reached0;
+       reached[1] = reached1;
+       reached[2] = reached2;
+       reached[3] = reached3;
+       reached[4] = reached4;
+       reached[5] = reached5;
+       accpstate[0] = (uchar *) emalloc(nstates0);
+       accpstate[1] = (uchar *) emalloc(nstates1);
+       accpstate[2] = (uchar *) emalloc(nstates2);
+       accpstate[3] = (uchar *) emalloc(nstates3);
+       accpstate[4] = (uchar *) emalloc(nstates4);
+       accpstate[5] = (uchar *) emalloc(nstates5);
+       progstate[0] = (uchar *) emalloc(nstates0);
+       progstate[1] = (uchar *) emalloc(nstates1);
+       progstate[2] = (uchar *) emalloc(nstates2);
+       progstate[3] = (uchar *) emalloc(nstates3);
+       progstate[4] = (uchar *) emalloc(nstates4);
+       progstate[5] = (uchar *) emalloc(nstates5);
+       loopstate0 = loopstate[0] = (uchar *) emalloc(nstates0);
+       loopstate1 = loopstate[1] = (uchar *) emalloc(nstates1);
+       loopstate2 = loopstate[2] = (uchar *) emalloc(nstates2);
+       loopstate3 = loopstate[3] = (uchar *) emalloc(nstates3);
+       loopstate4 = loopstate[4] = (uchar *) emalloc(nstates4);
+       loopstate5 = loopstate[5] = (uchar *) emalloc(nstates5);
+       stopstate[0] = (uchar *) emalloc(nstates0);
+       stopstate[1] = (uchar *) emalloc(nstates1);
+       stopstate[2] = (uchar *) emalloc(nstates2);
+       stopstate[3] = (uchar *) emalloc(nstates3);
+       stopstate[4] = (uchar *) emalloc(nstates4);
+       stopstate[5] = (uchar *) emalloc(nstates5);
+       visstate[0] = (uchar *) emalloc(nstates0);
+       visstate[1] = (uchar *) emalloc(nstates1);
+       visstate[2] = (uchar *) emalloc(nstates2);
+       visstate[3] = (uchar *) emalloc(nstates3);
+       visstate[4] = (uchar *) emalloc(nstates4);
+       visstate[5] = (uchar *) emalloc(nstates5);
+       mapstate[0] = (short *) emalloc(nstates0 * sizeof(short));
+       mapstate[1] = (short *) emalloc(nstates1 * sizeof(short));
+       mapstate[2] = (short *) emalloc(nstates2 * sizeof(short));
+       mapstate[3] = (short *) emalloc(nstates3 * sizeof(short));
+       mapstate[4] = (short *) emalloc(nstates4 * sizeof(short));
+       mapstate[5] = (short *) emalloc(nstates5 * sizeof(short));
+#ifdef HAS_CODE
+#ifdef HAS_CODE
+#ifdef HAS_CODE
+#ifdef HAS_CODE
+#ifdef HAS_CODE
+#ifdef HAS_CODE
+       NrStates[0] = nstates0;
+       NrStates[1] = nstates1;
+       NrStates[2] = nstates2;
+       NrStates[3] = nstates3;
+       NrStates[4] = nstates4;
+       NrStates[5] = nstates5;
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+       stopstate[0][endstate0] = 1;
+       stopstate[1][endstate1] = 1;
+       stopstate[2][endstate2] = 1;
+       stopstate[3][endstate3] = 1;
+       stopstate[4][endstate4] = 1;
+       stopstate[5][endstate5] = 1;
+       stopstate[1][48] = 1;
+       retrans(0, nstates0, start0, src_ln0, reached0, loopstate0);
+       retrans(1, nstates1, start1, src_ln1, reached1, loopstate1);
+       retrans(2, nstates2, start2, src_ln2, reached2, loopstate2);
+       retrans(3, nstates3, start3, src_ln3, reached3, loopstate3);
+       retrans(4, nstates4, start4, src_ln4, reached4, loopstate4);
+       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);
+       }
+       iniglobals();
+#if defined(VERI) && !defined(NOREDUCE) && !defined(NP)
+       if (!state_tables
+#ifdef HAS_CODE
+       && !readtrail
+#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");
+         printf("(never claims generated from LTL ");
+         printf("formulae are stutter-invariant)\n");
+       }
+#endif
+       UnBlock;        /* disable rendez-vous */
+#ifdef BITSTATE
+       if (udmem)
+       {       udmem *= 1024L*1024L;
+       #if NCORE>1
+               if (!readtrail)
+               {       void init_SS(unsigned long);
+                       init_SS((unsigned long) udmem);
+               } else
+       #endif
+               SS = (uchar *) emalloc(udmem);
+               bstore = bstore_mod;
+       } else
+       #if NCORE>1
+               { void init_SS(unsigned long);
+                 init_SS(ONE_L<<(ssize-3));
+               }
+       #else
+               SS = (uchar *) emalloc(ONE_L<<(ssize-3));
+       #endif
+#else
+       hinit();
+#endif
+#if defined(FULLSTACK) && defined(BITSTATE)
+       onstack_init();
+#endif
+#if defined(CNTRSTACK) && !defined(BFS)
+       LL = (uchar *) emalloc(ONE_L<<(ssize-3));
+#endif
+       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
+       if (vprefix > 0)
+               write(svfd, (uchar *) &vprefix, sizeof(int));
+#endif
+#ifdef VERI
+       Addproc(VERI);  /* never - pid = 0 */
+#endif
+       active_procs(); /* started after never */
+#ifdef EVENT_TRACE
+       now._event = start_event;
+       reached[EVENT_TRACE][start_event] = 1;
+#endif
+#ifdef HAS_CODE
+       globinit();
+#endif
+#ifdef BITSTATE
+go_again:
+#endif
+       do_the_search();
+#ifdef BITSTATE
+       if (--Nrun > 0 && HASH_CONST[++HASH_NR])
+       {       printf("Run %d:\n", HASH_NR);
+               wrap_stats();
+               printf("\n");
+               memset(SS, 0, ONE_L<<(ssize-3));
+#ifdef CNTRSTACK
+               memset(LL, 0, ONE_L<<(ssize-3));
+#endif
+#ifdef FULLSTACK
+               memset((uchar *) S_Tab, 0, 
+               maxdepth*sizeof(struct H_el *));
+#endif
+               nstates=nlinks=truncs=truncs2=ngrabs = 0;
+               nlost=nShadow=hcmp = 0;
+               Fa=Fh=Zh=Zn = 0;
+               PUT=PROBE=ZAPS=Ccheck=Cholds = 0;
+               goto go_again;
+       }
+#endif
+}
+#ifdef HAS_PROVIDED
+int provided(int, uchar, int, Trans *);
+#endif
+#if NCORE>1
+#define GLOBAL_LOCK    (0)
+#ifndef CS_N
+#define CS_N           (256*NCORE)
+#endif
+#ifdef NGQ
+#define NR_QS          (NCORE)
+#define CS_NR          (CS_N+1)        /* 2^N + 1, nr critical sections */
+#define GQ_RD          GLOBAL_LOCK
+#define GQ_WR          GLOBAL_LOCK
+#define CS_ID          (1 + (int) (j1 & (CS_N-1))) /* mask: 2^N - 1, zero reserved */
+#define QLOCK(n)       (1+n)
+#else
+#define NR_QS          (NCORE+1)
+#define CS_NR          (CS_N+3)
+#define GQ_RD          (1)
+#define GQ_WR          (2)
+#define CS_ID          (3 + (int) (j1 & (CS_N-1)))
+#define QLOCK(n)       (3+n)
+#endif
+
+void e_critical(int);
+void x_critical(int);
+
+#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, ...)
+{      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
+int
+cpu_printf(const char *fmt, ...)
+{      va_list args;
+       va_start(args, fmt);
+       vprintf(fmt, args);
+       va_end(args);
+       return 1;
+}
+#endif
+int
+Printf(const char *fmt, ...)
+{      /* Make sure the args to Printf
+        * are always evaluated (e.g., they
+        * could contain a run stmnt)
+        * but do not generate the output
+        * during verification runs
+        * unless explicitly wanted
+        * If this fails on your system
+        * compile SPIN itself -DPRINTF
+        * and this code is not generated
+        */
+#ifdef HAS_CODE
+       if (readtrail)
+       {       va_list args;
+               va_start(args, fmt);
+               vprintf(fmt, args);
+               va_end(args);
+               return 1;
+       }
+#endif
+#ifdef PRINTF
+       va_list args;
+       va_start(args, fmt);
+       vprintf(fmt, args);
+       va_end(args);
+#endif
+       return 1;
+}
+extern void printm(int);
+#ifndef SC
+#define getframe(i)    &trail[i];
+#else
+static long HHH, DDD, hiwater;
+static long CNT1, CNT2;
+static int stackwrite;
+static int stackread;
+static Trail frameptr;
+Trail *
+getframe(int d)
+{
+       if (CNT1 == CNT2)
+               return &trail[d];
+
+       if (d >= (CNT1-CNT2)*DDD)
+               return &trail[d - (CNT1-CNT2)*DDD];
+
+       if (!stackread
+       &&  (stackread = open(stackfile, 0)) < 0)
+       {       printf("getframe: cannot open %s\n", stackfile);
+               wrapup();
+       }
+       if (lseek(stackread, d* (off_t) sizeof(Trail), SEEK_SET) == -1
+       || read(stackread, &frameptr, sizeof(Trail)) != sizeof(Trail))
+       {       printf("getframe: frame read error\n");
+               wrapup();
+       }
+       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;
+}
+#endif
+#endif
+#if NCORE>1
+extern void cleanup_shm(int);
+volatile unsigned int  *search_terminated; /* to signal early termination */
+#endif
+void
+pan_exit(int val)
+{      void stop_timer(void);
+       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
+       if (val == 2)
+       {       val = 0;
+       } else
+       {       stop_timer();
+       }
+       exit(val);
+}
+#ifdef HAS_CODE
+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")))
+       {       *v = '\0'; v++;
+               strcpy(buf[1-toggle], buf[toggle]);
+               for (w = v; *w != '}' && *w != '\0'; w++) /* skip */;
+               if (*w != '}') return s;
+               *w = '\0'; w++;
+               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])
+                                +  strlen(code_lookup[i].t)
+                                +  strlen(w) > 2047)
+                                       return s;
+                               strcat(buf[1-toggle], code_lookup[i].t);
+                               break;
+                       }
+               strcat(buf[1-toggle], w);
+               toggle = 1 - toggle;
+       }
+       buf[toggle][2047] = '\0';
+       return buf[toggle];
+}
+#else
+char * transmognify(char *s) { return s; }
+#endif
+#ifdef HAS_CODE
+void
+add_src_txt(int ot, int tt)
+{      Trans *t;
+       char *q;
+
+       for (t = trans[ot][tt]; t; t = t->nxt)
+       {       printf("\t\t");
+               q = transmognify(t->tp);
+               for ( ; q && *q; q++)
+                       if (*q == '\n')
+                               printf("\\n");
+                       else
+                               putchar(*q);
+               printf("\n");
+       }
+}
+void
+wrap_trail(void)
+{      static int wrap_in_progress = 0;
+       int i; short II;
+       P0 *z;
+
+       if (wrap_in_progress++) return;
+
+       printf("spin: trail ends after %ld steps\n", depth);
+       if (onlyproc >= 0)
+       {       if (onlyproc >= now._nr_pr) { pan_exit(0); }
+               II = onlyproc;
+               z = (P0 *)pptr(II);
+               printf("%3ld:   proc %d (%s) ",
+                       depth, II, procname[z->_t]);
+               for (i = 0; src_all[i].src; i++)
+                       if (src_all[i].tp == (int) z->_t)
+                       {       printf(" line %3d",
+                                       src_all[i].src[z->_p]);
+                               break;
+                       }
+               printf(" (state %2d)", z->_p);
+               if (!stopstate[z->_t][z->_p])
+                       printf(" (invalid end state)");
+               printf("\n");
+               add_src_txt(z->_t, z->_p);
+               pan_exit(0);
+       }
+       printf("#processes %d:\n", now._nr_pr);
+       if (depth < 0) depth = 0;
+       for (II = 0; II < now._nr_pr; II++)
+       {       z = (P0 *)pptr(II);
+               printf("%3ld:   proc %d (%s) ",
+                       depth, II, procname[z->_t]);
+               for (i = 0; src_all[i].src; i++)
+                       if (src_all[i].tp == (int) z->_t)
+                       {       printf(" line %3d",
+                                       src_all[i].src[z->_p]);
+                               break;
+                       }
+               printf(" (state %2d)", z->_p);
+               if (!stopstate[z->_t][z->_p])
+                       printf(" (invalid end state)");
+               printf("\n");
+               add_src_txt(z->_t, z->_p);
+       }
+       c_globals();
+       for (II = 0; II < now._nr_pr; II++)
+       {       z = (P0 *)pptr(II);
+               c_locals(II, z->_t);
+       }
+#ifdef ON_EXIT
+       ON_EXIT;
+#endif
+       pan_exit(0);
+}
+FILE *
+findtrail(void)
+{      FILE *fd;
+       char fnm[512], *q;
+       char MyFile[512];
+       char MySuffix[16];
+       int  try_core;
+       int  candidate_files;
+
+       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';
+                               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';
+                               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';
+                       sprintf(fnm, "%s%d.%s",
+                               MyFile, whichtrail, tprefix);
+                       *q = '.';
+                       fd = fopen(fnm, "r");
+               }
+       } else
+       {       sprintf(fnm, "%s.%s", MyFile, tprefix);
+               fd = fopen(fnm, "r");
+               if (fd == NULL && (q = strchr(MyFile, '.')))
+               {       *q = '\0';
+                       sprintf(fnm, "%s.%s", MyFile, tprefix);
+                       *q = '.';
+                       fd = fopen(fnm, "r");
+       }       }
+       if (fd == NULL)
+       {       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);
+
+void
+getrail(void)
+{      FILE *fd;
+       char *q;
+       int i, t_id, lastnever=-1; short II;
+       Trans *t;
+       P0 *z;
+
+       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");
+               if (depth < 0)
+                       continue;
+               if (i > now._nr_pr)
+               {       printf("pan: Error, proc %d invalid pid ", i);
+                       printf("transition %d\n", t_id);
+                       break;
+               }
+               II = i;
+               z = (P0 *)pptr(II);
+               for (t = trans[z->_t][z->_p]; t; t = t->nxt)
+                       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) t_id)
+                               {       printf("\tRecovered at state %d\n", i);
+                                       z->_p = i;
+                                       goto recovered;
+                       }       }
+                       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);
+                       break; /* pan_exit(1); */
+               }
+recovered:
+               q = transmognify(t->tp);
+               if (gui) simvals[0] = '\0';
+               this = pptr(II);
+               trpt->tau |= 1;
+               if (!do_transit(t, II))
+               {       if (onlyproc >= 0 && II != onlyproc)
+                               goto moveon;
+                       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");
+               }
+               if (onlyproc >= 0 && II != onlyproc)
+                       goto moveon;
+               if (verbose)
+               {       printf("%3ld: proc %2d (%s) ", depth, II, procname[z->_t]);
+                       for (i = 0; src_all[i].src; i++)
+                               if (src_all[i].tp == (int) z->_t)
+                               {       printf(" line %3d \"%s\" ",
+                                               src_all[i].src[z->_p], PanSource);
+                                       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)
+               {       if (lastnever != (int) z->_p)
+                       {       for (i = 0; src_all[i].src; i++)
+                                       if (src_all[i].tp == (int) z->_t)
+                                       {       printf("MSC: ~G %d\n",
+                                                       src_all[i].src[z->_p]);
+                                               break;
+                                       }
+                               if (!src_all[i].src)
+                                       printf("MSC: ~R %d\n", z->_p);
+                       }
+                       lastnever = z->_p;
+                       goto sameas;
+               } else
+               if (strcmp(procname[z->_t], ":np_:") != 0)
+               {
+sameas:                if (no_rck) goto moveon;
+                       if (coltrace)
+                       {       printf("%ld: ", depth);
+                               for (i = 0; i < II; i++)
+                                       printf("\t\t");
+                               printf("%s(%d):", procname[z->_t], II);
+                               printf("[%s]\n", q?q:"");
+                       } else if (!silent)
+                       {       if (strlen(simvals) > 0) {
+                               printf("%3ld:   proc %2d (%s)", 
+                                       depth, II, procname[z->_t]);
+                               for (i = 0; src_all[i].src; i++)
+                                       if (src_all[i].tp == (int) z->_t)
+                                       {       printf(" line %3d \"%s\" ",
+                                                       src_all[i].src[z->_p], PanSource);
+                                               break;
+                                       }
+                               printf("(state %d)      [values: %s]\n", z->_p, simvals);
+                               }
+                               printf("%3ld:   proc %2d (%s)", 
+                                       depth, II, procname[z->_t]);
+                               for (i = 0; src_all[i].src; i++)
+                                       if (src_all[i].tp == (int) z->_t)
+                                       {       printf(" line %3d \"%s\" ",
+                                                       src_all[i].src[z->_p], PanSource);
+                                               break;
+                                       }
+                               printf("(state %d)      [%s]\n", z->_p, q?q:"");
+                       /*      printf("\n");   */
+               }       }
+moveon:        z->_p = t->st;
+       }
+       wrap_trail();
+}
+#endif
+int
+f_pid(int pt)
+{      int i;
+       P0 *z;
+       for (i = 0; i < now._nr_pr; i++)
+       {       z = (P0 *)pptr(i);
+               if (z->_t == (unsigned) pt)
+                       return BASE+z->_pid;
+       }
+       return -1;
+}
+#ifdef VERI
+void check_claim(int);
+#endif
+
+#if !defined(HASH64) && !defined(HASH32)
+       #define HASH32
+#endif
+#if defined(HASH32) && defined(SAFETY) && !defined(SFH) && !defined(SPACE)
+       #define SFH
+#endif
+#if defined(SFH) && (defined(BITSTATE) || defined(COLLAPSE) || defined(HC) || defined(HASH64))
+       #undef SFH
+#endif
+#if defined(SFH) && !defined(NOCOMP)
+       #define NOCOMP  /* go for speed */
+#endif
+#if NCORE>1 && !defined(GLOB_HEAP)
+       #define SEP_HEAP /* version 5.1.2 */
+#endif
+
+#ifdef BITSTATE
+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 = K1; y = j3;
+       for (;;)
+       {       if (!(SS[x%udmem]&(1<<y))) break;
+               if (i == hfns) {
+#ifdef DEBUG
+                       printf("Old bitstate\n");
+#endif
+                       return 1;
+               }
+               x = (x + K2 + i);
+               y = (y + j4) & 7;
+               i++;
+       }
+#ifdef RANDSTOR
+       if (rand()%100 > RANDSTOR) return 0;
+#endif
+       for (;;)
+       {       SS[x%udmem] |= (1<<y);
+               if (i == hfns) break;
+               x = (x + K2 + i);
+               y = (y + j4) & 7;
+               i++;
+       }
+#ifdef DEBUG
+       printf("New bitstate\n");
+#endif
+       if (now._a_t&1)
+       {       nShadow++;
+       }
+       return 0;
+}
+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;
+       for (;;)
+       {       if (!(SS[x]&(1<<y))) break;
+               if (i == hfns) {
+#ifdef DEBUG
+                       printf("Old bitstate\n");
+#endif
+                       return 1;
+               }
+               x = (x + j1 + i) & nmask;
+               y = (y + j4) & 7;
+               i++;
+       }
+#ifdef RANDSTOR
+       if (rand()%100 > RANDSTOR) return 0;
+#endif
+       for (;;)
+       {       SS[x] |= (1<<y);
+               if (i == hfns) break;
+               x = (x + j1 + i) & nmask;
+               y = (y + j4) & 7;
+               i++;
+       }
+#ifdef DEBUG
+       printf("New bitstate\n");
+#endif
+       if (now._a_t&1)
+       {       nShadow++;
+       }
+       return 0;
+}
+#endif
+unsigned long TMODE = 0666; /* file permission bits for trail files */
+
+int trcnt=1;
+char snap[64], fnm[512];
+
+int
+make_trail(void)
+{      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)
+       {       sprintf(fnm, "%s%d.%s",
+                       MyFile, Nr_Trails-1, tprefix);
+       } else
+       {
+#ifdef PUTPID
+               sprintf(fnm, "%s%d.%s", MyFile, getpid(), tprefix);
+#else
+               sprintf(fnm, "%s.%s", MyFile, tprefix);
+#endif
+       }
+       if ((fd = open(fnm, w_flags, TMODE)) < 0)
+       {       if ((q = strchr(MyFile, '.')))
+               {       *q = '\0';
+                       if (iterative == 0 && Nr_Trails-1 > 0)
+                               sprintf(fnm, "%s%d.%s",
+                                       MyFile, Nr_Trails-1, tprefix);
+                       else
+                               sprintf(fnm, "%s.%s", MyFile, tprefix);
+                       *q = '.';
+                       fd = open(fnm, w_flags, TMODE);
+       }       }
+       if (fd < 0)
+       {       printf("pan: cannot create %s\n", fnm);
+               perror("cause");
+       } else
+       {
+#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;
+}
+
+#ifndef FREQ
+#define FREQ   (1000000)
+#endif
+#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;
+       int  sz;
+       int nrpr;
+       int nrqs;
+       char *po;
+       char *qo;
+       char *ps, *qs;
+       struct EV_Hold *nxt;
+} EV_Hold;
+
+typedef struct BFS_Trail {
+       Trail   *frame;
+       SV_Hold *onow;
+       EV_Hold *omask;
+#ifdef Q_PROVISO
+       struct H_el *lstate;
+#endif
+       short boq;
+       struct BFS_Trail *nxt;
+} BFS_Trail;
+
+BFS_Trail *bfs_trail, *bfs_bot, *bfs_free;
+
+SV_Hold *svhold, *svfree;
+
+#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)
+#else
+       #define RFLAGS  (O_RDONLY)
+       #define WFLAGS  (O_CREAT|O_WRONLY|O_TRUNC)
+#endif
+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
+
+uchar do_reverse(Trans *, short, uchar);
+void snapshot(void);
+
+SV_Hold *
+getsv(int n)
+{      SV_Hold *h = (SV_Hold *) 0, *oh;
+
+       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)
+       {       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 */
+               }
+               bfs_size_limit++;
+#endif
+               h->sv = (State *) emalloc(sizeof(State) - VECTORSZ + n);
+       }
+
+       memcpy((char *)h->sv, (char *)&now, n);
+       return h;
+}
+
+EV_Hold *
+getsv_mask(int n)
+{      EV_Hold *h;
+       static EV_Hold *kept = (EV_Hold *) 0;
+
+       for (h = kept; h; h = h->nxt)
+               if (n == h->sz
+               &&  (memcmp((char *) Mask, (char *) h->sv, n) == 0)
+               &&  (now._nr_pr == h->nrpr)
+               &&  (now._nr_qs == h->nrqs)
+#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))
+                       break;
+       if (!h)
+       {       h = (EV_Hold *) emalloc(sizeof(EV_Hold));
+               h->sz = n;
+               h->nrpr = now._nr_pr;
+               h->nrqs = now._nr_qs;
+
+               h->sv = (char *) emalloc(n * sizeof(char));
+               memcpy((char *) h->sv, (char *) Mask, n);
+
+               if (now._nr_pr > 0)
+               {       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
+                       h->po = (char *) emalloc(now._nr_pr * sizeof(short));
+                       memcpy((char *) h->po, (char *) proc_offset, now._nr_pr * sizeof(short));
+#endif
+               }
+               if (now._nr_qs > 0)
+               {       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
+                       h->qo = (char *) emalloc(now._nr_qs * sizeof(short));
+                       memcpy((char *) h->qo, (char *) q_offset, now._nr_qs * sizeof(short));
+#endif
+               }
+
+               h->nxt = kept;
+               kept = h;
+       }
+       return h;
+}
+
+void
+freesv(SV_Hold *p)
+{      SV_Hold *h, *oh;
+
+       oh = (SV_Hold *) 0;
+       for (h = svfree; h; oh = h, h = h->nxt)
+               if (h->sz >= p->sz)
+                       break;
+
+       if (!oh)
+       {       p->nxt = svfree;
+               svfree = p;
+       } else
+       {       p->nxt = h;
+               oh->nxt = p;
+       }
+}
+
+BFS_Trail *
+get_bfs_frame(void)
+{      BFS_Trail *t;
+
+       if (bfs_free)
+       {       t = bfs_free;
+               bfs_free = bfs_free->nxt;
+               t->nxt = (BFS_Trail *) 0;
+       } else
+       {       t = (BFS_Trail *) emalloc(sizeof(BFS_Trail));
+       }
+       t->frame = (Trail *) emalloc(sizeof(Trail));
+       return t;
+}
+
+void
+push_bfs(Trail *f, int d)
+{      BFS_Trail *t;
+
+       t = get_bfs_frame();
+       memcpy((char *)t->frame, (char *)f, sizeof(Trail));
+       t->frame->o_tt = d;     /* depth */
+
+       t->boq = boq;
+       t->onow = getsv(vsize);
+       t->omask = getsv_mask(vsize);
+#if defined(FULLSTACK) && defined(Q_PROVISO)
+       t->lstate = Lstate;
+#endif
+       if (!bfs_bot)
+       {       bfs_bot = bfs_trail = t;
+       } else
+       {       bfs_bot->nxt = t;
+               bfs_bot = t;
+       }
+#ifdef CHECK
+       printf("PUSH %u (%d)\n", t->frame, d);
+#endif
+}
+
+Trail *
+pop_bfs(void)
+{      BFS_Trail *t;
+
+       if (!bfs_trail)
+               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
+
+       t->nxt = bfs_free;
+       bfs_free = t;
+
+       vsize = t->onow->sz;
+       boq = t->boq;
+#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);
+       memcpy((uchar *) Mask, (uchar *) t->omask->sv, vsize);
+       if (now._nr_pr > 0)
+#if VECTORSZ>32000
+       {       memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(int));
+#else
+       {       memcpy((char *)proc_offset, (char *)t->omask->po, now._nr_pr * sizeof(short));
+#endif
+               memcpy((char *)proc_skip,   (char *)t->omask->ps, now._nr_pr * sizeof(uchar));
+       }
+       if (now._nr_qs > 0)
+#if VECTORSZ>32000
+       {       memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(int));
+#else
+       {       memcpy((uchar *)q_offset, (uchar *)t->omask->qo, now._nr_qs * sizeof(short));
+#endif
+               memcpy((uchar *)q_skip,   (uchar *)t->omask->qs, now._nr_qs * sizeof(uchar));
+       }
+#ifdef BFS_DISK
+       if (t->onow->sv != (State *) 0)
+#endif
+               freesv(t->onow);        /* omask not freed */
+#ifdef CHECK
+       printf("POP %u (%d)\n", t->frame, t->frame->o_tt);
+#endif
+       return t->frame;
+}
+
+void
+store_state(Trail *ntrpt, int shortcut, short oboq)
+{
+#ifdef VERI
+       Trans *t2 = (Trans *) 0;
+       uchar ot; int tt, E_state;
+       uchar o_opm = trpt->o_pm, *othis = this;
+
+       if (shortcut)
+       {
+#ifdef VERBOSE
+               printf("claim: shortcut\n");
+#endif
+               goto store_it;  /* no claim move */
+       }
+
+       this  = (((uchar *)&now)+proc_offset[0]); /* 0 = never claim */
+       trpt->o_pm = 0;
+
+       tt    = (int)   ((P0 *)this)->_p;
+       ot    = (uchar) ((P0 *)this)->_t;
+
+#ifdef HAS_UNLESS
+       E_state = 0;
+#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
+               if (do_transit(t2, 0))
+               {
+#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
+                       E_state = t2->e_trans;
+#endif
+                       if (t2->st > 0)
+                       {       ((P0 *)this)->_p = t2->st;
+                               reached[ot][t2->st] = 1;
+#ifndef NOCLAIM
+                               check_claim(t2->st);
+#endif
+                       }
+                       if (now._nr_pr == 0)    /* claim terminated */
+                               uerror("end state in claim reached");
+
+#ifdef PEG
+                       peg[t2->forw]++;
+#endif
+                       trpt->o_pm |= 1;
+                       if (t2->atom&2)
+                       Uerror("atomic in claim not supported in BFS mode");
+store_it:
+
+#endif
+
+#ifdef BITSTATE
+                       if (!bstore((char *)&now, vsize))
+#else
+#ifdef MA
+                       if (!gstore((char *)&now, vsize, 0))
+#else
+                       if (!hstore((char *)&now, vsize))
+#endif
+#endif
+                       {       static long sdone = (long) 0; long ndone;
+                               nstates++;
+#ifndef NOREDUCE
+                               trpt->tau |= 64;
+#endif
+                               ndone = (unsigned long) (nstates/((double) 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)
+                               {       Trail *x;
+                                       x = (Trail *) trpt->ostate; /* pre-rv state */
+                                       if (x) x->o_pm |= 4; /* mark success */
+                               }
+#endif
+                               push_bfs(ntrpt, trpt->o_tt+1);
+                       } else
+                       {       truncs++;
+#if !defined(NOREDUCE) && defined(FULLSTACK) && defined(Q_PROVISO)
+#if !defined(BITSTATE)
+                               if (Lstate && Lstate->tagged) trpt->tau |= 64;
+#else
+                               if (trpt->tau&32)
+                               {  BFS_Trail *tprov;
+                                  for (tprov = bfs_trail; tprov; tprov = tprov->nxt)
+                                       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
+                       }
+#ifdef VERI
+                       ((P0 *)this)->_p = tt;  /* reset claim */
+                       if (t2)
+                               do_reverse(t2, 0, 0);
+                       else
+                               break;
+       }       }
+       this = othis;
+       trpt->o_pm = o_opm;
+#endif
+}
+
+Trail *ntrpt;
+
+void
+bfs(void)
+{      Trans *t; Trail *otrpt, *x;
+       uchar _n, _m, ot, nps = 0;
+       int tt, E_state;
+       short II, From = (short) (now._nr_pr-1), To = BASE;
+       short oboq = boq;
+
+       ntrpt = (Trail *) emalloc(sizeof(Trail));
+       trpt->ostate = (struct H_el *) 0;
+       trpt->tau = 0;
+
+       trpt->o_tt = -1;
+       store_state(ntrpt, 0, oboq);    /* initial state */
+
+       while ((otrpt = pop_bfs()))     /* also restores now */
+       {       memcpy((char *) trpt, (char *) otrpt, sizeof(Trail));
+#if defined(C_States) && (HAS_TRACK==1)
+               c_revert((uchar *) &(now.c_state[0]));
+#endif
+               if (trpt->o_pm & 4)
+               {
+#ifdef VERBOSE
+                       printf("Revisit of atomic not needed (%d)\n",
+                               trpt->o_pm);
+#endif
+                       continue;
+               }
+#ifndef NOREDUCE
+               nps = 0;
+#endif
+               if (trpt->o_pm == 8)
+               {       revrv++;
+                       if (trpt->tau&8)
+                       {
+#ifdef VERBOSE
+                               printf("Break atomic (pm:%d,tau:%d)\n",
+                                       trpt->o_pm, trpt->tau);
+#endif
+                               trpt->tau &= ~8;
+                       }
+#ifndef NOREDUCE
+                       else if (trpt->tau&32)
+                       {
+#ifdef VERBOSE
+                               printf("Void preselection (pm:%d,tau:%d)\n",
+                                       trpt->o_pm, trpt->tau);
+#endif
+                               trpt->tau &= ~32;
+                               nps = 1; /* no preselection in repeat */
+                       }
+#endif
+               }
+               trpt->o_pm &= ~(4|8);
+               if (trpt->o_tt > mreached)
+               {       mreached = trpt->o_tt;
+                       if (mreached%10 == 0)
+                       {       snapshot();
+               }       }
+               depth = trpt->o_tt;
+               if (depth >= maxdepth)
+               {
+#if SYNC
+                       Trail *x;
+                       if (boq != -1)
+                       {       x = (Trail *) trpt->ostate;
+                               if (x) x->o_pm |= 4; /* not failing */
+                       }
+#endif
+                       truncs++;
+                       if (!warned)
+                       {       warned = 1;
+                               printf("error: max search depth too small\n");
+                       }
+                       if (bounded)
+                               uerror("depth limit reached");
+                       continue;
+               }
+#ifndef NOREDUCE
+               if (boq == -1 && !(trpt->tau&8) && 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)
+                               {       Ccheck++;
+                                       if (!q_cond(II, t))
+                                               continue;
+                                       Cholds++;
+                               }
+                               From = To = II;
+                               trpt->tau |= 32; /* preselect marker */
+#ifdef DEBUG
+                               printf("%3d: proc %d PreSelected (tau=%d)\n", 
+                                       depth, II, trpt->tau);
+#endif
+                               goto MainLoop;
+               }       }
+               trpt->tau &= ~32;
+#endif
+Repeat:
+               if (trpt->tau&8)                /* atomic */
+               {       From = To = (short ) trpt->pr;
+                       nlinks++;
+               } else
+               {       From = now._nr_pr-1;
+                       To = BASE;
+               }
+MainLoop:
+               _n = _m = 0;
+               for (II = From; II >= To; II -= 1)
+               {
+                       this = (((uchar *)&now)+proc_offset[II]);
+                       tt = (int) ((P0 *)this)->_p;
+                       ot = (uchar) ((P0 *)this)->_t;
+#if SYNC
+                       /* no rendezvous with same proc */
+                       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_event = now._event;
+#endif
+#ifdef HAS_PROVIDED
+                       if (!provided(II, ot, tt, t)) continue;
+#endif
+#ifdef HAS_UNLESS
+                       E_state = 0;
+#endif
+                       for (t = trans[ot][tt]; t; t = t->nxt)
+                       {
+#ifdef HAS_UNLESS
+                               if (E_state > 0
+                               &&  E_state != t->e_trans)
+                                       break;
+#endif
+                               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 CHECK
+                               printf("%3d: 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);
+#endif
+#ifdef HAS_UNLESS
+                               E_state = t->e_trans;
+#if SYNC>0
+                               if (t->e_trans > 0 && (boq != -1 /* || oboq != -1 */))
+                               { fprintf(efd, "error:  the use of rendezvous stmnt in the escape clause\n");
+                                 fprintf(efd, "        of an unless stmnt is not compatible with -DBFS\n");
+                                 pan_exit(1);
+                               }
+#endif
+#endif
+                               if (t->st > 0) ((P0 *)this)->_p = t->st;
+
+       /* ptr to pred: */      ntrpt->ostate = (struct 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
+                               now._event = trpt->o_event;
+#endif
+
+                               /* undo move and continue */
+                               trpt++; /* this is where ovals and ipt are set */
+                               do_reverse(t, II, _m);  /* restore now. */
+                               trpt--;
+#ifdef CHECK
+       #if NCORE>1
+                               enter_critical(GLOBAL_LOCK);    /* in verbose mode only */
+                               printf("cpu%d: ", core_id);
+       #endif
+                               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);
+       #if NCORE>1
+                               leave_critical(GLOBAL_LOCK);
+       #endif
+#endif
+                               reached[ot][t->st] = 1;
+                               reached[ot][tt] = 1;
+
+                               ((P0 *)this)->_p = tt;
+                               _n |= _m;
+               }       }
+#ifndef NOREDUCE
+               /* preselected - no succ definitely outside stack */
+               if ((trpt->tau&32) && !(trpt->tau&64))
+               {       From = now._nr_pr-1; To = BASE;
+#ifdef DEBUG
+                       cpu_printf("%3d: 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 MainLoop;
+               }
+               trpt->tau &= ~(32|64);
+#endif
+               if (_n != 0)
+                       continue;
+#ifdef DEBUG
+               printf("%3d: no move [II=%d, tau=%d, boq=%d, _nr_pr=%d]\n",
+                       depth, II, trpt->tau, boq, now._nr_pr);
+#endif
+               if (boq != -1)
+               {       failedrv++;
+                       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
+                               printf("\treset state of %d from %d to %d\n",
+                                       otrpt->pr, ((P0 *)this)->_p, otrpt->st);
+#endif
+                               ((P0 *)this)->_p = otrpt->st;
+                               unsend(boq);    /* retract rv offer */
+                               boq = -1;
+                               push_bfs(x, x->o_tt);
+#ifdef VERBOSE
+                               printf("failed rv, repush with %d\n", x->o_pm);
+#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",
+                                       depth, II+1);
+#endif
+                               goto Repeat;
+                       }
+
+                       if (!(trpt->tau&1)) /* didn't try timeout yet */
+                       {       trpt->tau |=  1;
+#ifdef DEBUG
+                               printf("%d: timeout\n", depth);
+#endif
+                               goto MainLoop;
+                       }
+#ifndef VERI
+                       if (!noends && !a_cycles && !endstate())
+                               uerror("invalid end state");
+#endif
+       }       }
+}
+
+void
+putter(Trail *trpt, int fd)
+{      long j;
+
+       if (!trpt) return;
+
+       if (trpt != (Trail *) trpt->ostate)
+               putter((Trail *) trpt->ostate, fd);
+
+       if (trpt->o_t)
+       {       sprintf(snap, "%d:%d:%d\n",
+                       trcnt++, trpt->pr, trpt->o_t->t_id);
+               j = strlen(snap);
+               if (write(fd, snap, j) != j)
+               {       printf("pan: error writing %s\n", fnm);
+                       pan_exit(1);
+       }       }
+}
+
+void
+nuerror(char *str)
+{      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
+       trcnt = 1;
+       putter(trpt, fd);
+       if (ntrpt->o_t)
+       {       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);
+       }       }
+       close(fd);
+       if (errors >= upto && upto != 0)
+       {       wrapup();
+       }
+}
+#endif
+#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 usefule -- 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)
+#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];
+       volatile char   m_Mask    [(VMAX + 7)/8];
+       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];
+#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
+#endif
+
+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;
+volatile int *prfull;
+volatile int *prcnt;
+volatile int *prmax;
+
+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 *);
+#if 0
+void enter_critical(int);
+void leave_critical(int);
+#endif
+
+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, (int) (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", 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, *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 */
+               {
+#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",
+                                       worker_pids[i], (dwExitCode == STILL_ACTIVE));
+#else
+                               sprintf(b, "kill -%d %d", SIGKILL, worker_pids[i]);
+                               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)
+               {       sprintf(b, "kill -%d %d", SIGINT, worker_pids[0]);
+                       system(b);      /* warn the root process */
+                       printf("cpu%d: %s\n", core_id, b);
+                       issued_kill++;
+       }       }
+}
+
+#define iam_alive()    is_alive[core_id]++
+
+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>%d)\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");
+       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");
+       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;
+
+struct 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 %d)\n",
+                       core_id, depth);
+       }
+}
+#endif
+
+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;
+               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);
+               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
+       if (memcnt + (double) n > memlim)
+       {       printf("cpu0: S %8g + %d Kb exceeds memory limit of %8g Mb\n",
+                       memcnt/1024., 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",
+                               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++;
+       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");
+       }
+ #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)
+       {       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 *);
+
+       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 = (struct H_el **) emalloc(n);
+       #endif
+#else
+       #ifndef MEMLIM
+               #warning MEMLIM not set
+               #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 = (struct 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 0.000000\n", SEG_SIZE);
+                       }
+                       if (SEG_SIZE >= 1024.)
+                       {       goto shm_more;
+                       }
+                       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 *);
+
+                       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
+}
+
+       /* 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;
+               }
+       #else
+               #error missing definition of test and set operation for this platform
+       #endif
+
+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 %d 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 BFS is not supported with multi-core
+#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)
+               {       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 */
+       }
+       if (verbose)
+       {       cpu_printf("starting core_id %d -- pid %d\n", core_id, getpid());
+       }
+#if defined(SEP_HEAP) && !defined(SEP_STATE)
+       {       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
+
+struct 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 (struct 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
+               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 (struct H_el *) rval;
+#else
+       return (struct 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)
+                       {       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;
+                       *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);
+       }       }
+       return rval;
+}
+#endif
+
+int
+unpack_state(SM_frame *f, int from_q)
+{      int i, j;
+       static struct 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);
+               for (i = j = 0; i < VMAX; i++, j = (j+1)%8)
+               {       Mask[i] = (f->m_Mask[i/8] & (1<<j)) ? 1 : 0;
+               }
+               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];
+       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(" line %3d \"%s\" ",
+                                               src_all[j].src[z->_p], PanSource);
+                                       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)
+{      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)
+#define TargetQ_NotFull(n)     (m_workq[n][prfree[n]].m_vsize == 0)
+
+int
+AllQueuesEmpty(void)
+{      int q;
+#ifndef NGQ
+       if (*grcnt != 0)
+       {       return 0;
+       }
+#endif
+       for (q = 0; q < NCORE; q++)
+       {       if (prcnt[q] != 0)
+               {       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", 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);
+       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);
+       }       }
+
+       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);
+       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);
+       }       }
+
+       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)
+       #else
+               if (TargetQ_NotFull(q)
+               && (dfs_phase2 == 0 || prcnt[core_id] > 0))
+       #endif
+               {       mem_put(q);
+                       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)
+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)
+               {       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 *);
+ #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 = (struct H_el **) emalloc(n);
+       #endif
+#else
+       #ifndef MEMLIM
+               #warning MEMLIM not set
+               #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 = (struct 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)
+{      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 BFS is not supported in multi-core mode
+#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
+
+#ifdef BITSTATE
+void
+init_SS(unsigned long n)
+{
+       SS = (uchar *) prep_shmid_S((size_t) n);
+       init_HT(0L);
+}
+#endif
+
+#endif
+clock_t start_time;
+#if NCORE>1
+clock_t crash_stamp;
+#endif
+#if !defined(WIN32) && !defined(WIN64)
+struct tms start_tm;
+#endif
+
+void
+start_timer(void)
+{
+#if defined(WIN32) || defined(WIN64)
+       start_time = clock();
+#else
+       start_time = times(&start_tm);
+#endif
+}
+
+void
+stop_timer(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 (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
+       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));
+       }       }
+#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
+
+void
+do_the_search(void)
+{      int i;
+       depth = mreached = 0;
+       trpt = &trail[0];
+#ifdef VERI
+       trpt->tau |= 4; /* the claim moves first */
+#endif
+       for (i = 0; i < (int) now._nr_pr; i++)
+       {       P0 *ptr = (P0 *) pptr(i);
+#ifndef NP
+               if (!(trpt->o_pm&2)
+               &&  accpstate[ptr->_t][ptr->_p])
+               {       trpt->o_pm |= 2;
+               }
+#else
+               if (!(trpt->o_pm&4)
+               &&  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
+#ifndef NOCOMP
+       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[] */
+       }
+#endif
+#endif
+#ifndef NOFAIR
+       if (fairness
+       &&  (a_cycles && (trpt->o_pm&2)))
+       {       now._a_t = 2;   /* set the A-bit */
+               now._cnt[0] = now._nr_pr + 1;
+#ifdef VERBOSE
+       printf("%3d: 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]));
+#endif
+#ifdef HAS_CODE
+       if (readtrail) getrail(); /* no return */
+#endif
+       start_timer();
+#ifdef BFS
+       bfs();
+#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
+       #if RANDOMIZE>0
+       srand(RANDOMIZE);
+       #else
+       srand(123);
+       #endif
+#endif
+#if NCORE>1
+       mem_get();
+#else
+       new_state();    /* start 1st DFS */
+#endif
+#endif
+}
+#ifdef INLINE_REV
+uchar
+do_reverse(Trans *t, short II, uchar M)
+{      uchar _m = M;
+       int  tt = (int) ((P0 *)this)->_p;
+#include REVERSE_MOVES
+R999:  return _m;
+}
+#endif
+#ifndef INLINE
+#ifdef EVENT_TRACE
+static char _tp = 'n'; static int _qid = 0;
+#endif
+uchar
+do_transit(Trans *t, short II)
+{      uchar _m = 0;
+       int  tt = (int) ((P0 *)this)->_p;
+#ifdef M_LOSS
+       uchar delta_m = 0;
+#endif
+#ifdef EVENT_TRACE
+       short oboq = boq;
+       uchar ot = (uchar)  ((P0 *)this)->_t;
+       if (ot == EVENT_TRACE) boq = -1;
+#define continue       { boq = oboq; return 0; }
+#else
+#define continue       return 0
+#ifdef SEPARATE
+       uchar ot = (uchar)  ((P0 *)this)->_t;
+#endif
+#endif
+#include FORWARD_MOVES
+P999:
+#ifdef EVENT_TRACE
+       if (ot == EVENT_TRACE) boq = oboq;
+#endif
+       return _m;
+#undef continue
+}
+#ifdef EVENT_TRACE
+void
+require(char tp, int qid)
+{      Trans *t;
+       _tp = tp; _qid = qid;
+
+       if (now._event != endevent)
+       for (t = trans[EVENT_TRACE][now._event]; t; t = t->nxt)
+       {       if (do_transit(t, EVENT_TRACE))
+               {       now._event = t->st;
+                       reached[EVENT_TRACE][t->st] = 1;
+#ifdef VERBOSE
+       printf("        event_trace move to -> %d\n", t->st);
+#endif
+#ifndef BFS
+#ifndef NP
+                       if (accpstate[EVENT_TRACE][now._event])
+                               (trpt+1)->o_pm |= 2;
+#else
+                       if (progstate[EVENT_TRACE][now._event])
+                               (trpt+1)->o_pm |= 4;
+#endif
+#endif
+#ifdef NEGATED_TRACE
+                       if (now._event == endevent)
+                       {
+#ifndef BFS
+                               depth++; trpt++;
+#endif
+                               uerror("event_trace error (all events matched)");
+#ifndef BFS
+                               trpt--; depth--;
+#endif
+                               break;
+                       }
+#endif
+                       for (t = t->nxt; t; t = t->nxt)
+                       {       if (do_transit(t, EVENT_TRACE))
+                                Uerror("non-determinism in event-trace");
+                       }
+                       return;
+               }
+#ifdef VERBOSE
+                else
+       printf("        event_trace miss '%c' -- %d, %d, %d\n",
+                       tp, qid, now._event, t->forw);
+#endif
+       }
+#ifdef NEGATED_TRACE
+       now._event = endevent; /* only 1st try will count -- fixed 4.2.6 */
+#else
+#ifndef BFS
+       depth++; trpt++;
+#endif
+       uerror("event_trace error (no matching event)");
+#ifndef BFS
+       trpt--; depth--;
+#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
+       if (pid == iam)
+               Uerror("used: enabled(pid=thisproc)");
+       if (pid < 0 || pid >= (int) now._nr_pr)
+               return 0;
+       this = pptr(pid);
+       TstOnly = 1;
+       tt = (int) ((P0 *)this)->_p;
+       ot = (uchar) ((P0 *)this)->_t;
+       for (t = trans[ot][tt]; t; t = t->nxt)
+               if (do_transit(t, (short) pid))
+               {       res = 1;
+                       break;
+               }
+       TstOnly = 0;
+       this = othis;
+       return res;
+}
+#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= %6.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)
+{
+#if NCORE>1
+       enter_critical(GLOBAL_LOCK);    /* 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);
+#endif
+       printf("Memory= %9.3f\t", memcnt/1048576.);
+       snap_time();
+       fflush(stdout);
+#if NCORE>1
+       leave_critical(GLOBAL_LOCK);
+#endif
+}
+#ifdef SC
+void
+stack2disk(void)
+{
+       if (!stackwrite
+       &&  (stackwrite = creat(stackfile, TMODE)) < 0)
+               Uerror("cannot create stackfile");
+
+       if (write(stackwrite, trail, DDD*sizeof(Trail))
+       !=  DDD*sizeof(Trail))
+               Uerror("stackfile write error -- disk is full?");
+
+       memmove(trail, &trail[DDD], (HHH-DDD+2)*sizeof(Trail));
+       memset(&trail[HHH-DDD+2], 0, (omaxdepth - HHH + DDD - 2)*sizeof(Trail));
+       CNT1++;
+}
+void
+disk2stack(void)
+{      long have;
+
+       CNT2++;
+       memmove(&trail[DDD], trail, (HHH-DDD+2)*sizeof(Trail));
+
+       if (!stackwrite
+       ||  lseek(stackwrite, -DDD* (off_t) sizeof(Trail), SEEK_CUR) == -1)
+               Uerror("disk2stack lseek error");
+
+       if (!stackread
+       &&  (stackread = open(stackfile, 0)) < 0)
+               Uerror("cannot open stackfile");
+
+       if (lseek(stackread, (CNT1-CNT2)*DDD* (off_t) sizeof(Trail), SEEK_SET) == -1)
+               Uerror("disk2stack lseek error");
+
+       have = read(stackread, trail, DDD*sizeof(Trail));
+       if (have !=  DDD*sizeof(Trail))
+               Uerror("stackfile read error");
+}
+#endif
+uchar *
+Pptr(int x)
+{      if (x < 0 || x >= MAXPROC || !proc_offset[x])
+               return noptr;
+       else
+               return (uchar *) pptr(x);
+}
+int qs_empty(void);
+/*
+ * 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
+ * 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
+ */
+#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     %10d    (%.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
+
+void
+new_state(void)
+{      Trans *t;
+       uchar _n, _m, ot;
+#ifdef RANDOMIZE
+       short ooi, eoi;
+#endif
+#ifdef M_LOSS
+       uchar delta_m = 0;
+#endif
+       short II, JJ = 0, kk;
+       int tt;
+#ifdef REVERSE
+       short From = BASE, To = now._nr_pr-1;
+#else
+       short From = now._nr_pr-1, To = BASE;
+#endif
+Down:
+#ifdef CHECK
+       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 SCHED
+       if (depth > 0)
+       {       trpt->sched_limit = (trpt-1)->sched_limit;
+       } else
+       {       trpt->sched_limit = 0;
+       }
+#endif
+#ifdef SC
+       if (depth > hiwater)
+       {       stack2disk();
+               maxdepth += DDD;
+               hiwater += DDD;
+               trpt -= DDD;
+               if(verbose)
+               printf("zap %d: %d (maxdepth now %d)\n",
+                       CNT1, hiwater, maxdepth);
+       }
+#endif
+       trpt->tau &= ~(16|32|64); /* make sure these are off */
+#if defined(FULLSTACK) && defined(MA)
+       trpt->proviso = 0;
+#endif
+#ifdef NSUCC
+       trpt->n_succ = 0;
+#endif
+#if NCORE>1
+       if (mem_hand_off())
+       {
+#if SYNC
+               (trpt+1)->o_n = 1;      /* not a deadlock: as below  */
+#endif
+#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");
+               }
+               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)) || NCORE>1
+       /* if atomic or rv move, carry forward previous state */
+       trpt->ostate = (trpt-1)->ostate;
+#endif
+#ifdef VERI
+       if ((trpt->tau&4) || ((trpt-1)->tau&128))
+#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 ((now._a_t&1) && depth > A_depth)
+               {       if (!memcmp((char *)&A_Root, 
+                               (char *)&now, vsize))
+                       {
+                               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
+                       printf("not seed\n");
+#endif
+               }
+#endif
+               if (!(trpt->tau&8)) /* if no atomic move */
+               {
+#ifdef BITSTATE
+#ifdef CNTRSTACK
+                       II = bstore((char *)&now, vsize);
+                       trpt->j6 = j1; trpt->j7 = j2;
+                       JJ = LL[j1] && LL[j2];
+#else
+#ifdef FULLSTACK
+                       JJ = onstack_now();
+#else
+#ifndef NOREDUCE
+                       JJ = II; /* worstcase guess for p.o. */
+#endif
+#endif
+                       II = bstore((char *)&now, vsize);
+#endif
+#else
+#ifdef MA
+                       II = gstore((char *)&now, vsize, 0);
+#ifndef FULLSTACK
+                       JJ = II;
+#else
+                       JJ = (II == 2)?1:0;
+#endif
+#else
+                       II = hstore((char *)&now, vsize);
+#ifdef FULLSTACK
+                       JJ = (II == 2)?1:0;
+#endif
+#endif
+#endif
+                       kk = (II == 1 || II == 2);
+#ifndef SAFETY
+#if NCORE==1 || defined (SEP_STATE)
+                       if (II == 2 && ((trpt->o_pm&2) || ((trpt-1)->o_pm&2)))
+               #ifndef NOFAIR
+#if 0
+                       if (!fairness || ((now._a_t&1) && now._cnt[1] == 1)) /* 5.1.4 */
+#else
+                       if (a_cycles && !fairness) /* 5.1.6 -- example by Hirofumi Watanabe */
+#endif
+               #endif
+                       {
+                               II = 3; /* Schwoon & Esparza 2005, Gastin&Moro 2004 */
+#ifdef VERBOSE
+                               printf("state match on dfs stack\n");
+#endif
+                               goto same_case;
+                       }
+#endif
+#if defined(FULLSTACK) && defined(BITSTATE)
+                       if (!JJ && (now._a_t&1) && depth > A_depth)
+                       {       int oj1 = j1;
+                               uchar o_a_t = now._a_t;
+                               now._a_t &= ~(1|16|32);
+                               if (onstack_now())
+                               {       II = 3;
+#ifdef VERBOSE
+                                       printf("state match on 1st dfs stack\n");
+#endif
+                               }
+                               now._a_t = o_a_t;
+                               j1 = oj1;
+                       }
+#endif
+                       if (II == 3 && a_cycles && (now._a_t&1))
+                       {
+#ifndef NOFAIR
+                          if (fairness && now._cnt[1] > 1)     /* was != 0 */
+                          {
+#ifdef VERBOSE
+                               printf("        fairness count non-zero\n");
+#endif
+                               II = 0;
+                          } else
+#endif
+                          {
+#ifndef BITSTATE
+                               nShadow--;
+#endif
+same_case:                     if (Lstate) depthfound = Lstate->D;
+#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;
+                          }
+                       }
+#endif
+#ifndef NOREDUCE
+#ifndef SAFETY
+#if NCORE>1 && !defined(SEP_STATE) && defined(V_PROVISO)
+                       if (II != 0 && (!Lstate || Lstate->cpu_id < core_id))
+                       {       (trpt-1)->tau |= 16;
+                       }
+#endif
+                       if ((II && JJ) || (II == 3))
+                       {       /* marker for liveness proviso */
+#ifndef LOOPSTATE
+                               (trpt-1)->tau |= 16;
+#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
+                       if (II)
+                       {       truncs++;
+#if NCORE>1 && defined(FULL_TRAIL)
+                               if (upto > 0)
+                               {       Pop_Stack_Tree();
+                                       if (depth == 0)
+                                       {       return;
+                               }       }
+#endif
+                               goto Up;
+                       }
+                       if (!kk)
+                       {       static long sdone = (long) 0; long ndone;
+                               nstates++;
+#if defined(ZAPH) && defined(BITSTATE)
+                               zstates += (double) hfns;
+#endif
+                               ndone = (unsigned long) (nstates/((double) 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)
+                               if (write(svfd, (uchar *) &now, vprefix) != vprefix)
+                               {       fprintf(efd, "writing %s.svd failed\n", PanSource);
+                                       wrapup();
+                               }
+#endif
+#if defined(MA) && defined(W_XPT)
+                               if ((unsigned long) nstates%W_XPT == 0)
+                               {       void w_xpoint(void);
+                                       w_xpoint();
+                               }
+#endif
+                       }
+#if defined(FULLSTACK) || defined(CNTRSTACK)
+                       onstack_put();
+#ifdef DEBUG2
+#if defined(FULLSTACK) && !defined(MA)
+                       printf("%d: putting %u (%d)\n", depth,
+                               trpt->ostate, 
+                               (trpt->ostate)?trpt->ostate->tagged:0);
+#else
+                       printf("%d: putting\n", depth);
+#endif
+#endif
+#else
+       #if NCORE>1
+                       trpt->ostate = Lstate;
+       #endif
+#endif
+       }       }
+       if (depth > mreached)
+               mreached = depth;
+#ifdef VERI
+       if (trpt->tau&4)
+#endif
+       trpt->tau &= ~(1|2);    /* timeout and -request off */
+       _n = 0;
+#if SYNC
+       (trpt+1)->o_n = 0;
+#endif
+#ifdef VERI
+       if (now._nr_pr == 0)    /* claim terminated */
+               uerror("end state in claim reached");
+       check_claim(((P0 *)pptr(0))->_p);
+Stutter:
+       if (trpt->tau&4)        /* must make a claimmove */
+       {
+#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
+       printf("%3d: fairness Rule 3.: _a_t = %d\n",
+               depth, now._a_t);
+#endif
+               }
+#endif
+               II = 0;         /* never */
+               goto Veri0;
+       }
+#endif
+#ifndef NOREDUCE
+       /* Look for a process with only safe transitions */
+       /* (special rules apply in the 2nd dfs) */
+       if (boq == -1 && From != To
+
+#ifdef SAFETY
+ #if NCORE>1
+       && (depth < z_handoff)
+ #endif
+       )
+#else
+ #if NCORE>1
+       && ((a_cycles) || (!a_cycles && depth < z_handoff))
+ #endif
+       &&  (!(now._a_t&1)
+           ||  (a_cycles &&
+ #ifndef BITSTATE
+#ifdef MA
+#ifdef VERI
+                !((trpt-1)->proviso))
+#else
+               !(trpt->proviso))
+#endif
+#else
+#ifdef VERI
+                (trpt-1)->ostate &&
+               !(((char *)&((trpt-1)->ostate->state))[0] & 128))
+#else
+               !(((char *)&(trpt->ostate->state))[0] & 128))
+#endif
+#endif
+ #else
+#ifdef VERI
+               (trpt-1)->ostate &&
+               (trpt-1)->ostate->proviso == 0)
+#else
+               trpt->ostate->proviso == 0)
+#endif
+ #endif
+          ))
+#endif
+
+#ifdef REVERSE
+       for (II = From; II <= To; II++)
+#else
+       for (II = From; II >= To; II--)
+#endif
+       {
+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; /* the process preselected */
+#ifdef NIBIS
+                       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;
+#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 */
+#ifndef NOFAIR
+       if (fairness && boq == -1
+#ifdef VERI
+       && (!(trpt->tau&4) && !((trpt-1)->tau&128))
+#endif
+       && !(trpt->tau&8))
+       {       /* A_bit = 1; Cnt = N in acc states with A_bit 0 */
+               if (!(now._a_t&2))
+               {
+                       if (a_cycles && (trpt->o_pm&2))
+                       {       /* Accepting state */
+                               now._a_t |= 2;
+                               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",
+                       depth, now._cnt[now._a_t&1], now._a_t);
+#endif
+                       }
+               } else
+               {       /* A_bit = 0 when Cnt 0 */
+                       if (now._cnt[now._a_t&1] == 1)
+                       {       now._a_t &= ~2;
+                               now._cnt[now._a_t&1] = 0;
+                               trpt->o_pm |= 16;
+#ifdef DEBUG
+       printf("%3d: fairness Rule 3: _a_t = %d\n",
+               depth, now._a_t);
+#endif
+       }       }       }
+#endif
+
+#ifdef REVERSE
+       for (II = From; II <= To; II++)
+#else
+       for (II = From; II >= To; II--)
+#endif
+       {
+#if SYNC
+               /* no rendezvous with same proc */
+               if (boq != -1 && trpt->pr == II) continue;
+#endif
+#ifdef SCHED
+               /* limit max nr of interleavings */
+               if (From != To
+               &&  depth > 0
+       #ifdef VERI
+               &&  II != 0
+       #endif
+               &&  (trpt-1)->pr != II
+               &&   trpt->sched_limit >= sched_max)
+               {       continue;
+               }
+#endif
+#ifdef VERI
+Veri0:
+#endif
+               this = pptr(II);
+               tt = (int) ((P0 *)this)->_p;
+               ot = (uchar) ((P0 *)this)->_t;
+#ifdef NIBIS
+               /* don't repeat a previous preselected expansion */
+               /* could hit this if reduction proviso was false */
+               t = trans[ot][tt];
+               if (!(trpt->tau&4)
+               && !(trpt->tau&1)
+               && !(trpt->tau&32)
+               && (t->atom & 8)
+               && boq == -1
+               && From != To)
+               {       if (t->qu[0] == 0
+                       ||  q_cond(II, t))
+                       {       _m = t->om;
+                               if (_m>_n||(_n>3&&_m!=0)) _n=_m;
+                               continue; /* did it before */
+               }       }
+#endif
+               trpt->o_pm &=  ~1; /* no move in this pid yet */
+#ifdef EVENT_TRACE
+               (trpt+1)->o_event = now._event;
+#endif
+               /* Fairness: Cnt++ when Cnt == II */
+#ifndef NOFAIR
+               trpt->o_pm &= ~64; /* didn't apply rule 2 */
+               if (fairness
+               && boq == -1
+               && !(trpt->o_pm&32)
+               && (now._a_t&2)
+               &&  now._cnt[now._a_t&1] == II+2)
+               {       now._cnt[now._a_t&1] -= 1;
+#ifdef VERI
+                       /* claim need not participate */
+                       if (II == 1)
+                               now._cnt[now._a_t&1] = 1;
+#endif
+#ifdef DEBUG
+               printf("%3d: proc %d fairness ", depth, II);
+               printf("Rule 2: --cnt to %d (%d)\n",
+                       now._cnt[now._a_t&1], now._a_t);
+#endif
+                       trpt->o_pm |= (32|64);
+               }
+#endif
+#ifdef HAS_PROVIDED
+               if (!provided(II, ot, tt, t)) continue;
+#endif
+               /* check all trans of proc II - escapes first */
+#ifdef HAS_UNLESS
+               trpt->e_state = 0;
+#endif
+               (trpt+1)->pr = (uchar) II;
+               (trpt+1)->st = tt;
+#ifdef RANDOMIZE
+               for (ooi = eoi = 0, t = trans[ot][tt]; t; t = t->nxt, ooi++)
+               {       if (strcmp(t->tp, "else") == 0)
+                       {       eoi++;
+                               break;
+               }       }
+               if (eoi > 0)
+               {       t = trans[ot][tt];
+       #ifdef VERBOSE
+                       printf("randomizer: suppressed, saw else\n");
+       #endif
+               } else
+               {       eoi = rand()%ooi;
+       #ifdef VERBOSE
+                       printf("randomizer: skip %d in %d\n", eoi, ooi);
+       #endif
+                       for (t = trans[ot][tt]; t; t = t->nxt)
+                               if (eoi-- <= 0) break;
+               }
+domore:
+               for ( ; t && ooi > 0; t = t->nxt, ooi--)
+#else
+               for (t = trans[ot][tt]; t; t = t->nxt)
+#endif
+               {
+#ifdef HAS_UNLESS
+                       /* exploring all transitions from
+                        * a single escape state suffices
+                        */
+                       if (trpt->e_state > 0
+                       &&  trpt->e_state != t->e_trans)
+                       {
+#ifdef DEBUG
+               printf("skip 2nd escape %d (did %d before)\n",
+                       t->e_trans, trpt->e_state);
+#endif
+                               break;
+                       }
+#endif
+                       (trpt+1)->o_t = t;
+#ifdef INLINE
+#include FORWARD_MOVES
+P999:                  /* jumps here when move succeeds */
+#else
+                       if (!(_m = do_transit(t, II))) continue;
+#endif
+#ifdef SCHED
+                       if (depth > 0
+       #ifdef VERI
+                       && II != 0
+       #endif
+                       && (trpt-1)->pr != II)
+                       {       trpt->sched_limit = 1 + (trpt-1)->sched_limit;
+                       }
+#endif
+                       if (boq == -1)
+#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->o_pm |= 1; /* we moved */
+                       }
+#else
+                               trpt->o_pm |= 1; /* we moved */
+#endif
+#ifdef LOOPSTATE
+                       if (loopstate[ot][tt])
+                       {
+#ifdef VERBOSE
+                               printf("exiting from loopstate:\n");
+#endif
+                               trpt->tau |= 16;
+                               cnt_loops++;
+                       }
+#endif
+#ifdef PEG
+                       peg[t->forw]++;
+#endif
+#if defined(VERBOSE) || defined(CHECK)
+#if defined(SVDUMP)
+       cpu_printf("%3d: proc %d exec %d \n", depth, II, t->t_id);
+#else
+       cpu_printf("%3d: 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":"",
+                               (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
+#endif
+#ifdef RANDOMIZE
+                       cpu_printf("\t(randomizer %d)\n", ooi);
+#endif
+#endif
+#ifdef HAS_LAST
+#ifdef VERI
+                       if (II != 0)
+#endif
+                               now._last = II - BASE;
+#endif
+#ifdef HAS_UNLESS
+                       trpt->e_state = t->e_trans;
+#endif
+                       depth++; trpt++;
+                       trpt->pr = (uchar) II;
+                       trpt->st = tt;
+                       trpt->o_pm &= ~(2|4);
+                       if (t->st > 0)
+                       {       ((P0 *)this)->_p = t->st;
+/*     moved down              reached[ot][t->st] = 1; */
+                       }
+#ifndef SAFETY
+                       if (a_cycles)
+                       {
+#if (ACCEPT_LAB>0 && !defined(NP)) || (PROG_LAB>0 && defined(HAS_NP))
+                               int ii;
+#endif
+#define P__Q   ((P0 *)pptr(ii))
+#if ACCEPT_LAB>0
+#ifdef NP
+                               /* state 1 of np_ claim is accepting */
+                               if (((P0 *)pptr(0))->_p == 1)
+                                       trpt->o_pm |= 2;
+#else
+                               for (ii = 0; ii < (int) now._nr_pr; ii++)
+                               { if (accpstate[P__Q->_t][P__Q->_p])
+                                 {     trpt->o_pm |= 2;
+                                       break;
+                               } }
+#endif
+#endif
+#if defined(HAS_NP) && PROG_LAB>0
+                               for (ii = 0; ii < (int) now._nr_pr; ii++)
+                               { if (progstate[P__Q->_t][P__Q->_p])
+                                 {     trpt->o_pm |= 4;
+                                       break;
+                               } }
+#endif
+#undef P__Q
+                       }
+#endif
+                       trpt->o_t  =  t; trpt->o_n  = _n;
+                       trpt->o_ot = ot; trpt->o_tt = tt;
+                       trpt->o_To = To; trpt->o_m  = _m;
+                       trpt->tau = 0;
+#ifdef RANDOMIZE
+                       trpt->oo_i = ooi;
+#endif
+                       if (boq != -1 || (t->atom&2))
+                       {       trpt->tau |= 8;
+#ifdef VERI
+                               /* atomic sequence in claim */
+                               if((trpt-1)->tau&4)
+                                       trpt->tau |= 4;
+                               else
+                                       trpt->tau &= ~4;
+                       } else
+                       {       if ((trpt-1)->tau&4)
+                                       trpt->tau &= ~4;
+                               else
+                                       trpt->tau |= 4;
+                       }
+                       /* if claim allowed timeout, so */
+                       /* does the next program-step: */
+                       if (((trpt-1)->tau&1) && !(trpt->tau&4))
+                               trpt->tau |= 1;
+#else
+                       } else
+                               trpt->tau &= ~8;
+#endif
+                       if (boq == -1 && (t->atom&2))
+                       {       From = To = II; nlinks++;
+                       } else
+#ifdef REVERSE
+                       {       From = BASE; To = now._nr_pr-1;
+#else
+                       {       From = now._nr_pr-1; To = BASE;
+#endif
+                       }
+#if NCORE>1 && defined(FULL_TRAIL)
+                       if (upto > 0)
+                       {       Push_Stack_Tree(II, t->t_id);
+                       }
+#endif
+                       goto Down;      /* pseudo-recursion */
+Up:
+#ifdef CHECK
+                       cpu_printf("%d: Up - %s\n", depth,
+                               (trpt->tau&4)?"claim":"program");
+#endif
+#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);
+                       }
+#endif
+#ifndef NOFAIR
+                       if (trpt->o_pm&128)     /* fairness alg */
+                       {       now._cnt[now._a_t&1] = trpt->bup.oval;
+                               _n = 1; trpt->o_pm &= ~128;
+                               depth--; trpt--;
+#if defined(VERBOSE) || defined(CHECK)
+       printf("%3d: reversed fairness default move\n", depth);
+#endif
+                               goto Q999;
+                       }
+#endif
+#ifdef HAS_LAST
+#ifdef VERI
+                       { int d; Trail *trl;
+                         now._last = 0;
+                         for (d = 1; d < depth; d++)
+                         {     trl = getframe(depth-d); /* was (trpt-d) */
+                               if (trl->pr != 0)
+                               { now._last = trl->pr - BASE;
+                                 break;
+                       } }     }
+#else
+                       now._last = (depth<1)?0:(trpt-1)->pr;
+#endif
+#endif
+#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);
+                       To = trpt->o_To; _m  = trpt->o_m;
+#ifdef RANDOMIZE
+                       ooi = trpt->oo_i;
+#endif
+#ifdef INLINE_REV
+                       _m = do_reverse(t, II, _m);
+#else
+#include REVERSE_MOVES
+R999:                  /* jumps here when done */
+#endif
+#ifdef VERBOSE
+                       cpu_printf("%3d: proc %d reverses %d, %d to %d\n",
+                               depth, II, t->forw, tt, t->st);
+                       cpu_printf("\t%s [abit=%d,adepth=%d,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
+                       if ((trpt->tau&8)       /* rv or atomic */
+                       &&  (trpt->tau&64))
+                               (trpt-1)->tau |= 64;
+#endif
+#endif
+                       depth--; trpt--;
+
+#ifdef NSUCC
+                       trpt->n_succ++;
+#endif
+#ifdef NIBIS
+                       (trans[ot][tt])->om = _m; /* head of list */
+#endif
+                       /* 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][tt] = 1;
+                       }
+#ifdef HAS_UNLESS
+                       else trpt->e_state = 0; /* undo */
+#endif
+                       if (_m>_n||(_n>3&&_m!=0)) _n=_m;
+                       ((P0 *)this)->_p = tt;
+               } /* all options */
+#ifdef RANDOMIZE
+               if (!t && ooi > 0)
+               {       t = trans[ot][tt];
+       #ifdef VERBOSE
+                       printf("randomizer: continue for %d more\n", ooi);
+       #endif
+                       goto domore;
+               }
+       #ifdef VERBOSE
+                 else
+                       printf("randomizer: done\n");
+       #endif
+#endif
+#ifndef NOFAIR
+               /* Fairness: undo Rule 2 */
+               if ((trpt->o_pm&32)
+               &&  (trpt->o_pm&64))
+               {       if (trpt->o_pm&1)
+                       {
+#ifdef VERI
+                               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("undo Rule 2, cnt=%d, _a_t=%d\n",
+                       now._cnt[now._a_t&1], now._a_t);
+#endif
+                               trpt->o_pm &= ~(32|64);
+                       } else
+                       {       if (_n > 0)
+                               {
+                                       trpt->o_pm &= ~64;
+#ifdef REVERSE
+                                       II = From-1;
+#else
+                                       II = From+1;
+#endif
+               }       }       }
+#endif
+#ifdef VERI
+               if (II == 0) break;     /* never claim */
+#endif
+       } /* all processes */
+#ifdef NSUCC
+       tally_succ(trpt->n_succ);
+#endif
+#ifdef SCHED
+       if (_n == 0     /* no process could move */
+ #ifdef VERI
+       &&  II != 0
+ #endif
+       &&  depth > 0
+       &&  trpt->sched_limit >= sched_max)
+       {       _n = 1; /* not a deadlock */
+       }
+#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)
+                       now._cnt[now._a_t&1] = 2;
+#endif
+               now._cnt[now._a_t&1] += 1;
+#ifdef VERBOSE
+               printf("%3d: 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
+       if (fairness
+       &&  _n == 0             /* nobody moved */
+#ifdef VERI
+       && !(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
+#endif
+#ifndef NOREDUCE
+       /* see below  */
+       && !((trpt->tau&32) && (_n == 0 || (trpt->tau&16)))
+#endif
+       && now._cnt[now._a_t&1] > 0)    /* needed more procs */
+       {       depth++; trpt++;
+               trpt->o_pm |= 128 | ((trpt-1)->o_pm&(2|4));
+               trpt->bup.oval = now._cnt[now._a_t&1];
+               now._cnt[now._a_t&1] = 1;
+#ifdef VERI
+               trpt->tau = 4;
+#else
+               trpt->tau = 0;
+#endif
+#ifdef REVERSE
+               From = BASE; To = now._nr_pr-1;
+#else
+               From = now._nr_pr-1; To = BASE;
+#endif
+#if defined(VERBOSE) || defined(CHECK)
+               printf("%3d: fairness default move ", depth);
+               printf("(all procs block)\n");
+#endif
+               goto Down;
+       }
+#endif
+Q999:  /* returns here with _n>0 when done */;
+       if (trpt->o_pm&8)
+       {       now._a_t &= ~2;
+               now._cnt[now._a_t&1] = 0;
+               trpt->o_pm &= ~8;
+#ifdef VERBOSE
+               printf("%3d: fairness undo Rule 1, _a_t=%d\n",
+                       depth, now._a_t);
+#endif
+       }
+       if (trpt->o_pm&16)
+       {       now._a_t |= 2;
+               now._cnt[now._a_t&1] = 1;
+               trpt->o_pm &= ~16;
+#ifdef VERBOSE
+               printf("%3d: fairness undo Rule 3, _a_t=%d\n",
+                       depth, now._a_t);
+#endif
+       }
+#endif
+#ifndef NOREDUCE
+#ifdef SAFETY
+#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
+#ifdef REVERSE
+       {       From = BASE; To = now._nr_pr-1;
+#else
+       {       From = now._nr_pr-1; To = BASE;
+#endif
+#ifdef DEBUG
+       printf("%3d: proc %d UnSelected (_n=%d, tau=%d)\n", 
+       depth, II+1, _n, trpt->tau);
+#endif
+               _n = 0; trpt->tau &= ~(16|32|64);
+#ifdef REVERSE
+               if (II <= To)   /* II already decremented */
+#else
+               if (II >= BASE) /* II already decremented */
+#endif
+                       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
+               if (a_cycles && (trpt->tau&16))
+               {       if (!(now._a_t&1))
+                       {
+#ifdef DEBUG
+       printf("%3d: setting proviso bit\n", depth);
+#endif
+#ifndef BITSTATE
+#ifdef MA
+#ifdef VERI
+                       (trpt-1)->proviso = 1;
+#else
+                       trpt->proviso = 1;
+#endif
+#else
+#ifdef VERI
+                       if ((trpt-1)->ostate)
+                       ((char *)&((trpt-1)->ostate->state))[0] |= 128;
+#else
+                       ((char *)&(trpt->ostate->state))[0] |= 128;
+#endif
+#endif
+#else
+#ifdef VERI
+                       if ((trpt-1)->ostate)
+                       (trpt-1)->ostate->proviso = 1;
+#else
+                       trpt->ostate->proviso = 1;
+#endif
+#endif
+#ifdef REVERSE
+                               From = BASE; To = now._nr_pr-1;
+#else
+                               From = now._nr_pr-1; To = BASE;
+#endif
+                               _n = 0; trpt->tau &= ~(16|32|64);
+                               goto Again; /* do full search */
+                       } /* else accept reduction */
+               } else
+#ifdef REVERSE
+               {       From = BASE; To = now._nr_pr-1;
+#else
+               {       From = now._nr_pr-1; To = BASE;
+#endif
+                       _n = 0; trpt->tau &= ~(16|32|64);
+#ifdef REVERSE
+                       if (II <= To)   /* already decremented */
+#else
+                       if (II >= BASE) /* already decremented */
+#endif
+                               goto Resume;
+                       else
+                               goto Again;
+       }       }
+/* #endif */
+#endif
+#endif
+       if (_n == 0 || ((trpt->tau&4) && (trpt->tau&2)))
+       {
+#ifdef DEBUG
+               cpu_printf("%3d: no move [II=%d, tau=%d, boq=%d]\n",
+                       depth, II, trpt->tau, boq);
+#endif
+#if SYNC
+               /* ok if a rendez-vous fails: */
+               if (boq != -1) goto Done;
+#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;
+               if ((trpt->tau&8) && !(trpt->tau&4))
+               {       trpt->tau &= ~(1|8);
+                       /* 1=timeout, 8=atomic */
+#ifdef REVERSE
+                       From = BASE; To = now._nr_pr-1;
+#else
+                       From = now._nr_pr-1; To = BASE;
+#endif
+#ifdef DEBUG
+               cpu_printf("%3d: atomic step proc %d unexecutable\n", depth, II+1);
+#endif
+#ifdef VERI
+                       trpt->tau |= 4; /* switch to claim */
+#endif
+                       goto AllOver;
+               }
+#ifdef ETIM
+               if (!(trpt->tau&1)) /* didn't try timeout yet */
+               {
+#ifdef VERI
+                       if (trpt->tau&4)
+                       {
+#ifndef NTIM
+                               if (trpt->tau&2) /* requested */
+#endif
+                               {       trpt->tau |=  1;
+                                       trpt->tau &= ~2;
+#ifdef DEBUG
+                               cpu_printf("%d: timeout\n", depth);
+#endif
+                                       goto Stutter;
+                       }       }
+                       else
+                       {       /* only claim can enable timeout */
+                               if ((trpt->tau&8)
+                               &&  !((trpt-1)->tau&4))
+/* blocks inside an atomic */          goto BreakOut;
+#ifdef DEBUG
+                               cpu_printf("%d: req timeout\n",
+                                       depth);
+#endif
+                               (trpt-1)->tau |= 2; /* request */
+#if NCORE>1 && defined(FULL_TRAIL)
+                               if (upto > 0)
+                               {       Pop_Stack_Tree();
+                               }
+#endif
+                               goto Up;
+                       }
+#else
+#ifdef DEBUG
+                       cpu_printf("%d: timeout\n", depth);
+#endif
+                       trpt->tau |=  1;
+                       goto Again;
+#endif
+               }
+#endif
+#ifdef VERI
+BreakOut:
+#ifndef NOSTUTTER
+               if (!(trpt->tau&4))
+               {       trpt->tau |= 4;   /* claim stuttering */
+                       trpt->tau |= 128; /* stutter mark */
+#ifdef DEBUG
+                       cpu_printf("%d: claim stutter\n", depth);
+#endif
+                       goto Stutter;
+               }
+#else
+               ;
+#endif
+#else
+               if (!noends && !a_cycles && !endstate())
+               {       depth--; trpt--;        /* new 4.2.3 */
+                       uerror("invalid end state");
+                       depth++; trpt++;
+               }
+#ifndef NOSTUTTER
+               else if (a_cycles && (trpt->o_pm&2)) /* new 4.2.4 */
+               {       depth--; trpt--;
+                       uerror("accept stutter");
+                       depth++; trpt++;
+               }
+#endif
+#endif
+       }
+Done:
+       if (!(trpt->tau&8))     /* not in atomic seqs */
+       {
+#ifndef SAFETY
+               if (_n != 0
+#ifdef VERI
+               /* --after-- a program-step, i.e., */
+               /* after backtracking a claim-step */
+               && (trpt->tau&4)
+               /* with at least one running process */
+               /* unless in a stuttered accept state */
+               && ((now._nr_pr > 1) || (trpt->o_pm&2))
+#endif
+               && !(now._a_t&1))
+               {
+#ifndef NOFAIR
+                       if (fairness)
+                       {
+#ifdef VERBOSE
+                       cpu_printf("Consider check %d %d...\n",
+                               now._a_t, now._cnt[0]);
+#endif
+                               if ((now._a_t&2) /* A-bit */
+                               &&  (now._cnt[0] == 1))
+                                       checkcycles();
+                       } else
+#endif
+                       if (a_cycles && (trpt->o_pm&2))
+                               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();
+               }
+#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
+       }
+       if (depth > 0)
+       {
+#if NCORE>1 && defined(FULL_TRAIL)
+               if (upto > 0)
+               {       Pop_Stack_Tree();
+               }
+#endif
+               goto Up;
+       }
+}
+
+#else
+void new_state(void) { /* place holder */ }
+#endif
+
+void
+assert(int a, char *s, int ii, int tt, Trans *t)
+{
+       if (!a && !noasserts)
+       {       char bad[1024];
+               strcpy(bad, "assertion violated ");
+               if (strlen(s) > 1000)
+               {       strncpy(&bad[19], (const char *) s, 1000);
+                       bad[1019] = '\0';
+               } else
+                       strcpy(&bad[19], s);
+               uerror(bad);
+       }
+}
+#ifndef NOBOUNDCHECK
+int
+Boundcheck(int x, int y, int a1, int a2, Trans *a3)
+{
+       assert((x >= 0 && x < y), "- invalid array index",
+               a1, a2, a3);
+       return x;
+}
+#endif
+void
+wrap_stats(void)
+{
+       if (nShadow>0)
+         printf("%9.8g states, stored (%g visited)\n",
+                       nstates - nShadow, nstates);
+       else
+         printf("%9.8g states, stored\n", nstates);
+#ifdef BFS
+#if SYNC
+       printf("        %8g nominal states (- rv and atomic)\n", nstates-midrv-nlinks+revrv);
+       printf("        %8g rvs succeeded\n", midrv-failedrv);
+#else
+       printf("        %8g nominal states (stored-atomic)\n", nstates-nlinks);
+#endif
+#ifdef DEBUG
+       printf("        %8g midrv\n", midrv);
+       printf("        %8g failedrv\n", failedrv);
+       printf("        %8g revrv\n", revrv);
+#endif
+#endif
+       printf("%9.8g states, matched\n", truncs);
+#ifdef CHECK
+       printf("%9.8g matches within stack\n",truncs2);
+#endif
+       if (nShadow>0)
+       printf("%9.8g transitions (= visited+matched)\n",
+               nstates+truncs);
+       else
+       printf("%9.8g transitions (= stored+matched)\n",
+               nstates+truncs);
+       printf("%9.8g atomic steps\n", nlinks);
+       if (nlost) printf("%g lost messages\n", (double) nlost);
+
+#ifndef BITSTATE
+       printf("hash conflicts: %9.8g (resolved)\n", hcmp);
+       #ifndef AUTO_RESIZE
+       if (hcmp > (double) (1<<ssize))
+       {       printf("hint: increase hashtable-size (-w) to reduce runtime\n");
+       }       /* in multi-core: also reduces lock delays on access to hashtable */
+       #endif
+#else
+#ifdef CHECK
+       printf("%8g states allocated for dfs stack\n", ngrabs);
+#endif
+       if (udmem)
+       printf("\nhash factor: %4g (best if > 100.)\n\n",
+               (double)(((double) udmem) * 8.0) / (double) nstates);
+       else
+       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
+       if (udmem)
+       {       printf("total bits available: %8g (-M%ld)\n",
+               ((double) udmem) * 8.0, udmem/(1024L*1024L));
+       } else
+       printf("total bits available: %8g (-w%d)\n",
+               ((double) (ONE_L << (ssize-4)) * 16.0), ssize);
+       #endif
+#endif
+#ifdef BFS_DISK
+       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;
+       #endif
+#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);
+#endif
+       printf("\n(%s)\n", SpinVersion);
+       if (!done) printf("Warning: Search not completed\n");
+#ifdef SC
+       (void) unlink((const char *)stackfile);
+#endif
+#if NCORE>1
+       if (a_cycles)
+       {       printf("        + Multi-Core (NCORE=%d)\n", NCORE);
+       } else
+       {       printf("        + Multi-Core (NCORE=%d -z%d)\n", NCORE, z_handoff);
+       }
+#endif
+#ifdef BFS
+       printf("        + Using Breadth-First Search\n");
+#endif
+#ifndef NOREDUCE
+       printf("        + Partial Order Reduction\n");
+#endif
+#ifdef REVERSE
+       printf("        + Reverse Depth-First Search Order\n");
+#endif
+#ifdef T_REVERSE
+       printf("        + Reverse Transition Ordering\n");
+#endif
+#ifdef RANDOMIZE
+       printf("        + Randomized Transition Ordering\n");
+#endif
+#ifdef SCHED
+       printf("        + Scheduling Restriction (-DSCHED=%d)\n", sched_max);
+#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", PanSource);
+  #endif
+#endif
+#ifdef CHECK
+  #ifdef FULLSTACK
+       printf("        + FullStack Matching\n");
+  #endif
+  #ifdef CNTRSTACK
+       printf("        + CntrStack Matching\n");
+  #endif
+#endif
+#ifdef BITSTATE
+       printf("\nBit statespace search for:\n");
+#else
+#ifdef HC
+       printf("\nHash-Compact %d search for:\n", HC);
+#else
+       printf("\nFull statespace search for:\n");
+#endif
+#endif
+#ifdef EVENT_TRACE
+#ifdef NEGATED_TRACE
+       printf("        notrace assertion       +\n");
+#else
+       printf("        trace assertion         +\n");
+#endif
+#endif
+#ifdef VERI
+       printf("        never claim             +\n");
+       printf("        assertion violations    ");
+       if (noasserts)
+               printf("- (disabled by -A flag)\n");
+       else
+               printf("+ (if within scope of claim)\n");
+#else
+#ifdef NOCLAIM
+       printf("        never claim             - (not selected)\n");
+#else
+       printf("        never claim             - (none specified)\n");
+#endif
+       printf("        assertion violations    ");
+       if (noasserts)
+               printf("- (disabled by -A flag)\n");
+       else
+               printf("+\n");
+#endif
+#ifndef SAFETY
+#ifdef NP
+       printf("        non-progress cycles     ");
+#else
+       printf("        acceptance   cycles     ");
+#endif
+       if (a_cycles)
+               printf("+ (fairness %sabled)\n",
+                       fairness?"en":"dis");
+       else printf("- (not selected)\n");
+#else
+       printf("        cycle checks            - (disabled by -DSAFETY)\n");
+#endif
+#ifdef VERI
+       printf("        invalid end states      - ");
+       printf("(disabled by ");
+       if (noends)
+               printf("-E flag)\n\n");
+       else
+               printf("never claim)\n\n");
+#else
+       printf("        invalid end states      ");
+       if (noends)
+               printf("- (disabled by -E flag)\n\n");
+       else
+               printf("+\n\n");
+#endif
+       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);
+               if (maxgs+a_cycles+2 < MA)
+               printf("MA stats: -DMA=%d is sufficient\n",
+                       maxgs+a_cycles+2);
+               dfa_stats();
+       }
+#endif
+       wrap_stats();
+#ifdef CHECK
+       printf("stackframes: %d/%d\n\n", smax, svmax);
+       printf("stats: fa %d, fh %d, zh %d, zn %d - ",
+               Fa, Fh, Zh, Zn);
+       printf("check %d holds %d\n", Ccheck, Cholds);
+       printf("stack stats: puts %d, probes %d, zaps %d\n",
+               PUT, PROBE, ZAPS);
+#else
+       printf("\n");
+#endif
+
+#if defined(BITSTATE) || !defined(NOCOMP)
+       nr1 = (nstates-nShadow)*
+             (double)(hmax+sizeof(struct H_el)-sizeof(unsigned));
+#ifdef BFS
+       nr2 = 0.0;
+#else
+       nr2 = (double) ((maxdepth+3)*sizeof(Trail));
+#endif
+#ifndef BITSTATE
+#if !defined(MA) || defined(COLLAPSE)
+       nr3 = (double) (ONE_L<<ssize)*sizeof(struct H_el *);
+#endif
+#else
+       if (udmem)
+               nr3 = (double) (udmem);
+       else
+       nr3 = (double) (ONE_L<<(ssize-3));
+#ifdef CNTRSTACK
+       nr5 = (double) (ONE_L<<(ssize-3));
+#endif
+#ifdef FULLSTACK
+       nr5 = (double) (maxdepth*sizeof(struct H_el *));
+#endif
+#endif
+       nr4 = (double) (svmax * (sizeof(Svtack) + hmax))
+           + (double) (smax * (sizeof(Stack) + Maxbody));
+#ifndef MA
+       if (mverbose || 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("%9.3f   equivalent memory usage for states",
+                       nr1/1048576.); /* 1024*1024=1048576 */
+               printf(" (stored*(State-vector + overhead))\n");
+       #if NCORE>1 && !defined(WIN32) && !defined(WIN64)
+               printf("%9.3f   shared memory reserved for state storage\n",
+                       mem_reserved/1048576.);
+               #ifdef SEP_HEAP
+               printf("                in %d local heaps of %7.3f MB each\n",
+                       NCORE, mem_reserved/(NCORE*1048576.));
+               #endif
+               printf("\n");
+       #endif
+#ifdef BITSTATE
+               if (udmem)
+               printf("%9.3f   memory used for hash array (-M%ld)\n",
+                       nr3/1048576., udmem/(1024L*1024L));
+               else
+               printf("%9.3f   memory used for hash array (-w%d)\n",
+                       nr3/1048576., ssize);
+               if (nr5 > 0.0)
+               printf("%9.3f   memory used for bit stack\n",
+                       nr5/1048576.);
+               remainder = remainder - nr3 - nr5;
+#else
+               printf("%9.3f   actual memory usage for states",
+                       tmp_nr/1048576.);
+               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("                state-vector as stored = %.0f byte",
+                       (tmp_nr)/(nstates-nShadow) -
+                       (double) (sizeof(struct H_el) - sizeof(unsigned)));
+                       printf(" + %ld byte overhead\n",
+                       (long int) sizeof(struct H_el)-sizeof(unsigned));
+               }
+#endif
+#if !defined(MA) || defined(COLLAPSE)
+               printf("%9.3f   memory used for hash table (-w%d)\n",
+                       nr3/1048576., ssize);
+               remainder -= nr3;
+#endif
+#endif
+#ifndef BFS
+               printf("%9.3f   memory 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   shared memory used for work-queues\n",
+                       (GWQ_SIZE + (double) NCORE * LWQ_SIZE) /1048576.);
+               printf("                in %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   other (proc and chan stacks)\n",
+                       (remainder-fragment)/1048576.);
+               if (fragment > 1048576.)
+               printf("%9.3f   memory lost to fragmentation\n",
+                       fragment/1048576.);
+               printf("%9.3f   total actual memory usage\n\n",
+                       memcnt/1048576.);
+       }
+#ifndef MA
+       else
+#endif
+#endif
+#ifndef MA
+               printf("%9.3f   memory usage (Mbyte)\n\n",
+                       memcnt/1048576.);
+#endif
+#ifdef COLLAPSE
+       printf("nr of templates: [ globals chans procs ]\n");
+       printf("collapse counts: [ ");
+       { int i; for (i = 0; i < 256+2; i++)
+               if (ncomps[i] != 0)
+                       printf("%d ", ncomps[i]);
+               printf("]\n");
+       }
+#endif
+       if ((done || verbose) && !no_rck) do_reach();
+#ifdef PEG
+       { int i;
+         printf("\nPeg Counts (transitions executed):\n");
+         for (i = 1; i < NTRANS; i++)
+         {     if (peg[i]) putpeg(i, peg[i]);
+       } }
+#endif
+#ifdef VAR_RANGES
+       dumpranges();
+#endif
+#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
+       pan_exit(0);
+}
+
+void
+stopped(int arg)
+{      printf("Interrupted\n");
+#if NCORE>1
+       was_interrupted = 1;
+#endif
+       wrapup();
+       pan_exit(0);
+}
+
+#ifdef SFH
+/*
+ * super fast hash, based on Paul Hsieh's function
+ * http://www.azillionmonkeys.com/qed/hash.html
+ */
+#include <stdint.h>
+       #undef get16bits
+       #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
+       || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+               #define get16bits(d) (*((const uint16_t *) (d)))
+       #endif
+
+       #ifndef get16bits
+               #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+                       +(uint32_t)(((const uint8_t *)(d))[0]) )
+       #endif
+
+void
+d_sfh(const char *s, int len)
+{      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;
+}
+#endif
+
+#include <stdint.h>
+#if defined(HASH64) || defined(WIN64)
+/* 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);  \
+  c -= a; c -= b; c ^= (b>>8);  \
+  a -= b; a -= c; a ^= (c>>38); \
+  b -= c; b -= a; b ^= (a<<23); \
+  c -= a; c -= b; c ^= (b>>5);  \
+  a -= b; a -= c; a ^= (c>>35); \
+  b -= c; b -= a; b ^= (a<<49); \
+  c -= a; c -= b; c ^= (b>>11); \
+  a -= b; a -= c; a ^= (c>>12); \
+  b -= c; b -= a; b ^= (a<<18); \
+  c -= a; c -= b; c ^= (b>>22); \
+}
+#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 -= 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; \
+}
+
+#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)
+{      uint8_t  *bp;
+#if defined(HASH64) || defined(WIN64)
+       uint64_t a = 0, b, c, n;
+       uint64_t *k = (uint64_t *) kb;
+#else
+       uint32_t a, b, c, n;
+       uint32_t *k = (uint32_t *) kb;
+#endif
+       /* extend to multiple of words, if needed */
+       n = nbytes/WS;  /* nr of words */
+       a = nbytes - (n*WS);
+       if (a > 0)
+       {       n++;
+               bp = kb + nbytes;
+               switch (a) {
+               case 3: *bp++ = 0; /* fall thru */
+               case 2: *bp++ = 0; /* fall thru */
+               case 1: *bp   = 0;
+               case 0: break;
+       }       }
+#if defined(HASH64) || defined(WIN64)
+       b = HASH_CONST[HASH_NR];
+       c = 0x9e3779b97f4a7c13LL; /* arbitrary value */
+       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);
+#else
+       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];
+       case 0: break;
+       }
+       final(a,b,c);
+#endif
+       j1 = c&nmask; j3 = a&7;      /* 1st bit */
+       j2 = b&nmask; j4 = (a>>3)&7; /* 2nd bit */
+       K1 = c; K2 = b;
+}
+
+void
+s_hash(uchar *cp, int om)
+{
+#if defined(SFH)
+       d_sfh((const char *) cp, om); /* sets K1 */
+#else
+       d_hash(cp, om); /* sets K1 etc */
+#endif
+#ifdef BITSTATE
+       if (S_Tab == H_tab)
+               j1 = K1 % omaxdepth;
+       else
+#endif
+               if (ssize < 8*WS)
+                       j1 = K1&mask;
+               else
+                       j1 = K1;
+}
+#ifndef RANDSTOR
+int *prerand;
+void
+inirand(void)
+{      int i;
+       srand(123);     /* fixed startpoint */
+       prerand = (int *) emalloc((omaxdepth+3)*sizeof(int));
+       for (i = 0; i < omaxdepth+3; i++)
+               prerand[i] = rand();
+}
+int
+pan_rand(void)
+{      if (!prerand) inirand();
+       return prerand[depth];
+}
+#endif
+
+void
+set_masks(void)        /* 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 = ((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);
+       }
+}
+
+static long reclaim_size;
+static char *reclaim_mem;
+#if defined(AUTO_RESIZE) && !defined(BITSTATE) && !defined(MA)
+#if NCORE>1
+       #error cannot combine AUTO_RESIZE with NCORE>1 yet
+#endif
+static struct H_el **N_tab;
+void
+reverse_capture(struct H_el *p)
+{      if (!p) return;
+       reverse_capture(p->nxt);
+       /* last element of list moves first */
+       /* to preserve list-order */
+       j2 = p->m_K1;
+       if (ssize < 8*WS) /* probably always true */
+       {       j2 &= mask;
+       }
+       p->nxt = N_tab[j2];
+       N_tab[j2] = p;
+}
+void
+resize_hashtable(void)
+{
+       if (WS == 4 && ssize >= 27 - 1)
+       {       return; /* canot increase further */
+       }
+
+       ssize += 2; /* 4x size */
+
+       printf("pan: resizing hashtable to -w%d.. ", ssize);
+
+       N_tab = (struct H_el **)
+               emalloc((ONE_L<<ssize)*sizeof(struct H_el *));
+
+       set_masks();    /* they changed */
+
+       for (j1 = 0; j1 < (ONE_L << (ssize - 2)); j1++)
+       {       reverse_capture(H_tab[j1]);
+       }
+       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
+
+int
+main(int argc, char *argv[])
+{      void to_compile(void);
+
+       efd = stderr;   /* default */
+#ifdef BITSTATE
+       bstore = 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
+               case 'a': a_cycles = 1; break;
+#endif
+#endif
+               case 'A': noasserts = 1; break;
+               case 'b': bounded = 1; break;
+#ifdef HAS_CODE
+               case 'C': coltrace = 1; goto samething;
+#endif
+               case 'c': upto  = atoi(&argv[1][2]); break;
+               case 'd': state_tables++; break;
+               case 'e': every_error = 1; Nr_Trails = 1; break;
+               case 'E': noends = 1; break;
+#ifdef SC
+               case 'F': if (strlen(argv[1]) > 2)
+                               stackfile = &argv[1][2];
+                         break;
+#endif
+#if !defined(SAFETY) && !defined(NOFAIR)
+               case 'f': fairness = 1; break;
+#endif
+#ifdef HAS_CODE
+               case 'g': gui = 1; goto samething;
+#endif
+               case 'h': if (!argv[1][2]) usage(efd); else
+                         HASH_NR = atoi(&argv[1][2])%33; break;
+               case 'I': iterative = 2; every_error = 1; break;
+               case 'i': 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 SCHED
+               case 'L': sched_max = atoi(&argv[1][2]); break;
+#endif
+#ifndef SAFETY
+#ifdef NP
+               case 'l': a_cycles = 1; break;
+#else
+               case 'l': fprintf(efd, "error: -l disabled");
+                         usage(efd); break;
+#endif
+#endif
+#ifdef BITSTATE
+               case 'M': udmem = atoi(&argv[1][2]); break;
+               case 'G': udmem = atoi(&argv[1][2]); udmem *= 1024; break;
+#else
+               case 'M': case 'G':
+                         fprintf(stderr, "-M and -G affect only -DBITSTATE\n");
+                         break;
+#endif
+               case 'm': maxdepth = atoi(&argv[1][2]); break;
+               case 'n': no_rck = 1; break;
+               case 'P': readtrail = 1; onlyproc = atoi(&argv[1][2]);
+                         if (argv[2][0] != '-') /* check next arg */
+                         {     trailfilename = argv[2];
+                               argc--; argv++; /* skip next arg */
+                         }
+                         break;
+#ifdef SVDUMP
+               case 'p': vprefix = atoi(&argv[1][2]); break;
+#endif
+#if NCORE==1
+               case 'Q': quota = (double) 60.0 * (double) atoi(&argv[1][2]); break;
+#endif
+               case 'q': strict = 1; break;
+               case 'R': Nrun = atoi(&argv[1][2]); break;
+#ifdef HAS_CODE
+               case 'r':
+samething:               readtrail = 1;
+                         if (isdigit(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 'S': silent = 1; goto samething;
+#endif
+#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': 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]); break;
+               case 'Y': signoff = 1; break;
+               case 'X': efd = stdout; 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 that 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 (iterative && TMODE != 0666)
+       {       TMODE = 0666;
+               fprintf(efd, "warning: -T ignored when -i or -I is used\n");
+       }
+#if defined(HASH32) && !defined(SFH)
+       if (WS > 4)
+       {       fprintf(efd, "strong warning: compiling -DHASH32 on a 64-bit machine\n");
+               fprintf(efd, " without -DSFH can slow down performance a lot\n");
+       }
+#endif
+#if defined(WIN32) || defined(WIN64)
+       if (TMODE == 0666)
+               TMODE = _S_IWRITE | _S_IREAD;
+       else
+               TMODE = _S_IREAD;
+#endif
+#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);
+#endif
+       #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
+       }
+       #endif
+       #ifdef HAS_HIDDEN
+       #error cannot use hidden variables when compiling multi-core
+       #endif
+#endif
+#ifdef BITSTATE
+       if (hfns <= 0)
+       {       hfns = 1;
+               fprintf(efd, "warning: using -k%d as minimal usable value\n", hfns);
+       }
+#endif
+       omaxdepth = maxdepth;
+#ifdef BITSTATE
+       if (WS == 4 && ssize > 34)
+       {       ssize = 34;
+               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
+ */
+       }
+#else
+       if (WS == 4 && ssize > 27)
+       {       ssize = 27;
+               fprintf(efd, "warning: using -w%d as max usable value\n", ssize);
+/*
+ *     for emalloc, the lookup table size multiplies by 4 for the pointers
+ *     the largest power of 2 that can be represented in a ulong is 1^31
+ *     hence the largest number of lookup table slots is 31-4 = 27
+ */
+       }
+#endif
+#ifdef SC
+       hiwater = HHH = maxdepth-10;
+       DDD = HHH/2;
+       if (!stackfile)
+       {       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");
+               pan_exit(1);
+       }
+#endif
+#if (defined(R_XPT) || defined(W_XPT)) && !defined(MA)
+       #warning -DR_XPT and -DW_XPT assume -DMA (ignored)
+#endif
+       if (iterative && a_cycles)
+       fprintf(efd, "warning: -i or -I work for safety properties only\n");
+#ifdef BFS
+       #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 REACH
+               #warning -DREACH is redundant when -DBFS is used
+       #endif
+#endif
+#if defined(MERGED) && defined(PEG)
+       #error to use -DPEG use: spin -o3 -a
+#endif
+#ifdef HC
+       #ifdef SFH
+               #error cannot combine -DHC and -DSFH
+               /* use of NOCOMP is the real reason */
+       #else
+               #ifdef NOCOMP
+               #error cannot combine -DHC and -DNOCOMP
+               #endif
+       #endif
+       #ifdef BITSTATE
+               #error cannot combine -DHC and -DBITSTATE
+       #endif
+#endif
+#if defined(SAFETY) && defined(NP)
+       #error cannot combine -DNP and -DBFS or -DSAFETY
+#endif
+#ifdef MA
+       #ifdef BITSTATE
+               #error cannot combine -DMA and -DBITSTATE
+       #endif
+       #if MA <= 0
+               #error usage: -DMA=N with N > 0 and N < VECTORSZ
+       #endif
+#endif
+#ifdef COLLAPSE
+       #ifdef BITSTATE
+               #error cannot combine -DBITSTATE and -DCOLLAPSE
+       #endif
+       #ifdef SFH
+               #error cannot combine -DCOLLAPSE and -DSFH
+               /* use of NOCOMP is the real reason */
+       #else
+               #ifdef NOCOMP
+               #error cannot combine -DCOLLAPSE and -DNOCOMP
+               #endif
+       #endif
+#endif
+       if (maxdepth <= 0 || ssize <= 1) usage(efd);
+#if SYNC>0 && !defined(NOREDUCE)
+       if (a_cycles && fairness)
+       { fprintf(efd, "error: p.o. reduction not compatible with ");
+         fprintf(efd, "fairness (-f) in models\n");
+         fprintf(efd, "       with rendezvous operations: ");
+         fprintf(efd, "recompile with -DNOREDUCE\n");
+         pan_exit(1);
+       }
+#endif
+#if defined(REM_VARS) && !defined(NOREDUCE)
+       #warning p.o. reduction not compatible with remote varrefs (use -DNOREDUCE)
+#endif
+#if defined(NOCOMP) && !defined(BITSTATE)
+       if (a_cycles)
+       { fprintf(efd, "error: use of -DNOCOMP voids -l and -a\n");
+         pan_exit(1);
+       }
+#endif
+#ifdef MEMLIM
+       memlim = ((double) MEMLIM) * (double) (1<<20);  /* size in Mbyte */
+#endif
+#ifndef BITSTATE
+       if (Nrun > 1) HASH_NR = Nrun - 1;
+#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)
+       {       fprintf(efd, "error: no accept labels defined ");
+               fprintf(efd, "in model (for option -a)\n");
+               usage(efd);
+       }
+       #endif
+#endif
+#ifndef NOREDUCE
+       #ifdef 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
+       #ifdef HAS_LAST
+               #error use of _last requires -DNOREDUCE
+       #endif
+#endif
+#if SYNC>0 && !defined(NOREDUCE)
+       #ifdef HAS_UNLESS
+       fprintf(efd, "warning: use of a rendezvous stmnts in the escape\n");
+       fprintf(efd, "  of an unless clause, if present, could make p.o. reduction\n");
+       fprintf(efd, "  invalid (use -DNOREDUCE to avoid this)\n");
+               #ifdef BFS
+               fprintf(efd, "  (this type of rv is also not compatible with -DBFS)\n");
+               #endif
+       #endif
+#endif
+#if SYNC>0 && defined(BFS)
+       #warning use of rendezvous with BFS does not preserve all invalid endstates
+#endif
+#if !defined(REACH) && !defined(BITSTATE)
+       if (iterative != 0 && a_cycles == 0)
+       {       fprintf(efd, "warning: -i and -I need -DREACH to work accurately\n");
+       }
+#endif
+#if defined(BITSTATE) && defined(REACH)
+       #warning -DREACH is voided by -DBITSTATE
+#endif
+#if defined(MA) && defined(REACH)
+       #warning -DREACH is voided by -DMA
+#endif
+#if defined(FULLSTACK) && defined(CNTRSTACK)
+       #error cannot combine -DFULLSTACK and -DCNTRSTACK
+#endif
+#if defined(VERI)
+       #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 (!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
+#ifndef SAFETY
+       if (!a_cycles
+       #ifdef HAS_CODE
+       && !readtrail
+       #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
+       if (!a_cycles)
+       {       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;
+               /* -2 because first two uchars in now are masked */
+               #endif
+       }       }
+       #endif
+#endif
+       signal(SIGINT, stopped);
+       set_masks();
+#ifdef BFS
+       trail = (Trail *) emalloc(6*sizeof(Trail));
+       trail += 3;
+#else
+       trail = (Trail *) emalloc((maxdepth+3)*sizeof(Trail));
+       trail++;        /* protect trpt-1 refs at depth 0 */
+#endif
+#ifdef SVDUMP
+       if (vprefix > 0)
+       {       char nm[64];
+               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);
+#endif
+#if SYNC>0 && ASYNC==0
+       set_recvs();
+#endif
+       run();
+       done = 1;
+       wrapup();
+       return 0;
+}
+
+void
+usage(FILE *fd)
+{
+       fprintf(fd, "%s\n", SpinVersion);
+       fprintf(fd, "Valid Options are:\n");
+#ifndef SAFETY
+#ifdef NP
+       fprintf(fd, "   -a  -> is disabled by -DNP ");
+       fprintf(fd, "(-DNP compiles for -l only)\n");
+#else
+       fprintf(fd, "   -a  find acceptance cycles\n");
+#endif
+#else
+       fprintf(fd, "   -a,-l,-f  -> are disabled by -DSAFETY\n");
+#endif
+       fprintf(fd, "   -A  ignore assert() violations\n");
+       fprintf(fd, "   -b  consider it an error to exceed the depth-limit\n");
+       fprintf(fd, "   -cN stop at Nth error ");
+       fprintf(fd, "(defaults to -c1)\n");
+       fprintf(fd, "   -d  print state tables and stop\n");
+       fprintf(fd, "   -e  create trails for all errors\n");
+       fprintf(fd, "   -E  ignore invalid end states\n");
+#ifdef SC
+       fprintf(fd, "   -Ffile  use 'file' to store disk-stack\n");
+#endif
+#ifndef NOFAIR
+       fprintf(fd, "   -f  add weak fairness (to -a or -l)\n");
+#endif
+       fprintf(fd, "   -hN use different hash-seed N:1..32\n");
+       fprintf(fd, "   -i  search for shortest path to error\n");
+       fprintf(fd, "   -I  like -i, but approximate and faster\n");
+       fprintf(fd, "   -J  reverse eval order of nested unlesses\n");
+#ifdef BITSTATE
+       fprintf(fd, "   -kN set N bits per state (defaults to 3)\n");
+#endif
+#ifdef SCHED
+       fprintf(fd, "   -LN set scheduling restriction to N (default 10)\n");
+#endif
+#ifndef SAFETY
+#ifdef NP
+       fprintf(fd, "   -l  find non-progress cycles\n");
+#else
+       fprintf(fd, "   -l  find non-progress cycles -> ");
+       fprintf(fd, "disabled, requires ");
+       fprintf(fd, "compilation with -DNP\n");
+#endif
+#endif
+#ifdef BITSTATE
+       fprintf(fd, "   -MN use N Megabytes for bitstate hash array\n");
+       fprintf(fd, "   -GN use N Gigabytes for bitstate hash array\n");
+#endif
+       fprintf(fd, "   -mN max depth N steps (default=10k)\n");
+       fprintf(fd, "   -n  no listing of unreached states\n");
+#ifdef SVDUMP
+       fprintf(fd, "   -pN create svfile (save N bytes per state)\n");
+#endif
+       fprintf(fd, "   -QN set time-limit on execution of N minutes\n");
+       fprintf(fd, "   -q  require empty chans in valid end states\n");
+#ifdef HAS_CODE
+       fprintf(fd, "   -r  read and execute trail - can add -v,-n,-PN,-g,-C\n");
+       fprintf(fd, "   -rN read and execute N-th error trail\n");
+       fprintf(fd, "   -C  read and execute trail - columnated output (can add -v,-n)\n");
+       fprintf(fd, "   -PN read and execute trail - restrict trail output to proc N\n");
+       fprintf(fd, "   -g  read and execute trail + msc gui support\n");
+       fprintf(fd, "   -S  silent replay: only user defined printfs show\n");
+#endif
+#ifdef BITSTATE
+       fprintf(fd, "   -RN repeat run Nx with N ");
+       fprintf(fd, "[1..32] independent hash functions\n");
+       fprintf(fd, "   -s  same as -k1 (single bit per state)\n");
+#endif
+       fprintf(fd, "   -T  create trail files in read-only mode\n");
+       fprintf(fd, "   -tsuf replace .trail with .suf on trailfiles\n");
+       fprintf(fd, "   -V  print SPIN version number\n");
+       fprintf(fd, "   -v  verbose -- filenames in unreached state listing\n");
+       fprintf(fd, "   -wN hashtable of 2^N entries ");
+       fprintf(fd, "(defaults to -w%d)\n", ssize);
+       fprintf(fd, "   -x  do not overwrite an existing trail file\n");
+#if NCORE>1
+       fprintf(fd, "   -zN handoff states below depth N to 2nd cpu (multi_core)\n");
+#endif
+#ifdef HAS_CODE
+       fprintf(fd, "\n options -r, -C, -PN, -g, and -S can optionally be followed by\n");
+       fprintf(fd, "   a 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)
+{      char *tmp;
+#ifdef MEMLIM
+       if (memcnt+ (double) n > memlim) goto err;
+#endif
+#if 1
+       tmp = (char *) malloc(n);
+       if (!tmp)
+#else
+       tmp = (char *) sbrk(n);
+       if (tmp == (char *) -ONE_L)
+#endif
+       {
+#ifdef MEMLIM
+err:
+#endif
+               printf("pan: out of memory\n");
+#ifdef MEMLIM
+               printf("        %g bytes used\n", memcnt);
+               printf("        %g bytes more needed\n", (double) n);
+               printf("        %g bytes limit\n",
+                       memlim);
+#endif
+#ifdef COLLAPSE
+               printf("hint: to reduce memory, recompile with\n");
+#ifndef MA
+               printf("  -DMA=%d   # better/slower compression, or\n", hmax);
+#endif
+               printf("  -DBITSTATE # supertrace, approximation\n");
+#else
+#ifndef BITSTATE
+               printf("hint: to reduce memory, recompile with\n");
+#ifndef HC
+               printf("  -DCOLLAPSE # good, fast compression, or\n");
+#ifndef MA
+               printf("  -DMA=%d   # better/slower compression, or\n", hmax);
+#endif
+               printf("  -DHC # hash-compaction, approximation\n");
+#endif
+               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;
+       return tmp;
+}
+
+#define CHUNK  (100*VECTORSZ)
+
+char *
+emalloc(unsigned long 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)
+       {       grow = (n < CHUNK) ? CHUNK : n;
+               have = Malloc(grow);
+               fragment += (double) left;
+               left = grow;
+       }
+       tmp = have;
+       have += (long) n;
+       left -= (long) n;
+       memset(tmp, 0, n);
+       return tmp;
+}
+void
+Uerror(char *str)
+{      /* always fatal */
+       uerror(str);
+#if NCORE>1
+       sudden_stop("Uerror");
+#endif
+       wrapup();
+}
+
+#if defined(MA) && !defined(SAFETY)
+int
+Unwind(void)
+{      Trans *t; uchar ot, _m; int tt; short II;
+#ifdef VERBOSE
+       int i;
+#endif
+       uchar oat = now._a_t;
+       now._a_t &= ~(1|16|32);
+       memcpy((char *) &comp_now, (char *) &now, vsize);
+       now._a_t = oat;
+Up:
+#ifdef SC
+       trpt = getframe(depth);
+#endif
+#ifdef VERBOSE
+       printf("%d       State: ", depth);
+       for (i = 0; i < vsize; i++) printf("%d%s,",
+               ((char *)&now)[i], Mask[i]?"*":"");
+       printf("\n");
+#endif
+#ifndef NOFAIR
+       if (trpt->o_pm&128)     /* fairness alg */
+       {       now._cnt[now._a_t&1] = trpt->bup.oval;
+               depth--;
+#ifdef SC
+               trpt = getframe(depth);
+#else
+               trpt--;
+#endif
+               goto Q999;
+       }
+#endif
+#ifdef HAS_LAST
+#ifdef VERI
+       { int d; Trail *trl;
+         now._last = 0;
+         for (d = 1; d < depth; d++)
+         {     trl = getframe(depth-d); /* was trl = (trpt-d); */
+               if (trl->pr != 0)
+               { now._last = trl->pr - BASE;
+                 break;
+       } }     }
+#else
+       now._last = (depth<1)?0:(trpt-1)->pr;
+#endif
+#endif
+#ifdef EVENT_TRACE
+       now._event = trpt->o_event;
+#endif
+       if ((now._a_t&1) && depth <= A_depth)
+       {       now._a_t &= ~(1|16|32);
+               if (fairness) now._a_t |= 2;    /* ? */
+               A_depth = 0;
+               goto CameFromHere;      /* checkcycles() */
+       }
+       t  = trpt->o_t;
+       ot = trpt->o_ot; II = trpt->pr;
+       tt = trpt->o_tt; this = pptr(II);
+       _m = do_reverse(t, II, trpt->o_m);
+#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] <unwind>\n", 
+               trpt->tau, (trpt-1)->tau);
+#endif
+       depth--;
+#ifdef SC
+       trpt = getframe(depth);
+#else
+       trpt--;
+#endif
+       /* reached[ot][t->st] = 1;      3.4.13 */
+       ((P0 *)this)->_p = tt;
+#ifndef NOFAIR
+       if ((trpt->o_pm&32))
+       {
+#ifdef VERI
+               if (now._cnt[now._a_t&1] == 0)
+                       now._cnt[now._a_t&1] = 1;
+#endif
+               now._cnt[now._a_t&1] += 1;
+       }
+Q999:
+       if (trpt->o_pm&8)
+       {       now._a_t &= ~2;
+               now._cnt[now._a_t&1] = 0;
+       }
+       if (trpt->o_pm&16)
+               now._a_t |= 2;
+#endif
+CameFromHere:
+       if (memcmp((char *) &now, (char *) &comp_now, vsize) == 0)
+               return depth;
+       if (depth > 0) goto Up;
+       return 0;
+}
+#endif
+static char unwinding;
+void
+uerror(char *str)
+{      static char laststr[256];
+       int is_cycle;
+
+       if (unwinding) return; /* 1.4.2 */
+       if (strncmp(str, laststr, 254))
+#if NCORE>1
+       cpu_printf("pan: %s (at depth %ld)\n", str,
+#else
+       printf("pan: %s (at depth %ld)\n", str,
+#endif
+#if NCORE>1
+               (nr_handoffs * z_handoff) + 
+#endif
+               ((depthfound==-1)?depth:depthfound));
+       strncpy(laststr, str, 254);
+       errors++;
+#ifdef HAS_CODE
+       if (readtrail) { wrap_trail(); return; }
+#endif
+       is_cycle = (strstr(str, " cycle") != (char *) 0);
+       if (!is_cycle)
+       {       depth++; trpt++;
+       }
+       if ((every_error != 0)
+       ||  errors == upto)
+       {
+#if defined(MA) && !defined(SAFETY)
+               if (is_cycle)
+               {       int od = depth;
+                       unwinding = 1;
+                       depthfound = Unwind();
+                       unwinding = 0;
+                       depth = od;
+               }
+#endif
+#if NCORE>1
+               writing_trail = 1;
+#endif
+#ifdef BFS
+               if (depth > 1) trpt--;
+               nuerror(str);
+               if (depth > 1) trpt++;
+#else
+               putrail();
+#endif
+#if defined(MA) && !defined(SAFETY)
+               if (strstr(str, " cycle"))
+               {       if (every_error)
+                       printf("sorry: MA writes 1 trail max\n");
+                       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
+       if (iterative != 0 && maxdepth > 0)
+       {       maxdepth = (iterative == 1)?(depth-1):(depth/2);
+               warned = 1;
+               printf("pan: reducing search depth to %ld\n",
+                       maxdepth);
+       } else
+#endif
+       if (errors >= upto && upto != 0)
+       {
+#if NCORE>1
+               sudden_stop("uerror");
+#endif
+               wrapup();
+       }
+       depthfound = -1;
+}
+
+int
+xrefsrc(int lno, S_F_MAP *mp, int M, int i)
+{      Trans *T; int j, retval=1;
+       for (T = trans[M][i]; T; T = T->nxt)
+       if (T && T->tp)
+       {       if (strcmp(T->tp, ".(goto)") == 0
+               ||  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);
+                               break;
+                       }
+               printf(", state %d", i);
+               if (strcmp(T->tp, "") != 0)
+               {       char *q;
+                       q = transmognify(T->tp);
+                       printf(", \"%s\"", q?q:"");
+               } else if (stopstate[M][i])
+                       printf(", -end state-");
+               printf("\n");
+               retval = 0; /* reported */
+       }
+       return retval;
+}
+
+void
+r_ck(uchar *which, int N, int M, short *src, S_F_MAP *mp)
+{      int i, m=0;
+
+#ifdef VERI
+       if (M == VERI && !verbose) return;
+#endif
+       printf("unreached in proctype %s\n", procname[M]);
+       for (i = 1; i < N; i++)
+         if (which[i] == 0
+         &&  (mapstate[M][i] == 0
+         ||   which[mapstate[M][i]] == 0))
+               m += xrefsrc((int) src[i], mp, M, i);
+         else
+               m++;
+       printf("        (%d of %d states)\n", N-1-m, N-1);
+}
+#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)
+       {       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)
+               {       write(fd, "-1:-1:-1\n", 9);
+       }       }
+}
+#endif
+#endif
+
+void
+putrail(void)
+{      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));
+#endif
+#ifdef MERGED
+       sprintf(snap, "-4:-4:-4\n");
+       write(fd, snap, strlen(snap));
+#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);
+               trl = getframe(i);
+               if (!trl->o_t) continue;
+               if (trl->o_pm&128) continue;
+               sprintf(snap, "%ld:%d:%d\n", 
+                       i, trl->pr, trl->o_t->t_id);
+               j = strlen(snap);
+               if (write(fd, snap, j) != j)
+               {       printf("pan: error writing trailfile\n");
+                       close(fd);
+                       wrapup();
+       }       }
+#endif
+       close(fd);
+#if NCORE>1
+       cpu_printf("pan: wrote trailfile\n");
+#endif
+}
+
+void
+sv_save(void)  /* push state vector onto save stack */
+{      if (!svtack->nxt)
+       {  svtack->nxt = (Svtack *) emalloc(sizeof(Svtack));
+          svtack->nxt->body = emalloc(vsize*sizeof(char));
+          svtack->nxt->lst = svtack;
+          svtack->nxt->m_delta = vsize;
+          svmax++;
+       } else if (vsize > svtack->nxt->m_delta)
+       {  svtack->nxt->body = emalloc(vsize*sizeof(char));
+          svtack->nxt->lst = svtack;
+          svtack->nxt->m_delta = vsize;
+          svmax++;
+       }
+       svtack = svtack->nxt;
+#if SYNC
+       svtack->o_boq = boq;
+#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)
+       c_stack((uchar *) &(svtack->c_stack[0]));
+#endif
+#ifdef DEBUG
+       cpu_printf("%d: sv_save\n", depth);
+#endif
+}
+
+void
+sv_restor(void)        /* pop state vector from save stack */
+{
+       memcpy((char *)&now, svtack->body, svtack->o_delta);
+#if SYNC
+       boq = svtack->o_boq;
+#endif
+#if defined(C_States) && (HAS_TRACK==1)
+#ifdef HAS_STACK
+       c_unstack((uchar *) &(svtack->c_stack[0]));
+#endif
+       c_revert((uchar *) &(now.c_state[0]));
+#endif
+       if (vsize != svtack->o_delta)
+               Uerror("sv_restor");
+       if (!svtack->lst)
+               Uerror("error: v_restor");
+       svtack  = svtack->lst;
+#ifdef DEBUG
+       cpu_printf("    sv_restor\n");
+#endif
+}
+
+void
+p_restor(int h)
+{      int i; char *z = (char *) &now;
+
+       proc_offset[h] = stack->o_offset;
+       proc_skip[h]   = (uchar) stack->o_skip;
+#ifndef XUSAFE
+       p_name[h] = stack->o_name;
+#endif
+#ifndef NOCOMP
+       for (i = vsize + stack->o_skip; i > vsize; i--)
+               Mask[i-1] = 1; /* align */
+#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 (BASE > 0 && h > 0)
+               ((P0 *)pptr(h))->_pid = h-BASE;
+       else
+               ((P0 *)pptr(h))->_pid = h;
+       i = stack->o_delqs;
+       now._nr_pr += 1;
+       if (!stack->lst)        /* debugging */
+               Uerror("error: p_restor");
+       stack = stack->lst;
+       this = pptr(h);
+       while (i-- > 0)
+               q_restor();
+}
+
+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
+       vsize += stack->o_skip;
+       memcpy(z+vsize, stack->body, stack->o_delta);
+       vsize += stack->o_delta;
+#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;
+#endif
+#endif
+       for ( ; k < k_end; k++)
+               Mask[k] = 1;
+#endif
+       if (!stack->lst)        /* debugging */
+               Uerror("error: q_restor");
+       stack = stack->lst;
+}
+typedef struct IntChunks {
+       int     *ptr;
+       struct  IntChunks *nxt;
+} IntChunks;
+IntChunks *filled_chunks[512];
+IntChunks *empty_chunks[512];
+int *
+grab_ints(int nr)
+{      IntChunks *z;
+       if (nr >= 512) Uerror("cannot happen grab_int");
+       if (filled_chunks[nr])
+       {       z = filled_chunks[nr];
+               filled_chunks[nr] = filled_chunks[nr]->nxt;
+       } else 
+       {       z = (IntChunks *) emalloc(sizeof(IntChunks));
+               z->ptr = (int *) emalloc(nr * sizeof(int));
+       }
+       z->nxt = empty_chunks[nr];
+       empty_chunks[nr] = z;
+       return z->ptr;
+}
+void
+ungrab_ints(int *p, int nr)
+{      IntChunks *z;
+       if (!empty_chunks[nr]) Uerror("cannot happen ungrab_int");
+       z = empty_chunks[nr];
+       empty_chunks[nr] = empty_chunks[nr]->nxt;
+       z->ptr = p;
+       z->nxt = filled_chunks[nr];
+       filled_chunks[nr] = z;
+}
+int
+delproc(int sav, int h)
+{      int d, i=0;
+#ifndef NOCOMP
+       int o_vsize = vsize;
+#endif
+       if (h+1 != (int) now._nr_pr) return 0;
+
+       while (now._nr_qs
+       &&     q_offset[now._nr_qs-1] > proc_offset[h])
+       {       delq(sav);
+               i++;
+       }
+       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->lst = stack;
+                       smax++;
+               }
+               stack = stack->nxt;
+               stack->o_offset = proc_offset[h];
+#if VECTORSZ>32000
+               stack->o_skip   = (int) proc_skip[h];
+#else
+               stack->o_skip   = (short) proc_skip[h];
+#endif
+#ifndef XUSAFE
+               stack->o_name   = p_name[h];
+#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;
+       memset((char *)pptr(h), 0, d);
+       vsize -= (int) proc_skip[h];
+#ifndef NOVSZ
+       now._vsz = vsize;
+#endif
+#ifndef NOCOMP
+       for (i = vsize; i < o_vsize; i++)
+               Mask[i] = 0; /* reset */
+#endif
+       return 1;
+}
+
+void
+delq(int sav)
+{      int h = now._nr_qs - 1;
+       int d = vsize - q_offset[now._nr_qs - 1];
+#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->lst = stack;
+                       smax++;
+               }
+               stack = stack->nxt;
+               stack->o_offset = q_offset[h];
+#if VECTORSZ>32000
+               stack->o_skip   = (int) q_skip[h];
+#else
+               stack->o_skip   = (short) q_skip[h];
+#endif
+#ifndef XUSAFE
+               stack->o_name   = q_name[h];
+#endif
+               stack->o_delta  = d;
+               memcpy(stack->body, (char *)qptr(h), d);
+       }
+       vsize = q_offset[h];
+       now._nr_qs = now._nr_qs - 1;
+       memset((char *)qptr(h), 0, d);
+       vsize -= (int) q_skip[h];
+#ifndef NOVSZ
+       now._vsz = vsize;
+#endif
+#ifndef NOCOMP
+       for (k = vsize; k < o_vsize; k++)
+               Mask[k] = 0; /* reset */
+#endif
+}
+
+int
+qs_empty(void)
+{      int i;
+       for (i = 0; i < (int) now._nr_qs; i++)
+       {       if (q_sz(i) > 0)
+                       return 0;
+       }
+       return 1;
+}
+
+int
+endstate(void)
+{      int i; P0 *ptr;
+       for (i = BASE; i < (int) now._nr_pr; i++)
+       {       ptr = (P0 *) pptr(i);
+               if (!stopstate[ptr->_t][ptr->_p])
+                       return 0;
+       }
+       if (strict) return qs_empty();
+#if defined(EVENT_TRACE) && !defined(OTIM)
+       if (!stopstate[EVENT_TRACE][now._event] && !a_cycles)
+       {       printf("pan: event_trace not completed\n");
+               return 0;
+       }
+#endif
+       return 1;
+}
+
+#ifndef SAFETY
+void
+checkcycles(void)
+{      uchar o_a_t = now._a_t;
+#ifdef SCHED
+       int o_limit;
+#endif
+#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
+       now._a_t |= (1|16|32);
+       /* 1 = 2nd DFS; (16|32) to help hasher */
+#ifndef NOFAIR
+       now._cnt[1] = now._cnt[0];
+#endif
+       memcpy((char *)&A_Root, (char *)&now, vsize);
+       A_depth = depthfound = depth;
+#if NCORE>1
+       mem_put_acc();
+#else
+       #ifdef SCHED
+       o_limit = trpt->sched_limit;
+       trpt->sched_limit = 0;
+       #endif
+       new_state();    /* start 2nd DFS */
+       #ifdef SCHED
+       trpt->sched_limit = o_limit;
+       #endif
+#endif
+       now._a_t = o_a_t;
+#ifndef NOFAIR
+       now._cnt[1] = o_cnt;
+#endif
+       A_depth = 0; depthfound = -1;
+#ifdef DEBUG
+       printf("%d: cycle check returns\n", depth);
+#endif
+#ifdef FULLSTACK
+#ifndef MA
+       trpt->ostate = sv;      /* restore */
+#else
+       trpt->proviso = prov;
+#endif
+#endif
+}
+#endif
+
+#if defined(FULLSTACK) && defined(BITSTATE)
+struct H_el *Free_list = (struct 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 *));
+}
+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;
+               if (v && ((int) v->tagged >= n))
+                       goto gotcha;
+               ngrabs++;
+       }
+       return (struct H_el *)
+             emalloc(sizeof(struct H_el)+n-sizeof(unsigned));
+}
+
+#else
+#if NCORE>1
+struct H_el *
+grab_state(int n)
+{      struct H_el *grab_shared(int);
+       return grab_shared(sizeof(struct H_el)+n-sizeof(unsigned));
+}
+#else
+ #ifndef AUTO_RESIZE
+  #define grab_state(n) (struct H_el *) \
+               emalloc(sizeof(struct H_el)+n-sizeof(unsigned long));
+ #else
+  struct H_el *
+  grab_state(int n)
+  {    struct H_el *p;
+       int cnt = sizeof(struct H_el)+n-sizeof(unsigned long);
+
+       if (reclaim_size >= cnt+WS)
+       {       if ((cnt & (WS-1)) != 0) /* alignment */
+               {       cnt += WS - (cnt & (WS-1));
+               }
+               p = (struct H_el *) reclaim_mem;
+               reclaim_mem  += cnt;
+               reclaim_size -= cnt;
+               memset(p, 0, cnt);
+       } else
+       {       p = (struct H_el *) emalloc(cnt);
+       }
+       return p;
+  }
+ #endif
+#endif
+#endif
+#ifdef COLLAPSE
+unsigned long
+ordinal(char *v, long n, short tp)
+{      struct H_el *tmp, *ntmp; long m;
+       struct H_el *olst = (struct H_el *) 0;
+       s_hash((uchar *)v, n);
+#if NCORE>1 && !defined(SEP_STATE)
+       enter_critical(CS_ID);  /* uses spinlock - 1..128 */
+#endif
+       tmp = H_tab[j1];
+       if (!tmp)
+       {       tmp = grab_state(n);
+               H_tab[j1] = tmp;
+       } else
+       for ( ;; olst = tmp, tmp = tmp->nxt)
+       {       m = memcmp(((char *)&(tmp->state)), v, n);
+               if (n == tmp->ln)
+               {
+                       if (m == 0)
+                               goto done;
+                       if (m < 0)
+                       {
+Insert:                        ntmp = grab_state(n);
+                               ntmp->nxt = tmp;
+                               if (!olst)
+                                       H_tab[j1] = ntmp;
+                               else
+                                       olst->nxt = ntmp;
+                               tmp = ntmp;
+                               break;
+                       } else if (!tmp->nxt)
+                       {
+Append:                        tmp->nxt = grab_state(n);
+                               tmp = tmp->nxt;
+                               break;
+                       }
+                       continue;
+               }
+               if (n < tmp->ln)
+                       goto Insert;
+               else if (!tmp->nxt)
+                       goto Append;
+       }
+       m = ++ncomps[tp];
+#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);  /* uses spinlock */
+#endif
+#ifdef FULLSTACK
+       return tmp->tagged;
+#else
+       return tmp->st_id;
+#endif
+}
+
+int
+compress(char *vin, int nin)   /* collapse compression */
+{      char    *w, *v = (char *) &comp_now;
+       int     i, j;
+       unsigned long   n;
+       static char     *x;
+       static uchar    nbytes[513]; /* 1 + 256 + 256 */
+       static unsigned short nbytelen;
+       long col_q(int, char *);
+       long col_p(int, char *);
+#ifndef SAFETY
+       if (a_cycles)
+               *v++ = now._a_t;
+#ifndef NOFAIR
+       if (fairness)
+       for (i = 0; i < NFAIR; i++)
+               *v++ = now._cnt[i];
+#endif
+#endif
+       nbytelen = 0;
+#ifndef JOINPROCS
+       for (i = 0; i < (int) now._nr_pr; i++)
+       {       n = col_p(i, (char *) 0);
+#ifdef NOFIX
+               nbytes[nbytelen] = 0;
+#else
+               nbytes[nbytelen] = 1;
+               *v++ = ((P0 *) pptr(i))->_t;
+#endif
+               *v++ = n&255;
+               if (n >= (1<<8))
+               {       nbytes[nbytelen]++;
+                       *v++ = (n>>8)&255;
+               }
+               if (n >= (1<<16))
+               {       nbytes[nbytelen]++;
+                       *v++ = (n>>16)&255;
+               }
+               if (n >= (1<<24))
+               {       nbytes[nbytelen]++;
+                       *v++ = (n>>24)&255;
+               }
+               nbytelen++;
+       }
+#else
+       x = scratch;
+       for (i = 0; i < (int) now._nr_pr; i++)
+               x += col_p(i, x);
+       n = ordinal(scratch, x-scratch, 2); /* procs */
+       *v++ = n&255;
+       nbytes[nbytelen] = 0;
+       if (n >= (1<<8))
+       {       nbytes[nbytelen]++;
+               *v++ = (n>>8)&255;
+       }
+       if (n >= (1<<16))
+       {       nbytes[nbytelen]++;
+               *v++ = (n>>16)&255;
+       }
+       if (n >= (1<<24))
+       {       nbytes[nbytelen]++;
+               *v++ = (n>>24)&255;
+       }
+       nbytelen++;
+#endif
+#ifdef SEPQS
+       for (i = 0; i < (int) now._nr_qs; i++)
+       {       n = col_q(i, (char *) 0);
+               nbytes[nbytelen] = 0;
+               *v++ = n&255;
+               if (n >= (1<<8))
+               {       nbytes[nbytelen]++;
+                       *v++ = (n>>8)&255;
+               }
+               if (n >= (1<<16))
+               {       nbytes[nbytelen]++;
+                       *v++ = (n>>16)&255;
+               }
+               if (n >= (1<<24))
+               {       nbytes[nbytelen]++;
+                       *v++ = (n>>24)&255;
+               }
+               nbytelen++;
+       }
+#endif
+#ifdef NOVSZ
+       /* 3 = _a_t, _nr_pr, _nr_qs */
+       w = (char *) &now + 3 * sizeof(uchar);
+#ifndef NOFAIR
+       w += NFAIR;
+#endif
+#else
+#if VECTORSZ<65536
+       w = (char *) &(now._vsz) + sizeof(unsigned short);
+#else
+       w = (char *) &(now._vsz) + sizeof(unsigned long);
+#endif
+#endif
+       x = scratch;
+       *x++ = now._nr_pr;
+       *x++ = now._nr_qs;
+       if (now._nr_qs > 0 && qptr(0) < pptr(0))
+               n = qptr(0) - (uchar *) w;
+       else
+               n = pptr(0) - (uchar *) w;
+       j = w - (char *) &now;
+       for (i = 0; i < (int) n; i++, w++)
+               if (!Mask[j++]) *x++ = *w;
+#ifndef SEPQS
+       for (i = 0; i < (int) now._nr_qs; i++)
+               x += col_q(i, x);
+#endif
+       x--;
+       for (i = 0, j = 6; i < nbytelen; i++)
+       {       if (j == 6)
+               {       j = 0;
+                       *(++x) = 0;
+               } else
+                       j += 2;
+               *x |= (nbytes[i] << j);
+       }
+       x++;
+       for (j = 0; j < WS-1; j++)
+               *x++ = 0;
+       x -= j; j = 0;
+       n = ordinal(scratch, x-scratch, 0); /* globals */
+       *v++ = n&255;
+       if (n >= (1<< 8)) { *v++ = (n>> 8)&255; j++; }
+       if (n >= (1<<16)) { *v++ = (n>>16)&255; j++; }
+       if (n >= (1<<24)) { *v++ = (n>>24)&255; j++; }
+       *v++ = j;       /* add last count as a byte */
+       for (i = 0; i < WS-1; i++)
+               *v++ = 0;
+       v -= i;
+#if 0
+       printf("collapse %d -> %d\n",
+               vsize, v - (char *)&comp_now);
+#endif
+       return v - (char *)&comp_now;
+}
+#else
+#if !defined(NOCOMP)
+int
+compress(char *vin, int n)     /* default compression */
+{
+#ifdef HC
+       int delta = 0;
+       s_hash((uchar *)vin, n); /* sets K1 and K2 */
+#ifndef SAFETY
+       if (S_A)
+       {       delta++;        /* _a_t  */
+#ifndef NOFAIR
+               if (S_A > NFAIR)
+                       delta += NFAIR; /* _cnt[] */
+#endif
+       }
+#endif
+       memcpy((char *) &comp_now + delta, (char *) &K1, WS);
+       delta += WS;
+#if HC>0
+       memcpy((char *) &comp_now + delta, (char *) &K2, HC);
+       delta += HC;
+#endif
+       return delta;
+#else
+       char *vv = vin;
+       char *v = (char *) &comp_now;
+       int i;
+  #ifndef NO_FAST_C
+       int r = 0, unroll = n/8;
+       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;
+               }
+               r = (n+WS-1)/WS; /* words rounded up */
+               r *= WS;         /* bytes */
+               i = r - i;       /* remainder */
+               switch (i) {
+               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);
+#endif
+       return v - (char *)&comp_now;
+#endif
+}
+#endif
+#endif
+#if defined(FULLSTACK) && defined(BITSTATE)
+#if defined(MA)
+#if !defined(onstack_now)
+int  onstack_now(void) {}
+#endif
+#if !defined(onstack_put)
+void onstack_put(void) {}
+#endif
+#if !defined(onstack_zap)
+void onstack_zap(void) {}
+#endif
+#else
+void
+onstack_zap(void)
+{      struct H_el *v, *w, *last = 0;
+       struct H_el **tmp = H_tab;
+       char *nv; int n, m;
+
+       static char warned = 0;
+
+       H_tab = S_Tab;
+#ifndef NOCOMP
+       nv = (char *) &comp_now;
+       n = compress((char *)&now, vsize);
+#else
+#if defined(BITSTATE) && defined(LC)
+       nv = (char *) &comp_now;
+       n = compact_stack((char *)&now, vsize);
+#else
+       nv = (char *) &now;
+       n = vsize;
+#endif
+#endif
+#if !defined(HC) && !(defined(BITSTATE) && defined(LC))
+       s_hash((uchar *)nv, n);
+#endif
+       H_tab = tmp;
+       for (v = S_Tab[j1]; v; Zh++, last=v, v=v->nxt)
+       {       m = memcmp(&(v->state), nv, n);
+               if (m == 0)
+                       goto Found;
+               if (m < 0)
+                       break;
+       }
+/* NotFound: */
+#ifndef ZAPH
+       #if defined(BITSTATE) && NCORE>1
+       /* seen this happen, likely harmless, but not yet understood */
+       if (warned == 0)
+       #endif
+       {       /* Uerror("stack out of wack - zap"); */
+               cpu_printf("pan: warning, stack incomplete\n");
+               warned = 1;
+       }
+#endif
+       return;
+Found:
+       ZAPS++;
+       if (last)
+               last->nxt = v->nxt;
+       else
+               S_Tab[j1] = v->nxt;
+       v->tagged = (unsigned) n;
+#if !defined(NOREDUCE) && !defined(SAFETY)
+       v->proviso = 0;
+#endif
+       v->nxt = last = (struct H_el *) 0;
+       for (w = Free_list; w; Fa++, last=w, w = w->nxt)
+       {       if ((int) w->tagged <= n)
+               {       if (last)
+                       {       v->nxt = w;
+                               last->nxt = v;
+                       } else
+                       {       v->nxt = Free_list;
+                               Free_list = v;
+                       }
+                       return;
+               }
+               if (!w->nxt)
+               {       w->nxt = v;
+                       return;
+       }       }
+       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
+       #ifndef ZAPH
+               Uerror("cannot happen - unstack_put");
+       #endif
+#endif
+       H_tab = tmp;
+       trpt->ostate = Lstate;
+       PUT++;
+}
+int
+onstack_now(void)
+{      struct H_el *tmp;
+       struct H_el **tmp2 = H_tab;
+       char *v; int n, m = 1;
+
+       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 BITSTATE
+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(unsigned long);
+               init_HT(0L);
+       }
+#endif
+#endif
+  #endif
+  #if !defined(MA) || defined(COLLAPSE)
+#if NCORE>1
+       if (!readtrail)
+       {       void init_HT(unsigned long);
+               init_HT((unsigned long) (ONE_L<<ssize)*sizeof(struct H_el *));
+       } else
+#endif
+       H_tab = (struct H_el **)
+               emalloc((ONE_L<<ssize)*sizeof(struct H_el *));
+  #endif
+}
+#endif
+
+#if !defined(BITSTATE) || defined(FULLSTACK)
+#ifdef DEBUG
+void
+dumpstate(int wasnew, char *v, int n, int tag)
+{      int i;
+#ifndef SAFETY
+       if (S_A)
+       {       printf("        state tags %d (%d::%d): ",
+                       V_A, wasnew, v[0]);
+#ifdef FULLSTACK
+               printf(" %d ", tag);
+#endif
+               printf("\n");
+       }
+#endif
+#ifdef SDUMP
+#ifndef NOCOMP
+       printf("         State: ");
+       for (i = 0; i < vsize; i++) printf("%d%s,",
+               ((char *)&now)[i], Mask[i]?"*":"");
+#endif
+       printf("\n      Vector: ");
+       for (i = 0; i < n; i++) printf("%d,", v[i]);
+       printf("\n");
+#endif
+}
+#endif
+#ifdef MA
+int
+gstore(char *vin, int nin, uchar pbit)
+{      int n, i;
+       int ret_val = 1;
+       uchar *v;
+       static uchar Info[MA+1];
+#ifndef NOCOMP
+       n = compress(vin, nin);
+       v = (uchar *) &comp_now;
+#else
+       n = nin;
+       v = vin;
+#endif
+       if (n >= MA)
+       {       printf("pan: error, MA too small, recompile pan.c");
+               printf(" with -DMA=N with N>%d\n", n);
+               Uerror("aborting");
+       }
+       if (n > (int) maxgs)
+       {       maxgs = (unsigned int) n;
+       }
+       for (i = 0; i < n; i++)
+       {       Info[i] = v[i];
+       }
+       for ( ; i < MA-1; i++)
+       {       Info[i] = 0;
+       }
+       Info[MA-1] = pbit;
+       if (a_cycles)   /* place _a_t at the end */
+       {       Info[MA] = Info[0];
+               Info[0]  = 0;
+       }
+
+#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)
+               &&  depth > A_depth)
+               {       Info[MA] &= ~(1|16|32); /* _a_t */
+                       if (dfa_member(MA))
+                       {       Info[MA-1] = 4; /* off-stack bit */
+                               nShadow++;
+                               if (!dfa_member(MA-1))
+                               {       ret_val = 3;
+                       #ifdef VERBOSE
+                                       printf("intersected 1st dfs stack\n");
+                       #endif
+                                       goto done;
+               }       }       }
+               ret_val = 0;
+       #ifdef VERBOSE
+               printf("new state\n");
+       #endif
+               goto done;
+       }
+#ifdef FULLSTACK
+       if (pbit == 0)
+       {       Info[MA-1] = 1; /* proviso bit */
+#ifndef BFS
+               trpt->proviso = dfa_member(MA-1);
+#endif
+               Info[MA-1] = 4; /* off-stack bit */
+               if (dfa_member(MA-1))
+               {       ret_val = 1; /* off-stack */
+       #ifdef VERBOSE
+                       printf("old state\n");
+       #endif
+               } else
+               {       ret_val = 2; /* on-stack */
+       #ifdef VERBOSE
+                       printf("on-stack\n");
+       #endif
+               }
+               goto done;
+       }
+#endif
+       ret_val = 1;
+#ifdef VERBOSE
+       printf("old state\n");
+#endif
+done:
+#if NCORE>1 && !defined(SEP_STATE)
+       leave_critical(GLOBAL_LOCK);
+#endif
+       return ret_val; /* old state */
+}
+#endif
+#if defined(BITSTATE) && defined(LC)
+int
+compact_stack(char *vin, int n)
+{      int delta = 0;
+       s_hash((uchar *)vin, n); /* sets K1 and K2 */
+#ifndef SAFETY
+       delta++;        /* room for state[0] |= 128 */
+#endif
+       memcpy((char *) &comp_now + delta, (char *) &K1, WS);
+       delta += WS;
+       memcpy((char *) &comp_now + delta, (char *) &K2, WS);
+       delta += WS; /* use all available bits */
+       return delta;
+}
+#endif
+int
+hstore(char *vin, int nin)     /* hash table storage */
+{      struct H_el *ntmp;
+       struct H_el *tmp, *olst = (struct H_el *) 0;
+       char *v; int n, m=0;
+#ifdef HC
+       uchar rem_a;
+#endif
+#ifdef NOCOMP
+#if defined(BITSTATE) && defined(LC)
+       if (S_Tab == H_tab)
+       {       v = (char *) &comp_now;
+               n = compact_stack(vin, nin);
+       } else
+       {       v = vin; n = nin;
+       }
+#else
+       v = vin; n = nin;
+#endif
+#else
+       v = (char *) &comp_now;
+       #ifdef HC
+       rem_a = now._a_t;
+       now._a_t = 0;
+       #endif
+       n = compress(vin, nin);
+       #ifdef HC
+       now._a_t = rem_a;
+       #endif
+#ifndef SAFETY
+       if (S_A)
+       {       v[0] = 0;       /* _a_t  */
+#ifndef NOFAIR
+               if (S_A > NFAIR)
+               for (m = 0; m < NFAIR; m++)
+                       v[m+1] = 0;     /* _cnt[] */
+#endif
+               m = 0;
+       }
+       #endif
+#endif
+#if !defined(HC) && !(defined(BITSTATE) && defined(LC))
+       s_hash((uchar *)v, n);
+#endif
+#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)
+       enter_critical(CS_ID);  /* uses spinlock */
+#endif
+       tmp = H_tab[j1];
+       if (!tmp)
+       {  tmp = grab_state(n);
+#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] = tmp;
+       } else
+       {  for (;; hcmp++, olst = tmp, tmp = tmp->nxt)
+          {   /* skip the _a_t and the _cnt bytes */
+#ifdef COLLAPSE
+               if (tmp->ln != 0)
+               {       if (!tmp->nxt) goto Append;
+                       continue;
+               }
+#endif
+               m = memcmp(((char *)&(tmp->state)) + S_A, 
+                       v + S_A, n - S_A);
+               if (m == 0) {
+#ifdef SAFETY
+#define wasnew 0
+#else
+               int wasnew = 0;
+#endif
+#ifndef SAFETY
+#ifndef NOCOMP
+               if (S_A)
+               { if ((((char *)&(tmp->state))[0] & V_A) != V_A)
+                 {     wasnew = 1; nShadow++;
+                       ((char *)&(tmp->state))[0] |= V_A;
+                 }
+#ifndef NOFAIR
+                 if (S_A > NFAIR)
+                 {     /* 0 <= now._cnt[now._a_t&1] < MAXPROC */
+                       unsigned 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 */
+                       {       ci = (NFAIR - 1) - ci;
+                               bp = 7 - bp; /* bp = 0..7 */
+                       }
+                       ci++;   /* skip over _a_t */
+                       bp = 1 << bp;   /* the bit mask */
+                       if ((((char *)&(tmp->state))[ci] & bp)==0)
+                       {       if (!wasnew)
+                               {       wasnew = 1;
+                                       nShadow++;
+                               }
+                               ((char *)&(tmp->state))[ci] |= bp;
+                       }
+                  }
+                  /* else: wasnew == 0, i.e., old state */
+#endif
+               }
+#endif
+#endif
+#if NCORE>1
+               Lstate = (struct H_el *) tmp;
+#endif
+#ifdef FULLSTACK
+#ifndef SAFETY
+               if (wasnew)
+               {       Lstate = (struct H_el *) tmp;
+                       tmp->tagged |= V_A;
+                       if ((now._a_t&1)
+                       && (tmp->tagged&A_V)
+                       && depth > A_depth)
+                       {
+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 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("        New state %d+\n", (int) tmp->st_id);
+#endif
+#ifdef DEBUG
+       dumpstate(1, (char *)&(tmp->state),n,tmp->tagged);
+#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;
+#ifndef SAFETY
+                       /* already on current dfs stack */
+                       /* but may also be on 1st dfs stack */
+                       if ((now._a_t&1)
+                       && (tmp->tagged&A_V)
+                       && depth > A_depth
+#ifndef NOFAIR
+                       && (!fairness || now._cnt[1] <= 1)
+#endif
+                       )
+                               goto intersect;
+#endif
+#ifdef CHECK
+#if NCORE>1
+       printf("cpu%d: ", core_id);
+#endif
+       printf("        Stack state %d\n", (int) tmp->st_id);
+#endif
+#ifdef DEBUG
+       dumpstate(0, (char *)&(tmp->state),n,tmp->tagged);
+#endif
+#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)
+                       leave_critical(CS_ID);
+#endif
+                       return 2; /* match on stack */
+               }
+#else
+               if (wasnew)
+               {
+#ifdef CHECK
+#if NCORE>1
+       printf("cpu%d: ", core_id);
+#endif
+       printf("        New state %d+\n", (int) tmp->st_id);
+#endif
+#ifdef DEBUG
+       dumpstate(1, (char *)&(tmp->state), n, 0);
+#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("        Old 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
+#if NCORE>1
+       printf("cpu%d: ", core_id);
+#endif
+       printf("                ReVisiting (from smaller depth)\n");
+#endif
+                       nstates--;
+#if NCORE>1 && !defined(SEP_STATE) && !defined(BITSTATE)
+                       leave_critical(CS_ID);
+#endif
+                       return 0;
+               }
+#endif
+#if (defined(BFS) && defined(Q_PROVISO)) || NCORE>1
+               Lstate = (struct H_el *) tmp;
+#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;
+                       else
+                               olst->nxt = ntmp;
+                       tmp = ntmp;
+                       break;
+              } else if (!tmp->nxt)
+              {        /* append after tmp */
+#ifdef COLLAPSE
+Append:
+#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
+       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
+       printf("        New state %d\n", (int) nstates);
+#endif
+#endif
+#if !defined(SAFETY) || defined(REACH)
+       tmp->D = depth;
+#endif
+#ifndef SAFETY
+#ifndef NOCOMP
+       if (S_A)
+       {       v[0] = V_A;
+#ifndef NOFAIR
+               if (S_A > NFAIR)
+               {       unsigned 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)
+                       {       ci = (NFAIR - 1) - ci;
+                               bp = 7 - bp; /* bp = 0..7 */
+                       }
+                       v[1+ci] = 1 << bp;
+               }
+#endif
+       }
+#endif
+#endif
+#if defined(AUTO_RESIZE) && !defined(BITSTATE)
+       tmp->m_K1 = K1;
+#endif
+       memcpy(((char *)&(tmp->state)), v, n);
+#ifdef FULLSTACK
+       tmp->tagged = (S_A)?V_A:(depth+1);
+#ifdef DEBUG
+               dumpstate(-1, v, n, tmp->tagged);
+#endif
+       Lstate = (struct H_el *) tmp;
+#else
+       #ifdef DEBUG
+               dumpstate(-1, v, n, 0);
+       #endif
+       #if NCORE>1
+               Lstate = (struct H_el *) tmp;
+       #endif
+#endif
+/* #if NCORE>1 && !defined(SEP_STATE) */
+#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;
+}
+#endif
+#include TRANSITIONS
+void
+do_reach(void)
+{
+       r_ck(reached0, nstates0, 0, src_ln0, src_file0);
+       r_ck(reached1, nstates1, 1, src_ln1, src_file1);
+       r_ck(reached2, nstates2, 2, src_ln2, src_file2);
+       r_ck(reached3, nstates3, 3, src_ln3, src_file3);
+       r_ck(reached4, nstates4, 4, src_ln4, src_file4);
+}
+
+void
+iniglobals(void)
+{
+               deliver = 0;
+       {       int l_in;
+               for (l_in = 0; l_in < 4; l_in++)
+               {
+                       now.buffer_use[l_in] = 0;
+               }
+       }
+               now.write_off = 0;
+       {       int l_in;
+               for (l_in = 0; l_in < 2; l_in++)
+               {
+                       now.commit_count[l_in] = 0;
+               }
+       }
+               now.read_off = 0;
+       {       int l_in;
+               for (l_in = 0; l_in < 2; l_in++)
+               {
+                       now.retrieve_count[l_in] = 0;
+               }
+       }
+               now.events_lost = 0;
+               now.refcount = 0;
+#ifdef VAR_RANGES
+       {       int l_in;
+               for (l_in = 0; l_in < 4; l_in++)
+               {
+                       logval("buffer_use[l_in]", now.buffer_use[l_in]);
+               }
+       }
+               logval("write_off", now.write_off);
+       {       int l_in;
+               for (l_in = 0; l_in < 2; l_in++)
+               {
+                       logval("commit_count[l_in]", now.commit_count[l_in]);
+               }
+       }
+               logval("read_off", now.read_off);
+       {       int l_in;
+               for (l_in = 0; l_in < 2; l_in++)
+               {
+                       logval("retrieve_count[l_in]", now.retrieve_count[l_in]);
+               }
+       }
+               logval("events_lost", now.events_lost);
+               logval("refcount", now.refcount);
+#endif
+       Maxbody = max(Maxbody, sizeof(State)-VECTORSZ);
+}
+
+int
+addqueue(int n, int is_rv)
+{      int j=0, i = now._nr_qs;
+#ifndef NOCOMP
+       int k;
+#endif
+       if (i >= MAXQ)
+               Uerror("too many queues");
+       switch (n) {
+       default: Uerror("bad queue - addqueue");
+       }
+       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
+       vsize += (int) q_skip[i];
+       q_offset[i] = vsize;
+       now._nr_qs += 1;
+       vsize += j;
+#ifndef NOVSZ
+       now._vsz = vsize;
+#endif
+       hmax = max(hmax, vsize);
+       if (vsize >= VECTORSZ)
+               Uerror("VECTORSZ is too small, edit pan.h");
+       memset((char *)qptr(i), 0, j);
+       ((Q0 *)qptr(i))->_t = n;
+       return i+1;
+}
+
+#if NQS>0
+void
+qsend(int into, int sorted, int args_given)
+{      int j; uchar *z;
+
+#ifdef HAS_SORTED
+       int k;
+#endif
+       if (!into--)
+       uerror("ref to uninitialized chan name (sending)");
+       if (into >= (int) now._nr_qs || into < 0)
+               Uerror("qsend bad queue#");
+       z = qptr(into);
+       j = ((Q0 *)qptr(into))->Qlen;
+       switch (((Q0 *)qptr(into))->_t) {
+       case 0: printf("queue %d was deleted\n", into+1);
+       default: Uerror("bad queue - qsend");
+       }
+#ifdef EVENT_TRACE
+       if (in_s_scope(into+1))
+               require('s', into);
+#endif
+}
+#endif
+
+#if SYNC
+int
+q_zero(int from)
+{      if (!from--)
+       {       uerror("ref to uninitialized chan name (q_zero)");
+               return 0;
+       }
+       switch(((Q0 *)qptr(from))->_t) {
+       case 0: printf("queue %d was deleted\n", from+1);
+       }
+       Uerror("bad queue q-zero");
+       return -1;
+}
+int
+not_RV(int from)
+{      if (q_zero(from))
+       {       printf("==>> a test of the contents of a rv ");
+               printf("channel always returns FALSE\n");
+               uerror("error to poll rendezvous channel");
+       }
+       return 1;
+}
+#endif
+#ifndef XUSAFE
+void
+setq_claim(int x, int m, char *s, int y, char *p)
+{      if (x == 0)
+       uerror("x[rs] claim on uninitialized channel");
+       if (x < 0 || x > MAXQ)
+               Uerror("cannot happen setq_claim");
+       q_claim[x] |= m;
+       p_name[y] = p;
+       q_name[x] = s;
+       if (m&2) q_S_check(x, y);
+       if (m&1) q_R_check(x, y);
+}
+short q_sender[MAXQ+1];
+int
+q_S_check(int x, int who)
+{      if (!q_sender[x])
+       {       q_sender[x] = who+1;
+#if SYNC
+               if (q_zero(x))
+               {       printf("chan %s (%d), ",
+                               q_name[x], x-1);
+                       printf("sndr proc %s (%d)\n",
+                               p_name[who], who);
+                       uerror("xs chans cannot be used for rv");
+               }
+#endif
+       } else
+       if (q_sender[x] != who+1)
+       {       printf("pan: xs assertion violated: ");
+               printf("access to chan <%s> (%d)\npan: by ",
+                       q_name[x], x-1);
+               if (q_sender[x] > 0 && p_name[q_sender[x]-1])
+                       printf("%s (proc %d) and by ",
+                       p_name[q_sender[x]-1], q_sender[x]-1);
+               printf("%s (proc %d)\n",
+                       p_name[who], who);
+               uerror("error, partial order reduction invalid");
+       }
+       return 1;
+}
+short q_recver[MAXQ+1];
+int
+q_R_check(int x, int who)
+{      if (!q_recver[x])
+       {       q_recver[x] = who+1;
+#if SYNC
+               if (q_zero(x))
+               {       printf("chan %s (%d), ",
+                               q_name[x], x-1);
+                       printf("recv proc %s (%d)\n",
+                               p_name[who], who);
+                       uerror("xr chans cannot be used for rv");
+               }
+#endif
+       } else
+       if (q_recver[x] != who+1)
+       {       printf("pan: xr assertion violated: ");
+               printf("access to chan %s (%d)\npan: ",
+                       q_name[x], x-1);
+               if (q_recver[x] > 0 && p_name[q_recver[x]-1])
+                       printf("by %s (proc %d) and ",
+                       p_name[q_recver[x]-1], q_recver[x]-1);
+               printf("by %s (proc %d)\n",
+                       p_name[who], who);
+               uerror("error, partial order reduction invalid");
+       }
+       return 1;
+}
+#endif
+int
+q_len(int x)
+{      if (!x--)
+       uerror("ref to uninitialized chan name (len)");
+       return ((Q0 *)qptr(x))->Qlen;
+}
+
+int
+q_full(int from)
+{      if (!from--)
+       uerror("ref to uninitialized chan name (qfull)");
+       switch(((Q0 *)qptr(from))->_t) {
+       case 0: printf("queue %d was deleted\n", from+1);
+       }
+       Uerror("bad queue - q_full");
+       return 0;
+}
+
+#ifdef HAS_UNLESS
+int
+q_e_f(int from)
+{      /* empty or full */
+       return !q_len(from) || q_full(from);
+}
+#endif
+#if NQS>0
+int
+qrecv(int from, int slot, int fld, int done)
+{      uchar *z;
+       int j, k, r=0;
+
+       if (!from--)
+       uerror("ref to uninitialized chan name (receiving)");
+       if (from >= (int) now._nr_qs || from < 0)
+               Uerror("qrecv bad queue#");
+       z = qptr(from);
+#ifdef EVENT_TRACE
+       if (done && (in_r_scope(from+1)))
+               require('r', from);
+#endif
+       switch (((Q0 *)qptr(from))->_t) {
+       case 0: printf("queue %d was deleted\n", from+1);
+       default: Uerror("bad queue - qrecv");
+       }
+       return r;
+}
+#endif
+
+#ifndef BITSTATE
+#ifdef COLLAPSE
+long
+col_q(int i, char *z)
+{      int j=0, k;
+       char *x, *y;
+       Q0 *ptr = (Q0 *) qptr(i);
+       switch (ptr->_t) {
+       default: Uerror("bad qtype - collapse");
+       }
+       if (z) x = z; else x = scratch;
+       y = (char *) ptr; k = q_offset[i];
+       /* no need to store the empty slots at the end */
+       j -= (q_max[ptr->_t] - ptr->Qlen) * ((j - 2)/q_max[ptr->_t]);
+       for ( ; j > 0; j--, y++)
+               if (!Mask[k++]) *x++ = *y;
+       for (j = 0; j < WS-1; j++)
+               *x++ = 0;
+       x -= j;
+       if (z) return (long) (x - z);
+       return ordinal(scratch, x-scratch, 1); /* chan */
+}
+#endif
+#endif
+int 
+unsend(int into)
+{      int _m=0, j; uchar *z;
+
+#ifdef HAS_SORTED
+       int k;
+#endif
+       if (!into--)
+               uerror("ref to uninitialized chan (unsend)");
+       z = qptr(into);
+       j = ((Q0 *)z)->Qlen;
+       ((Q0 *)z)->Qlen = --j;
+       switch (((Q0 *)qptr(into))->_t) {
+       default: Uerror("bad queue - unsend");
+       }
+       return _m;
+}
+
+void
+unrecv(int from, int slot, int fld, int fldvar, int strt)
+{      int j; uchar *z;
+
+       if (!from--)
+               uerror("ref to uninitialized chan (unrecv)");
+       z = qptr(from);
+       j = ((Q0 *)z)->Qlen;
+       if (strt) ((Q0 *)z)->Qlen = j+1;
+       switch (((Q0 *)qptr(from))->_t) {
+       default: Uerror("bad queue - qrecv");
+       }
+}
+int
+q_cond(short II, Trans *t)
+{      int i = 0;
+       for (i = 0; i < 6; i++)
+       {       if (t->ty[i] == TIMEOUT_F) return 1;
+               if (t->ty[i] == ALPHA_F)
+#ifdef GLOB_ALPHA
+                       return 0;
+#else
+                       return (II+1 == (short) now._nr_pr && II+1 < MAXPROC);
+#endif
+               switch (t->qu[i]) {
+               case 0: break;
+               default: Uerror("unknown qid - q_cond");
+                               return 0;
+               }
+       }
+       return 1;
+}
+void
+to_compile(void)
+{      char ctd[1024], carg[64];
+#ifdef BITSTATE
+       strcpy(ctd, "-DBITSTATE ");
+#else
+       strcpy(ctd, "");
+#endif
+#ifdef NOVSZ
+       strcat(ctd, "-DNOVSZ ");
+#endif
+#ifdef REVERSE
+       strcat(ctd, "-DREVERSE ");
+#endif
+#ifdef T_REVERSE
+       strcat(ctd, "-DT_REVERSE ");
+#endif
+#ifdef RANDOMIZE
+       #if RANDOMIZE>0
+       sprintf(carg, "-DRANDOMIZE=%d ", RANDOMIZE);
+       strcat(ctd, carg);
+       #else
+       strcat(ctd, "-DRANDOMIZE ");
+       #endif
+#endif
+#ifdef SCHED
+       sprintf(carg, "-DSCHED=%d ", SCHED);
+       strcat(ctd, carg);
+#endif
+#ifdef BFS
+       strcat(ctd, "-DBFS ");
+#endif
+#ifdef MEMLIM
+       sprintf(carg, "-DMEMLIM=%d ", MEMLIM);
+       strcat(ctd, carg);
+#else
+#ifdef MEMCNT
+       sprintf(carg, "-DMEMCNT=%d ", MEMCNT);
+       strcat(ctd, carg);
+#endif
+#endif
+#ifdef NOCLAIM
+       strcat(ctd, "-DNOCLAIM ");
+#endif
+#ifdef SAFETY
+       strcat(ctd, "-DSAFETY ");
+#else
+#ifdef NOFAIR
+       strcat(ctd, "-DNOFAIR ");
+#else
+#ifdef NFAIR
+       if (NFAIR != 2)
+       {       sprintf(carg, "-DNFAIR=%d ", NFAIR);
+               strcat(ctd, carg);
+       }
+#endif
+#endif
+#endif
+#ifdef NOREDUCE
+       strcat(ctd, "-DNOREDUCE ");
+#else
+#ifdef XUSAFE
+       strcat(ctd, "-DXUSAFE ");
+#endif
+#endif
+#ifdef NP
+       strcat(ctd, "-DNP ");
+#endif
+#ifdef PEG
+       strcat(ctd, "-DPEG ");
+#endif
+#ifdef VAR_RANGES
+       strcat(ctd, "-DVAR_RANGES ");
+#endif
+#ifdef HC0
+       strcat(ctd, "-DHC0 ");
+#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
+#ifdef CTL
+       strcat(ctd, "-DCTL ");
+#endif
+#ifdef NIBIS
+       strcat(ctd, "-DNIBIS ");
+#endif
+#ifdef NOBOUNDCHECK
+       strcat(ctd, "-DNOBOUNDCHECK ");
+#endif
+#ifdef NOSTUTTER
+       strcat(ctd, "-DNOSTUTTER ");
+#endif
+#ifdef REACH
+       strcat(ctd, "-DREACH ");
+#endif
+#ifdef PRINTF
+       strcat(ctd, "-DPRINTF ");
+#endif
+#ifdef OTIM
+       strcat(ctd, "-DOTIM ");
+#endif
+#ifdef COLLAPSE
+       strcat(ctd, "-DCOLLAPSE ");
+#endif
+#ifdef MA
+       sprintf(carg, "-DMA=%d ", MA);
+       strcat(ctd, carg);
+#endif
+#ifdef SVDUMP
+       strcat(ctd, "-DSVDUMP ");
+#endif
+#ifdef VECTORSZ
+       if (VECTORSZ != 1024)
+       {       sprintf(carg, "-DVECTORSZ=%d ", VECTORSZ);
+               strcat(ctd, carg);
+       }
+#endif
+#ifdef VERBOSE
+       strcat(ctd, "-DVERBOSE ");
+#endif
+#ifdef CHECK
+       strcat(ctd, "-DCHECK ");
+#endif
+#ifdef SDUMP
+       strcat(ctd, "-DSDUMP ");
+#endif
+#if NCORE>1
+       sprintf(carg, "-DNCORE=%d ", NCORE);
+       strcat(ctd, carg);
+#endif
+#ifdef SFH
+       sprintf(carg, "-DSFH ");
+       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);
+}
+void
+active_procs(void)
+{
+       if (!permuted) {
+       Addproc(4);
+       } else {
+       Addproc(4);
+       }
+}
+#ifdef MA
+/*
+#include <stdio.h>
+#define uchar  unsigned char
+*/
+#define ulong  unsigned long
+#define ushort unsigned short
+
+#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))
+
+extern char    *emalloc(unsigned long);        /* imported routine  */
+extern void    dfa_init(ushort);       /* 4 exported routines */
+extern int     dfa_member(ulong);
+extern int     dfa_store(uchar *);
+extern void    dfa_stats(void);
+
+typedef struct Edge {
+       uchar From, To;         /* max range 0..255 */
+       uchar s, S;             /* if s=1, S is singleton */
+       struct Vertex   *Dst;
+       struct Edge     *Nxt;
+} Edge;
+
+typedef struct Vertex {
+       ulong   key, num;       /* key for splay tree, nr incoming edges */
+       uchar   from[2], to[2]; /* in-node predefined edge info    */
+       struct  Vertex  *dst[2];/* most nodes have 2 or more edges */
+       struct  Edge    *Succ;  /* in case there are more edges */
+       struct  Vertex  *lnk, *left, *right; /* splay tree plumbing */
+} Vertex;
+
+static Edge    *free_edges;
+static Vertex  *free_vertices;
+static Vertex  **layers;       /* one splay tree of nodes per layer */
+static Vertex  **path;         /* run of word in the DFA */
+static Vertex  *R, *F, *NF;    /* Root, Final, Not-Final */
+static uchar   *word, *lastword;/* string, and last string inserted */
+static int     dfa_depth, iv=0, nv=0, pfrst=0, Tally;
+
+static void    insert_it(Vertex *, int);       /* splay-tree code */
+static void    delete_it(Vertex *, int);
+static Vertex  *find_it(Vertex *, Vertex *, uchar, int);
+
+static void
+recyc_edges(Edge *e)
+{
+       if (!e) return;
+       recyc_edges(e->Nxt);
+       e->Nxt = free_edges;
+       free_edges = e;
+}
+
+static Edge *
+new_edge(Vertex *dst)
+{      Edge *e;
+
+       if (free_edges)
+       {       e = free_edges;
+               free_edges = e->Nxt;
+               e->From = e->To = e->s = e->S = 0;
+               e->Nxt = (Edge *) 0;
+       } else
+               e = (Edge *) emalloc(sizeof(Edge));
+       e->Dst = dst;
+
+       return e;
+}
+
+static void
+recyc_vertex(Vertex *v)
+{
+       recyc_edges(v->Succ);
+       v->Succ = (Edge *) free_vertices;
+       free_vertices = v;
+       nr_states--;
+}
+
+static Vertex *
+new_vertex(void)
+{      Vertex *v;
+
+       if (free_vertices)
+       {       v = free_vertices;
+               free_vertices = (Vertex *) v->Succ;
+               v->Succ = (Edge *) 0;
+               v->num  = 0;
+       } else
+               v = (Vertex *) emalloc(sizeof(Vertex));
+
+       nr_states++;
+       return v; 
+}
+
+static Vertex *
+allDelta(Vertex *v, int n)
+{      Vertex *dst = new_vertex();
+
+       v->from[0] = 0;
+       v->to[0] = 255;
+       v->dst[0] = dst;
+       dst->num = 256;
+       insert_it(v, n);
+       return dst;
+}
+
+static void
+insert_edge(Vertex *v, Edge *e)
+{      /* put new edge first */
+       if (!v->dst[0])
+       {       v->dst[0] = e->Dst;
+               v->from[0] = e->From;
+               v->to[0] = e->To;
+               recyc_edges(e);
+               return;
+       }
+       if (!v->dst[1])
+       {       v->from[1] = v->from[0]; v->from[0] = e->From;
+               v->to[1]   = v->to[0];   v->to[0]   = e->To;
+               v->dst[1]  = v->dst[0];  v->dst[0]  = e->Dst;
+               recyc_edges(e);
+               return;
+       } /* shift */
+       {       int f      = v->from[1];
+               int t      = v->to[1];
+               Vertex *d  = v->dst[1];
+               v->from[1] = v->from[0]; v->from[0] = e->From;
+               v->to[1]   = v->to[0];   v->to[0]   = e->To;
+               v->dst[1]  = v->dst[0];  v->dst[0]  = e->Dst;
+               e->From = f;
+               e->To   = t;
+               e->Dst  = d;
+       }
+       e->Nxt = v->Succ;
+       v->Succ = e;
+}
+
+static void
+copyRecursive(Vertex *v, Edge *e)
+{      Edge *f;
+       if (e->Nxt) copyRecursive(v, e->Nxt);
+       f = new_edge(e->Dst);
+       f->From = e->From;
+       f->To   = e->To;
+       f->s    = e->s;
+       f->S    = e->S;
+       f->Nxt  = v->Succ;
+       v->Succ = f;
+}
+
+static void
+copyEdges(Vertex *to, Vertex *from)
+{      int i;
+       for (i = 0; i < 2; i++)
+       {       to->from[i] = from->from[i];
+               to->to[i]   = from->to[i];
+               to->dst[i]  = from->dst[i];
+       }
+       if (from->Succ) copyRecursive(to, from->Succ);
+}
+
+static Edge *
+cacheDelta(Vertex *v, int h, int first)
+{      static Edge *ov, tmp;  int i;
+
+       if (!first && INRANGE(ov,h))
+               return ov; /* intercepts about 10% */
+       for (i = 0; i < 2; i++)
+               if (v->dst[i] && h >= v->from[i] && h <= v->to[i])
+               {       tmp.From = v->from[i];
+                       tmp.To   = v->to[i];
+                       tmp.Dst  = v->dst[i];
+                       tmp.s    =  tmp.S = 0;
+                       ov = &tmp;
+                       return ov;
+               }
+       for (ov = v->Succ; ov; ov = ov->Nxt)
+               if (INRANGE(ov,h)) return ov;
+
+       Uerror("cannot get here, cacheDelta");
+       return (Edge *) 0;
+}
+
+static Vertex *
+Delta(Vertex *v, int h)        /* v->delta[h] */
+{      Edge *e;
+
+       if (v->dst[0] && h >= v->from[0] && h <= v->to[0])
+               return v->dst[0];       /* oldest edge */
+       if (v->dst[1] && h >= v->from[1] && h <= v->to[1])
+               return v->dst[1];
+       for (e = v->Succ; e; e = e->Nxt)
+               if (INRANGE(e,h))
+                       return e->Dst;
+       Uerror("cannot happen Delta");
+       return (Vertex *) 0;
+}
+
+static void
+numDelta(Vertex *v, int d)
+{      Edge *e;
+       ulong cnt;
+       int i;
+
+       for (i = 0; i < 2; i++)
+       if (v->dst[i])
+       {       cnt = v->dst[i]->num + d*(1 + v->to[i] - v->from[i]);
+               if (d == 1 && cnt < v->dst[i]->num) goto bad;
+               v->dst[i]->num = cnt;
+       }
+       for (e = v->Succ; e; e = e->Nxt)
+       {       cnt = e->Dst->num + d*(1 + e->To - e->From + e->s);
+               if (d == 1 && cnt < e->Dst->num)
+bad:                   Uerror("too many incoming edges");
+               e->Dst->num = cnt;
+       }
+}
+
+static void
+setDelta(Vertex *v, int h, Vertex *newdst)     /* v->delta[h] = newdst; */
+{      Edge *e, *f = (Edge *) 0, *g;
+       int i;
+
+       /* remove the old entry, if there */
+       for (i = 0; i < 2; i++)
+               if (v->dst[i] && h >= v->from[i] && h <= v->to[i])
+               {       if (h == v->from[i])
+                       {       if (h == v->to[i])
+                               {       v->dst[i] = (Vertex *) 0;
+                                       v->from[i] = v->to[i] = 0;
+                               } else
+                                       v->from[i]++;
+                       } else if (h == v->to[i])
+                       {       v->to[i]--;
+                       } else
+                       {       g = new_edge(v->dst[i]);/* same dst */
+                               g->From    = v->from[i];
+                               g->To      = h-1;       /* left half */
+                               v->from[i] = h+1;       /* right half */
+                               insert_edge(v, g);
+                       }
+                       goto part2;
+               }
+       for (e = v->Succ; e; f = e, e = e->Nxt)
+       {       if (e->s == 1 && e->S == h)
+               {       e->s = e->S = 0;
+                       goto rem_tst;
+               }
+               if (h >= e->From && h <= e->To)
+               {       if (h == e->From)
+                       {       if (h == e->To)
+                               {       if (e->s)
+                                       {       e->From = e->To = e->S;
+                                               e->s = 0;
+                                               break;
+                                       } else
+                                               goto rem_do;
+                               } else
+                                       e->From++;
+                       } else if (h == e->To)
+                       {       e->To--;
+                       } else                          /* split */
+                       {       g = new_edge(e->Dst);   /* same dst */
+                               g->From = e->From;
+                               g->To   = h-1;          /* g=left half */
+                               e->From = h+1;          /* e=right half */
+                               g->Nxt  = e->Nxt;       /* insert g */
+                               e->Nxt  = g;            /* behind e */
+                               break;                  /* done */
+                       }
+
+rem_tst:               if (e->From > e->To)
+                       {       if (e->s == 0) {
+rem_do:                                if (f)
+                                               f->Nxt = e->Nxt;
+                                       else
+                                               v->Succ = e->Nxt;
+                                       e->Nxt = (Edge *) 0;
+                                       recyc_edges(e);
+                               } else
+                               {       e->From = e->To = e->S;
+                                       e->s = 0;
+                       }       }
+                       break;
+       }       }
+part2:
+       /* check if newdst is already there */
+       for (i = 0; i < 2; i++)
+               if (v->dst[i] == newdst)
+               {       if (h+1 == (int) v->from[i])
+                       {       v->from[i] = h;
+                               return;
+                       }
+                       if (h == (int) v->to[i]+1)
+                       {       v->to[i] = h;
+                               return;
+               }       }
+       for (e = v->Succ; e; e = e->Nxt)
+       {       if (e->Dst == newdst)
+               {       if (h+1 == (int) e->From)
+                       {       e->From = h;
+                               if (e->s == 1 && e->S+1 == e->From)
+                               {       e->From = e->S;
+                                       e->s = e->S = 0;
+                               }
+                               return;
+                       }
+                       if (h == (int) e->To+1)
+                       {       e->To = h;
+                               if (e->s == 1 && e->S == e->To+1)
+                               {       e->To = e->S;
+                                       e->s = e->S = 0;
+                               }
+                               return;
+                       }
+                       if (e->s == 0)
+                       {       e->s = 1;
+                               e->S = h;
+                               return;
+       }       }       }
+       /* add as a new edge */
+       e = new_edge(newdst);
+       e->From = e->To = h;
+       insert_edge(v, e);
+}
+
+static ulong
+cheap_key(Vertex *v)
+{      ulong vk2 = 0;
+
+       if (v->dst[0])
+       {       vk2 = (ulong) v->dst[0];
+               if ((ulong) v->dst[1] > vk2)
+                       vk2 = (ulong) v->dst[1];
+       } else if (v->dst[1])
+               vk2 = (ulong) v->dst[1]; 
+       if (v->Succ)
+       {       Edge *e;
+               for (e = v->Succ; e; e = e->Nxt)
+                       if ((ulong) e->Dst > vk2)
+                               vk2 = (ulong) e->Dst;
+       }
+       Tally = (vk2>>2)&(TWIDTH-1);
+       return v->key;
+}
+
+static ulong
+mk_key(Vertex *v)      /* not sensitive to order */
+{      ulong m = 0, vk2 = 0;
+       Edge *e;
+
+       if (v->dst[0])
+       {       m += HASH(v->dst[0], v->to[0] - v->from[0] + 1);
+               vk2 = (ulong) v->dst[0]; 
+       }
+       if (v->dst[1])
+       {       m += HASH(v->dst[1], v->to[1] - v->from[1] + 1);
+               if ((ulong) v->dst[1] > vk2) vk2 = (ulong) v->dst[1]; 
+       }
+       for (e = v->Succ; e; e = e->Nxt)
+       {       m += HASH(e->Dst, e->To - e->From + 1 + e->s);
+               if ((ulong) e->Dst > vk2) vk2 = (ulong) e->Dst; 
+       }
+       Tally = (vk2>>2)&(TWIDTH-1);
+       return m;
+}
+
+static ulong
+mk_special(int sigma, Vertex *n, Vertex *v)
+{      ulong m = 0, vk2 = 0;
+       Edge *f;
+       int i;
+
+       for (i = 0; i < 2; i++)
+               if (v->dst[i])
+               {       if (sigma >= v->from[i] && sigma <= v->to[i])
+                       {       m += HASH(v->dst[i], v->to[i]-v->from[i]);
+                               if ((ulong) v->dst[i] > vk2
+                               &&   v->to[i] > v->from[i])
+                                       vk2 = (ulong) v->dst[i]; 
+                       } else
+                       {       m += HASH(v->dst[i], v->to[i]-v->from[i]+1);
+                               if ((ulong) v->dst[i] > vk2)
+                                       vk2 = (ulong) v->dst[i]; 
+               }       }
+       for (f = v->Succ; f; f = f->Nxt)
+       {       if (sigma >= f->From && sigma <= f->To)
+               {       m += HASH(f->Dst, f->To - f->From + f->s);
+                       if ((ulong) f->Dst > vk2
+                       &&   f->To - f->From + f->s > 0)
+                               vk2 = (ulong) f->Dst; 
+               } else if (f->s == 1 && sigma == f->S)
+               {       m += HASH(f->Dst, f->To - f->From + 1);
+                       if ((ulong) f->Dst > vk2) vk2 = (ulong) f->Dst; 
+               } else
+               {       m += HASH(f->Dst, f->To - f->From + 1 + f->s);
+                       if ((ulong) f->Dst > vk2) vk2 = (ulong) f->Dst; 
+       }       }
+
+       if ((ulong) n > vk2) vk2 = (ulong) n; 
+       Tally = (vk2>>2)&(TWIDTH-1);
+       m += HASH(n, 1);
+       return m;
+}
+
+void 
+dfa_init(ushort nr_layers)
+{      int i; Vertex *r, *t;
+
+       dfa_depth = nr_layers;  /* one byte per layer */
+       path   = (Vertex **) emalloc((dfa_depth+1)*sizeof(Vertex *));
+       layers = (Vertex **) emalloc(TWIDTH*(dfa_depth+1)*sizeof(Vertex *));
+       lastword = (uchar *) emalloc((dfa_depth+1)*sizeof(uchar));
+       lastword[dfa_depth] = lastword[0] = 255;
+       path[0] = R = new_vertex(); F = new_vertex();
+
+       for (i = 1, r = R; i < dfa_depth; i++, r = t)
+               t = allDelta(r, i-1);
+       NF = allDelta(r, i-1);
+}
+
+#if 0
+static void complement_dfa(void) { Vertex *tmp = F; F = NF; NF = tmp; }
+#endif
+
+double
+tree_stats(Vertex *t)
+{      Edge *e; double cnt=0.0;
+       if (!t) return 0;
+       if (!t->key) return 0;
+       t->key = 0; /* precaution */
+       if (t->dst[0]) cnt++;
+       if (t->dst[1]) cnt++;
+       for (e = t->Succ; e; e = e->Nxt)
+               cnt++;
+       cnt += tree_stats(t->lnk);
+       cnt += tree_stats(t->left);
+       cnt += tree_stats(t->right);
+       return cnt;
+}
+
+void
+dfa_stats(void)
+{      int i, j; double cnt = 0.0;
+       for (j = 0; j < TWIDTH; j++)
+       for (i = 0; i < dfa_depth+1; i++)
+               cnt += tree_stats(layers[i*TWIDTH+j]);
+       printf("Minimized Automaton:    %6d nodes and %6g edges\n",
+               nr_states, cnt);
+}
+
+int
+dfa_member(ulong n)
+{      Vertex **p, **q;
+       uchar *w = &word[n];
+       int i;
+
+       p = &path[n]; q = (p+1);
+       for (i = n; i < dfa_depth; i++)
+               *q++ = Delta(*p++, *w++);
+       return (*p == F);
+}
+
+int
+dfa_store(uchar *sv)
+{      Vertex **p, **q, *s, *y, *old, *new = F;
+       uchar *w, *u = lastword;
+       int i, j, k;
+
+       w = word = sv;
+       while (*w++ == *u++)    /* find first byte that differs */
+               ;
+       pfrst = (int) (u - lastword) - 1;
+       memcpy(&lastword[pfrst], &sv[pfrst], dfa_depth-pfrst);
+       if (pfrst > iv) pfrst = iv;
+       if (pfrst > nv) pfrst = nv;
+/* phase1: */
+       p = &path[pfrst]; q = (p+1); w = &word[pfrst];
+       for (i = pfrst; i < dfa_depth; i++)
+               *q++ = Delta(*p++, *w++);       /* (*p)->delta[*w++]; */
+
+       if (*p == F) return 1;  /* it's already there */
+/* phase2: */
+       iv = dfa_depth;
+       do {    iv--;
+               old = new;
+               new = find_it(path[iv], old, word[iv], iv);
+       } while (new && iv > 0);
+
+/* phase3: */
+       nv = k = 0; s = path[0];
+       for (j = 1; j <= iv; ++j) 
+               if (path[j]->num > 1)
+               {       y = new_vertex();
+                       copyEdges(y, path[j]);
+                       insert_it(y, j);
+                       numDelta(y, 1);
+                       delete_it(s, j-1);
+                       setDelta(s, word[j-1], y);
+                       insert_it(s, j-1);
+                       y->num = 1;     /* initial value 1 */
+                       s = y;
+                       path[j]->num--; /* only 1 moved from j to y */
+                       k = 1;
+               } else
+               {       s = path[j];
+                       if (!k) nv = j;
+               }
+       y = Delta(s, word[iv]);
+       y->num--;
+       delete_it(s, iv); 
+       setDelta(s, word[iv], old);
+       insert_it(s, iv); 
+       old->num++;
+
+       for (j = iv+1; j < dfa_depth; j++)
+               if (path[j]->num == 0)
+               {       numDelta(path[j], -1);
+                       delete_it(path[j], j);
+                       recyc_vertex(path[j]);
+               } else
+                       break;
+       return 0;
+}
+
+static Vertex *
+splay(ulong i, Vertex *t)
+{      Vertex N, *l, *r, *y;
+
+       if (!t) return t;
+       N.left = N.right = (Vertex *) 0;
+       l = r = &N;
+       for (;;)
+       {       if (i < t->key)
+               {       if (!t->left) break;
+                       if (i < t->left->key)
+                       {       y = t->left;
+                               t->left = y->right;
+                               y->right = t;
+                               t = y;
+                               if (!t->left) break;
+                       }
+                       r->left = t;
+                       r = t;
+                       t = t->left;
+               } else if (i > t->key)
+               {       if (!t->right) break;
+                       if (i > t->right->key)
+                       {       y = t->right;
+                               t->right = y->left;
+                               y->left = t;
+                               t = y;
+                               if (!t->right) break;
+                       }
+                       l->right = t;
+                       l = t;
+                       t = t->right;
+               } else
+                       break;
+       }
+       l->right = t->left;
+       r->left = t->right;
+       t->left = N.right;
+       t->right = N.left;
+       return t;
+}
+
+static void
+insert_it(Vertex *v, int L)
+{      Vertex *new, *t;
+       ulong i; int nr;
+
+       i = mk_key(v);
+       nr = ((L*TWIDTH)+Tally);
+       t = layers[nr];
+
+       v->key = i; 
+       if (!t)
+       {       layers[nr] = v;
+               return;
+       }
+       t = splay(i, t);
+       if (i < t->key)
+       {       new = v;
+               new->left = t->left;
+               new->right = t;
+               t->left = (Vertex *) 0;
+       } else if (i > t->key)
+       {       new = v;
+               new->right = t->right;
+               new->left = t;
+               t->right = (Vertex *) 0;
+       } else   /* it's already there */
+       {       v->lnk = t->lnk; /* put in linked list off v */
+               t->lnk = v;
+               new = t;
+       }
+       layers[nr] = new;
+}
+
+static int
+checkit(Vertex *h, Vertex *v, Vertex *n, uchar sigma)
+{      Edge *g, *f;
+       int i, k, j = 1;
+
+       for (k = 0; k < 2; k++)
+               if (h->dst[k])
+               {       if (sigma >= h->from[k] && sigma <= h->to[k])
+                       {       if (h->dst[k] != n) goto no_match;
+                       }
+                       for (i = h->from[k]; i <= h->to[k]; i++)
+                       {       if (i == sigma) continue;
+                               g = cacheDelta(v, i, j); j = 0;
+                               if (h->dst[k] != g->Dst)
+                                       goto no_match;
+                               if (g->s == 0 || g->S != i)
+                                       i = g->To;
+               }       }
+       for (f = h->Succ; f; f = f->Nxt)
+       {       if (INRANGE(f,sigma))
+               {       if (f->Dst != n) goto no_match;
+               }
+               for (i = f->From; i <= f->To; i++)
+               {       if (i == sigma) continue;
+                       g = cacheDelta(v, i, j); j = 0;
+                       if (f->Dst != g->Dst)
+                               goto no_match;
+                       if (g->s == 1 && i == g->S)
+                               continue;
+                       i = g->To;
+               }
+               if (f->s && f->S != sigma)
+               {       g = cacheDelta(v, f->S, 1);
+                       if (f->Dst != g->Dst)
+                               goto no_match;
+               }
+       }
+       if (h->Succ || h->dst[0] || h->dst[1]) return 1;
+no_match:
+       return 0;
+}
+
+static Vertex *
+find_it(Vertex *v, Vertex *n, uchar sigma, int L)
+{      Vertex *z, *t;
+       ulong i; int nr;
+
+       i = mk_special(sigma,n,v);
+       nr = ((L*TWIDTH)+Tally);
+       t = layers[nr];
+
+       if (!t) return (Vertex *) 0;
+       layers[nr] = t = splay(i, t);
+       if (i == t->key)
+       for (z = t; z; z = z->lnk)
+               if (checkit(z, v, n, sigma))
+                       return z;
+
+       return (Vertex *) 0;
+}
+
+static void
+delete_it(Vertex *v, int L)
+{      Vertex *x, *t;
+       ulong i; int nr;
+
+       i = cheap_key(v);
+       nr = ((L*TWIDTH)+Tally);
+       t = layers[nr];
+       if (!t) return;
+
+       t = splay(i, t);
+       if (i == t->key)
+       {       Vertex *z, *y = (Vertex *) 0;
+               for (z = t; z && z != v; y = z, z = z->lnk)
+                       ;
+               if (z != v) goto bad;
+               if (y)
+               {       y->lnk = z->lnk;
+                       z->lnk = (Vertex *) 0;
+                       layers[nr] = t;
+                       return;
+               } else if (z->lnk)      /* z == t == v */
+               {       y = z->lnk;
+                       y->left = t->left;
+                       y->right = t->right;
+                       t->left = t->right = t->lnk = (Vertex *) 0;
+                       layers[nr] = y;
+                       return;
+               }
+               /* delete the node itself */
+               if (!t->left)
+               {       x = t->right;
+               } else
+               {       x = splay(i, t->left);
+                       x->right = t->right;
+               }
+               t->left = t->right = t->lnk = (Vertex *) 0;
+               layers[nr] = x;
+               return;
+       }
+bad:   Uerror("cannot happen delete");
+}
+#endif
+#if defined(MA) && (defined(W_XPT) || defined(R_XPT))
+static Vertex  **temptree;
+static char    wbuf[4096];
+static int     WCNT = 4096, wcnt=0;
+static uchar   stacker[MA+1];
+static ulong   stackcnt = 0;
+extern double  nstates, nlinks, truncs, truncs2;
+
+static void
+xwrite(int fd, char *b, int n)
+{
+       if (wcnt+n >= 4096)
+       {       write(fd, wbuf, wcnt);
+               wcnt = 0;
+       }
+       memcpy(&wbuf[wcnt], b, n);
+       wcnt += n;
+}
+
+static void
+wclose(fd)
+{
+       if (wcnt > 0)
+               write(fd, wbuf, wcnt);
+       wcnt = 0;
+       close(fd);
+}
+
+static void
+w_vertex(int fd, Vertex *v)
+{      char t[3]; int i; Edge *e;
+
+       xwrite(fd, (char *) &v,  sizeof(Vertex *));
+       t[0] = 0;
+       for (i = 0; i < 2; i++)
+               if (v->dst[i])
+               {       t[1] = v->from[i], t[2] = v->to[i];
+                       xwrite(fd, t, 3);
+                       xwrite(fd, (char *) &(v->dst[i]), sizeof(Vertex *));
+               }
+       for (e = v->Succ; e; e = e->Nxt)
+       {       t[1] = e->From, t[2] = e->To;
+               xwrite(fd, t, 3);
+               xwrite(fd, (char *) &(e->Dst), sizeof(Vertex *));
+
+               if (e->s)
+               {       t[1] = t[2] = e->S;
+                       xwrite(fd, t, 3);
+                       xwrite(fd, (char *) &(e->Dst), sizeof(Vertex *));
+       }       }
+}
+
+static void
+w_layer(int fd, Vertex *v)
+{      uchar c=1;
+
+       if (!v) return;
+       xwrite(fd, (char *) &c, 1);
+       w_vertex(fd, v);
+       w_layer(fd, v->lnk);
+       w_layer(fd, v->left);
+       w_layer(fd, v->right);
+}
+
+void
+w_xpoint(void)
+{      int fd; char nm[64];
+       int i, j;  uchar c;
+       static uchar xwarned = 0;
+
+       sprintf(nm, "%s.xpt", PanSource);
+       if ((fd = creat(nm, 0666)) <= 0)
+       if (!xwarned)
+       {       xwarned = 1;
+               printf("cannot creat checkpoint file\n");
+               return;
+       }
+       xwrite(fd, (char *) &nstates, sizeof(double));
+       xwrite(fd, (char *) &truncs, sizeof(double));
+       xwrite(fd, (char *) &truncs2, sizeof(double));
+       xwrite(fd, (char *) &nlinks, sizeof(double));
+       xwrite(fd, (char *) &dfa_depth, sizeof(int));
+       xwrite(fd, (char *) &R,  sizeof(Vertex *));
+       xwrite(fd, (char *) &F,  sizeof(Vertex *));
+       xwrite(fd, (char *) &NF, sizeof(Vertex *));
+
+       for (j = 0; j < TWIDTH; j++)
+       for (i = 0; i < dfa_depth+1; i++)
+       {       w_layer(fd, layers[i*TWIDTH+j]);
+               c = 2; xwrite(fd, (char *) &c, 1);
+       }
+       wclose(fd);
+}
+
+static void
+xread(int fd, char *b, int n)
+{      int m = wcnt; int delta = 0;
+       if (m < n)
+       {       if (m > 0) memcpy(b, &wbuf[WCNT-m], m);
+               delta = m;
+               WCNT = wcnt = read(fd, wbuf, 4096);
+               if (wcnt < n-m)
+                       Uerror("xread failed -- insufficient data");
+               n -= m;
+       }
+       memcpy(&b[delta], &wbuf[WCNT-wcnt], n);
+       wcnt -= n;
+}
+
+static void
+x_cleanup(Vertex *c)
+{      Edge *e;        /* remove the tree and edges from c */
+       if (!c) return;
+       for (e = c->Succ; e; e = e->Nxt)
+               x_cleanup(e->Dst);
+       recyc_vertex(c);
+}
+
+static void
+x_remove(void)
+{      Vertex *tmp; int i, s;
+       int r, j;
+       /* double-check: */
+       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);
+               for (i = 0; i < dfa_depth; i++)
+                       printf("%d,", stacker[i]);
+               printf(" -- not a stackstate <o:%d,4:%d>\n", r, j);
+               return;
+       }
+       stacker[dfa_depth-1] = 1;
+       s = dfa_member(dfa_depth-1);
+
+       { tmp = F; F = NF; NF = tmp; }  /* complement */
+               if (s) dfa_store(stacker);
+               stacker[dfa_depth-1] = 0;
+               dfa_store(stacker);
+               stackcnt++;
+       { tmp = F; F = NF; NF = tmp; }
+}
+
+static void
+x_rm_stack(Vertex *t, int k)
+{      int j; Edge *e;
+
+       if (k == 0)
+       {       x_remove();
+               return;
+       }
+       if (t)
+       for (e = t->Succ; e; e = e->Nxt)
+       {       for (j = e->From; j <= (int) e->To; j++)
+               {       stacker[k] = (uchar) j;
+                       x_rm_stack(e->Dst, k-1);
+               }
+               if (e->s)
+               {       stacker[k] = e->S;
+                       x_rm_stack(e->Dst, k-1);
+       }       }
+}
+
+static Vertex *
+insert_withkey(Vertex *v, int L)
+{      Vertex *new, *t = temptree[L];
+
+       if (!t) { temptree[L] = v; return v; }
+       t = splay(v->key, t);
+       if (v->key < t->key)
+       {       new = v;
+               new->left = t->left;
+               new->right = t;
+               t->left = (Vertex *) 0;
+       } else if (v->key > t->key)
+       {       new = v;
+               new->right = t->right;
+               new->left = t;
+               t->right = (Vertex *) 0;
+       } else
+       {       if (t != R && t != F && t != NF)
+                       Uerror("double insert, bad checkpoint data");
+               else
+               {       recyc_vertex(v);
+                       new = t;
+       }       }
+       temptree[L] = new;
+
+       return new;
+}
+
+static Vertex *
+find_withkey(Vertex *v, int L)
+{      Vertex *t = temptree[L];
+       if (t)
+       {       temptree[L] = t = splay((ulong) v, t);
+               if (t->key == (ulong) v)
+                       return t;
+       }
+       Uerror("not found error, bad checkpoint data");
+       return (Vertex *) 0;
+}
+
+void
+r_layer(int fd, int n)
+{      Vertex *v;
+       Edge *e;
+       char c, t[2];
+
+       for (;;)
+       {       xread(fd, &c, 1);
+               if (c == 2) break;
+               if (c == 1)
+               {       v = new_vertex();
+                       xread(fd, (char *) &(v->key), sizeof(Vertex *));
+                       v = insert_withkey(v, n);
+               } else  /* c == 0 */
+               {       e = new_edge((Vertex *) 0);
+                       xread(fd, t, 2);
+                       e->From = t[0];
+                       e->To = t[1];
+                       xread(fd, (char *) &(e->Dst), sizeof(Vertex *));
+                       insert_edge(v, e);
+       }       }
+}
+
+static void
+v_fix(Vertex *t, int nr)
+{      int i; Edge *e;
+
+       if (!t) return;
+
+       for (i = 0; i < 2; i++)
+       if (t->dst[i])
+               t->dst[i] = find_withkey(t->dst[i], nr);
+
+       for (e = t->Succ; e; e = e->Nxt)
+               e->Dst = find_withkey(e->Dst, nr);
+               
+       v_fix(t->left, nr);
+       v_fix(t->right, nr);
+}
+
+static void
+v_insert(Vertex *t, int nr)
+{      Edge *e; int i;
+
+       if (!t) return;
+       v_insert(t->left, nr);
+       v_insert(t->right, nr);
+
+       /* remove only leafs from temptree */
+       t->left = t->right = t->lnk = (Vertex *) 0;
+       insert_it(t, nr);       /* into layers */
+       for (i = 0; i < 2; i++)
+               if (t->dst[i])
+                       t->dst[i]->num += (t->to[i] - t->from[i] + 1);
+       for (e = t->Succ; e; e = e->Nxt)
+               e->Dst->num += (e->To - e->From + 1 + e->s);
+}
+
+static void
+x_fixup(void)
+{      int i;
+
+       for (i = 0; i < dfa_depth; i++)
+               v_fix(temptree[i], (i+1));
+
+       for (i = dfa_depth; i >= 0; i--)
+               v_insert(temptree[i], i);
+}
+
+static Vertex *
+x_tail(Vertex *t, ulong want)
+{      int i, yes, no; Edge *e; Vertex *v = (Vertex *) 0;
+
+       if (!t) return v;
+
+       yes = no = 0;
+       for (i = 0; i < 2; i++)
+               if ((ulong) t->dst[i] == want)
+               {       /* was t->from[i] <= 0 && t->to[i] >= 0 */
+                       /* but from and to are uchar */
+                       if (t->from[i] == 0)
+                               yes = 1;
+                       else
+                       if (t->from[i] <= 4 && t->to[i] >= 4)
+                               no = 1;
+               }
+
+       for (e = t->Succ; e; e = e->Nxt)
+               if ((ulong) e->Dst == want)
+               {       /* was INRANGE(e,0) but From and To are uchar */
+                       if ((e->From == 0) || (e->s==1 && e->S==0))
+                               yes = 1;
+                       else if (INRANGE(e, 4))
+                               no = 1;
+               }
+       if (yes && !no) return t;
+       v = x_tail(t->left, want);  if (v) return v;
+       v = x_tail(t->right, want); if (v) return v;
+       return (Vertex *) 0;
+}
+
+static void
+x_anytail(Vertex *t, Vertex *c, int nr)
+{      int i; Edge *e, *f; Vertex *v;
+
+       if (!t) return;
+
+       for (i = 0; i < 2; i++)
+               if ((ulong) t->dst[i] == c->key)
+               {       v = new_vertex(); v->key = t->key;
+                       f = new_edge(v);
+                       f->From = t->from[i];
+                       f->To = t->to[i];
+                       f->Nxt = c->Succ;
+                       c->Succ = f;
+                       if (nr > 0)
+                       x_anytail(temptree[nr-1], v, nr-1);
+               }
+
+       for (e = t->Succ; e; e = e->Nxt)
+               if ((ulong) e->Dst == c->key)
+               {       v = new_vertex(); v->key = t->key;
+                       f = new_edge(v);
+                       f->From = e->From;
+                       f->To = e->To;
+                       f->s = e->s;
+                       f->S = e->S;
+                       f->Nxt = c->Succ;
+                       c->Succ = f;
+                       x_anytail(temptree[nr-1], v, nr-1);
+               }
+
+       x_anytail(t->left, c, nr);
+       x_anytail(t->right, c, nr);
+}
+
+static Vertex *
+x_cpy_rev(void)
+{      Vertex *c, *v;  /* find 0 and !4 predecessor of F */
+
+       v = x_tail(temptree[dfa_depth-1], F->key);
+       if (!v) return (Vertex *) 0;
+
+       c = new_vertex(); c->key = v->key;
+
+       /* every node on dfa_depth-2 that has v->key as succ */
+       /* make copy and let c point to these (reversing ptrs) */
+
+       x_anytail(temptree[dfa_depth-2], c, dfa_depth-2);
+       return c;
+}
+
+void
+r_xpoint(void)
+{      int fd; char nm[64]; Vertex *d;
+       int i, j;
+
+       wcnt = 0;
+       sprintf(nm, "%s.xpt", PanSource);
+       if ((fd = open(nm, 0)) < 0)     /* O_RDONLY */
+               Uerror("cannot open checkpoint file");
+
+       xread(fd, (char *) &nstates,   sizeof(double));
+       xread(fd, (char *) &truncs,    sizeof(double));
+       xread(fd, (char *) &truncs2,   sizeof(double));
+       xread(fd, (char *) &nlinks,    sizeof(double));
+       xread(fd, (char *) &dfa_depth, sizeof(int));
+
+       if (dfa_depth != MA+a_cycles)
+               Uerror("bad dfa_depth in checkpoint file");
+
+       path      = (Vertex **) emalloc((dfa_depth+1)*sizeof(Vertex *));
+       layers    = (Vertex **) emalloc(TWIDTH*(dfa_depth+1)*sizeof(Vertex *));
+       temptree  = (Vertex **) emalloc((dfa_depth+2)*sizeof(Vertex *));
+       lastword  = (uchar *)   emalloc((dfa_depth+1)*sizeof(uchar));
+       lastword[dfa_depth] = lastword[0] = 255; 
+
+       path[0] = R = new_vertex();
+       xread(fd, (char *) &R->key, sizeof(Vertex *));
+       R = insert_withkey(R, 0);
+
+       F = new_vertex();
+       xread(fd, (char *) &F->key, sizeof(Vertex *));
+       F = insert_withkey(F, dfa_depth);
+
+       NF = new_vertex();
+       xread(fd, (char *) &NF->key, sizeof(Vertex *));
+       NF = insert_withkey(NF, dfa_depth);
+
+       for (j = 0; j < TWIDTH; j++)
+       for (i = 0; i < dfa_depth+1; i++)
+               r_layer(fd, i);
+
+       if (wcnt != 0) Uerror("bad count in checkpoint file");
+
+       d = x_cpy_rev();
+       x_fixup();
+       stacker[dfa_depth-1] = 0;
+       x_rm_stack(d, dfa_depth-2);
+       x_cleanup(d);
+       close(fd);
+
+       printf("pan: removed %d stackstates\n", stackcnt);
+       nstates -= (double) stackcnt;
+}
+#endif
+#ifdef VERI
+void
+check_claim(int st)
+{
+       if (st == endclaim)
+               uerror("claim violated!");
+       if (stopstate[VERI][st])
+               uerror("end state in claim reached");
+}
+#endif
+void
+c_globals(void)
+{      /* int i; */
+       printf("global vars:\n");
+       printf("        byte   write_off:       %d\n", now.write_off);
+       {       int l_in;
+               for (l_in = 0; l_in < 2; l_in++)
+               {
+                       printf("        byte   commit_count[%d]:        %d\n", l_in, now.commit_count[l_in]);
+               }
+       }
+       printf("        byte   read_off:        %d\n", now.read_off);
+       {       int l_in;
+               for (l_in = 0; l_in < 2; l_in++)
+               {
+                       printf("        byte   retrieve_count[%d]:      %d\n", l_in, now.retrieve_count[l_in]);
+               }
+       }
+       printf("        byte   events_lost:     %d\n", now.events_lost);
+       printf("        byte   refcount:        %d\n", now.refcount);
+       {       int l_in;
+               for (l_in = 0; l_in < 4; l_in++)
+               {
+                       printf("        bit    buffer_use[%d]:  %d\n", l_in, now.buffer_use[l_in]);
+               }
+       }
+}
+void
+c_locals(int pid, int tp)
+{      /* int i; */
+       switch(tp) {
+       case 4:
+               printf("local vars proc %d (:init:):\n", pid);
+       printf("        byte   i:       %d\n", ((P4 *)pptr(pid))->i);
+       printf("        byte   j:       %d\n", ((P4 *)pptr(pid))->j);
+       printf("        byte   sum:     %d\n", ((P4 *)pptr(pid))->sum);
+       printf("        byte   commit_sum:      %d\n", ((P4 *)pptr(pid))->commit_sum);
+               break;
+       case 3:
+               /* none */
+               break;
+       case 2:
+               printf("local vars proc %d (reader):\n", pid);
+       printf("        byte   i:       %d\n", ((P2 *)pptr(pid))->i);
+       printf("        byte   j:       %d\n", ((P2 *)pptr(pid))->j);
+       printf("        byte   tmp_retrieve:    %d\n", ((P2 *)pptr(pid))->tmp_retrieve);
+       printf("        byte   lwrite_off:      %d\n", ((P2 *)pptr(pid))->lwrite_off);
+       printf("        byte   lcommit_count:   %d\n", ((P2 *)pptr(pid))->lcommit_count);
+               break;
+       case 1:
+               printf("local vars proc %d (tracer):\n", pid);
+       printf("        byte   size:    %d\n", ((P1 *)pptr(pid))->size);
+       printf("        byte   prev_off:        %d\n", ((P1 *)pptr(pid))->prev_off);
+       printf("        byte   new_off: %d\n", ((P1 *)pptr(pid))->new_off);
+       printf("        byte   tmp_commit:      %d\n", ((P1 *)pptr(pid))->tmp_commit);
+       printf("        byte   i:       %d\n", ((P1 *)pptr(pid))->i);
+       printf("        byte   j:       %d\n", ((P1 *)pptr(pid))->j);
+               break;
+       case 0:
+               printf("local vars proc %d (switcher):\n", pid);
+       printf("        byte   prev_off:        %d\n", ((P0 *)pptr(pid))->prev_off);
+       printf("        byte   new_off: %d\n", ((P0 *)pptr(pid))->new_off);
+       printf("        byte   tmp_commit:      %d\n", ((P0 *)pptr(pid))->tmp_commit);
+       printf("        byte   size:    %d\n", ((P0 *)pptr(pid))->size);
+               break;
+       }
+}
+void
+printm(int x)
+{
+       switch (x) {
+       default: Printf("%d", x);
+       }
+}
+void
+c_chandump(int unused) { unused++; /* avoid complaints */ }
diff --git a/trunk/verif/examples/pan.h b/trunk/verif/examples/pan.h
new file mode 100644 (file)
index 0000000..0dcc8a8
--- /dev/null
@@ -0,0 +1,613 @@
+#define SpinVersion    "Spin Version 5.1.6 -- 9 May 2008"
+#define PanSource      "buffer.spin"
+
+#ifdef WIN64
+#define ONE_L  ((unsigned long) 1)
+#define long   long long
+#else
+#define ONE_L  (1L)
+#endif
+char *TrailFile = PanSource; /* default */
+char *trailfilename;
+#if defined(BFS)
+#ifndef SAFETY
+#define SAFETY
+#endif
+#ifndef XUSAFE
+#define XUSAFE
+#endif
+#endif
+#ifndef uchar
+#define uchar  unsigned char
+#endif
+#ifndef uint
+#define uint   unsigned int
+#endif
+#define DELTA  500
+#ifdef MA
+       #if NCORE>1 && !defined(SEP_STATE)
+       #define SEP_STATE
+       #endif
+#if MA==1
+#undef MA
+#define MA     100
+#endif
+#endif
+#ifdef W_XPT
+#if W_XPT==1
+#undef W_XPT
+#define W_XPT 1000000
+#endif
+#endif
+#ifndef NFAIR
+#define NFAIR  2       /* must be >= 2 */
+#endif
+#define HAS_CODE
+#define MERGED 1
+#ifdef NP      /* includes np_ demon */
+#define HAS_NP 2
+#define VERI   5
+#define endclaim       3 /* none */
+#endif
+typedef struct S_F_MAP {
+       char *fnm; int from; int upto;
+} S_F_MAP;
+
+#define nstates4       59      /* :init: */
+#define endstate4      58
+short src_ln4 [] = {
+         0, 225, 227, 228, 229, 230, 231, 231, 
+       226, 233, 226, 233, 235, 236, 237, 238, 
+       238, 234, 240, 234, 240, 241, 242, 244, 
+       245, 246, 247, 248, 248, 243, 250, 243, 
+       250, 252, 253, 254, 255, 256, 256, 251, 
+       258, 251, 224, 262, 263, 264, 266, 267, 
+       271, 272, 273, 273, 265, 278, 265, 278, 
+       282, 260, 284,   0, };
+S_F_MAP src_file4 [] = {
+       { "-", 0, 0 },
+       { "buffer.spin", 1, 58 },
+       { "-", 59, 60 }
+};
+uchar reached4 [] = {
+         0,   1,   1,   0,   0,   0,   1,   1, 
+         0,   1,   1,   0,   1,   0,   0,   1, 
+         1,   0,   1,   1,   0,   0,   0,   1, 
+         0,   0,   0,   1,   1,   0,   1,   1, 
+         0,   1,   0,   0,   0,   1,   1,   0, 
+         1,   1,   0,   1,   0,   0,   1,   0, 
+         0,   0,   1,   1,   0,   1,   1,   0, 
+         0,   0,   0,   0, };
+uchar *loopstate4;
+
+#define nstates3       10      /* cleaner */
+#define endstate3      9
+short src_ln3 [] = {
+         0, 210, 211, 212, 213, 209, 215, 209, 
+       208, 216,   0, };
+S_F_MAP src_file3 [] = {
+       { "-", 0, 0 },
+       { "buffer.spin", 1, 9 },
+       { "-", 10, 11 }
+};
+uchar reached3 [] = {
+         0,   1,   0,   0,   1,   0,   1,   1, 
+         0,   0,   0, };
+uchar *loopstate3;
+
+#define nstates2       32      /* reader */
+#define endstate2      31
+short src_ln2 [] = {
+         0, 169, 171, 173, 174, 175, 176, 177, 
+       177, 172, 179, 172, 170, 187, 189, 190, 
+       191, 192, 192, 188, 194, 188, 194, 196, 
+       197, 186, 199, 199, 164, 201, 164, 201, 
+         0, };
+S_F_MAP src_file2 [] = {
+       { "-", 0, 0 },
+       { "buffer.spin", 1, 31 },
+       { "-", 32, 33 }
+};
+uchar reached2 [] = {
+         0,   1,   1,   1,   0,   0,   0,   1, 
+         1,   0,   1,   1,   0,   1,   1,   0, 
+         0,   1,   1,   0,   1,   1,   0,   0, 
+         0,   0,   1,   1,   0,   1,   1,   0, 
+         0, };
+uchar *loopstate2;
+
+#define nstates1       51      /* tracer */
+#define endstate1      50
+short src_ln1 [] = {
+         0,  99, 100,  98, 104, 105, 106, 106, 
+       103, 108, 102, 111, 111, 112, 112, 110, 
+       114, 114, 116, 117, 118, 119, 120, 120, 
+       115, 122, 115, 109, 127, 129, 130, 131, 
+       132, 132, 128, 134, 128, 134, 135, 137, 
+       137, 138, 138, 136, 140, 126, 142, 144, 
+       146, 141, 148,   0, };
+S_F_MAP src_file1 [] = {
+       { "-", 0, 0 },
+       { "buffer.spin", 1, 50 },
+       { "-", 51, 52 }
+};
+uchar reached1 [] = {
+         0,   1,   0,   0,   1,   1,   1,   0, 
+         1,   1,   0,   1,   1,   1,   0,   1, 
+         1,   0,   1,   0,   0,   0,   1,   1, 
+         0,   1,   1,   0,   1,   1,   0,   0, 
+         1,   1,   0,   1,   1,   0,   0,   1, 
+         0,   1,   0,   0,   1,   0,   1,   0, 
+         0,   0,   0,   0, };
+uchar *loopstate1;
+
+#define nstates0       31      /* switcher */
+#define endstate0      30
+short src_ln0 [] = {
+         0,  56,  57,  58,  61,  62,  63,  64, 
+        64,  59,  66,  55,  69,  69,  70,  70, 
+        68,  72,  67,  75,  76,  78,  78,  79, 
+        79,  77,  81,  81,  74,  84,  85,   0, };
+S_F_MAP src_file0 [] = {
+       { "-", 0, 0 },
+       { "buffer.spin", 1, 30 },
+       { "-", 31, 32 }
+};
+uchar reached0 [] = {
+         0,   1,   0,   0,   1,   0,   1,   1, 
+         0,   0,   1,   0,   1,   1,   1,   0, 
+         1,   1,   0,   1,   0,   1,   0,   1, 
+         0,   0,   1,   0,   0,   1,   0,   0, };
+uchar *loopstate0;
+struct {
+       int tp; short *src;
+} src_all[] = {
+       { 4, &src_ln4[0] },
+       { 3, &src_ln3[0] },
+       { 2, &src_ln2[0] },
+       { 1, &src_ln1[0] },
+       { 0, &src_ln0[0] },
+       { 0, (short *) 0 }
+};
+short *frm_st0;
+struct {
+       char *c; char *t;
+} code_lookup[] = {
+       { (char *) 0, "" }
+};
+#define _T5    64
+#define _T2    65
+#define T_ID   unsigned char
+#define SYNC   0
+#define ASYNC  0
+
+#ifndef NCORE
+       #ifdef DUAL_CORE
+               #define NCORE   2
+       #elif QUAD_CORE
+               #define NCORE   4
+       #else
+               #define NCORE   1
+       #endif
+#endif
+char *procname[] = {
+   "switcher",
+   "tracer",
+   "reader",
+   "cleaner",
+   ":init:",
+   ":np_:",
+};
+
+#define Pinit  ((P4 *)this)
+typedef struct P4 { /* :init: */
+       unsigned _pid : 8;  /* 0..255 */
+       unsigned _t   : 4; /* proctype */
+       unsigned _p   : 7; /* state    */
+       uchar i;
+       uchar j;
+       uchar sum;
+       uchar commit_sum;
+} P4;
+#define Air4   (sizeof(P4) - Offsetof(P4, commit_sum) - 1*sizeof(uchar))
+#define Pcleaner       ((P3 *)this)
+typedef struct P3 { /* cleaner */
+       unsigned _pid : 8;  /* 0..255 */
+       unsigned _t   : 4; /* proctype */
+       unsigned _p   : 7; /* state    */
+} P3;
+#define Air3   (sizeof(P3) - 3)
+#define Preader        ((P2 *)this)
+typedef struct P2 { /* reader */
+       unsigned _pid : 8;  /* 0..255 */
+       unsigned _t   : 4; /* proctype */
+       unsigned _p   : 7; /* state    */
+       uchar i;
+       uchar j;
+       uchar tmp_retrieve;
+       uchar lwrite_off;
+       uchar lcommit_count;
+} P2;
+#define Air2   (sizeof(P2) - Offsetof(P2, lcommit_count) - 1*sizeof(uchar))
+#define Ptracer        ((P1 *)this)
+typedef struct P1 { /* tracer */
+       unsigned _pid : 8;  /* 0..255 */
+       unsigned _t   : 4; /* proctype */
+       unsigned _p   : 7; /* state    */
+       uchar size;
+       uchar prev_off;
+       uchar new_off;
+       uchar tmp_commit;
+       uchar i;
+       uchar j;
+} P1;
+#define Air1   (sizeof(P1) - Offsetof(P1, j) - 1*sizeof(uchar))
+#define Pswitcher      ((P0 *)this)
+typedef struct P0 { /* switcher */
+       unsigned _pid : 8;  /* 0..255 */
+       unsigned _t   : 4; /* proctype */
+       unsigned _p   : 7; /* state    */
+       uchar prev_off;
+       uchar new_off;
+       uchar tmp_commit;
+       uchar size;
+} P0;
+#define Air0   (sizeof(P0) - Offsetof(P0, size) - 1*sizeof(uchar))
+typedef struct P5 { /* np_ */
+       unsigned _pid : 8;  /* 0..255 */
+       unsigned _t   : 4; /* proctype */
+       unsigned _p   : 7; /* state    */
+} P5;
+#define Air5   (sizeof(P5) - 3)
+#if defined(BFS) && defined(REACH)
+#undef REACH
+#endif
+#ifdef VERI
+#define BASE   1
+#else
+#define BASE   0
+#endif
+typedef struct Trans {
+       short atom;     /* if &2 = atomic trans; if &8 local */
+#ifdef HAS_UNLESS
+       short escp[HAS_UNLESS]; /* lists the escape states */
+       short e_trans;  /* if set, this is an escp-trans */
+#endif
+       short tpe[2];   /* class of operation (for reduction) */
+       short qu[6];    /* for conditional selections: qid's  */
+       uchar ty[6];    /* ditto: type's */
+#ifdef NIBIS
+       short om;       /* completion status of preselects */
+#endif
+       char *tp;       /* src txt of statement */
+       int st;         /* the nextstate */
+       int t_id;       /* transition id, unique within proc */
+       int forw;       /* index forward transition */
+       int back;       /* index return  transition */
+       struct Trans *nxt;
+} Trans;
+
+#define qptr(x)        (((uchar *)&now)+(int)q_offset[x])
+#define pptr(x)        (((uchar *)&now)+(int)proc_offset[x])
+extern uchar *Pptr(int);
+#define q_sz(x)        (((Q0 *)qptr(x))->Qlen)
+
+#ifndef VECTORSZ
+#define VECTORSZ       1024           /* sv   size in bytes */
+#endif
+
+#ifdef VERBOSE
+#ifndef CHECK
+#define CHECK
+#endif
+#ifndef DEBUG
+#define DEBUG
+#endif
+#endif
+#ifdef SAFETY
+#ifndef NOFAIR
+#define NOFAIR
+#endif
+#endif
+#ifdef NOREDUCE
+#ifndef XUSAFE
+#define XUSAFE
+#endif
+#if !defined(SAFETY) && !defined(MA)
+#define FULLSTACK
+#endif
+#else
+#ifdef BITSTATE
+#if defined(SAFETY) && !defined(HASH64)
+#define CNTRSTACK
+#else
+#define FULLSTACK
+#endif
+#else
+#define FULLSTACK
+#endif
+#endif
+#ifdef BITSTATE
+#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
+#endif
+#ifdef HC
+#undef HC
+#define HC4
+#endif
+#ifdef HC0
+#define HC     0
+#endif
+#ifdef HC1
+#define HC     1
+#endif
+#ifdef HC2
+#define HC     2
+#endif
+#ifdef HC3
+#define HC     3
+#endif
+#ifdef HC4
+#define HC     4
+#endif
+#ifdef COLLAPSE
+#if NCORE>1 && !defined(SEP_STATE)
+unsigned long *ncomps; /* in shared memory */
+#else
+unsigned long ncomps[256+2];
+#endif
+#endif
+#define MAXQ           255
+#define MAXPROC        255
+#define WS             sizeof(void *) /* word size in bytes */
+typedef struct Stack  {         /* for queues and processes */
+#if VECTORSZ>32000
+       int o_delta;
+       int o_offset;
+       int o_skip;
+       int o_delqs;
+#else
+       short o_delta;
+       short o_offset;
+       short o_skip;
+       short o_delqs;
+#endif
+       short o_boq;
+#ifndef XUSAFE
+       char *o_name;
+#endif
+       char *body;
+       struct Stack *nxt;
+       struct Stack *lst;
+} Stack;
+
+typedef struct Svtack { /* for complete state vector */
+#if VECTORSZ>32000
+       int o_delta;
+       int m_delta;
+#else
+       short o_delta;   /* current size of frame */
+       short m_delta;   /* maximum size of frame */
+#endif
+#if SYNC
+       short o_boq;
+#endif
+#define StackSize      (WS)
+       char *body;
+       struct Svtack *nxt;
+       struct Svtack *lst;
+} Svtack;
+
+Trans ***trans;        /* 1 ptr per state per proctype */
+
+struct H_el *Lstate;
+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 */
+typedef struct State {
+       uchar _nr_pr;
+       uchar _nr_qs;
+       uchar   _a_t;   /* cycle detection */
+#ifndef NOFAIR
+       uchar   _cnt[NFAIR];    /* counters, weak fairness */
+#endif
+#ifndef NOVSZ
+#if VECTORSZ<65536
+       unsigned short _vsz;
+#else
+       unsigned long  _vsz;
+#endif
+#endif
+#ifdef HAS_LAST
+       uchar  _last;   /* pid executed in last step */
+#endif
+#ifdef EVENT_TRACE
+#if nstates_event<256
+       uchar _event;
+#else
+       unsigned short _event;
+#endif
+#endif
+       uchar buffer_use[4];
+       uchar write_off;
+       uchar commit_count[2];
+       uchar read_off;
+       uchar retrieve_count[2];
+       uchar events_lost;
+       uchar refcount;
+       uchar sv[VECTORSZ];
+} State;
+
+#define HAS_TRACK      0
+/* hidden variable: */ uchar deliver;
+int _; /* a predefined write-only variable */
+
+#define FORWARD_MOVES  "pan.m"
+#define REVERSE_MOVES  "pan.b"
+#define TRANSITIONS    "pan.t"
+#define _NP_   5
+uchar reached5[3];  /* np_ */
+uchar *loopstate5;  /* np_ */
+#define nstates5       3 /* np_ */
+#define endstate5      2 /* np_ */
+
+#define start5 0 /* np_ */
+#define start4 42
+#define start3 8
+#define start2 28
+#define start1 3
+#define start0 11
+#ifdef NP
+       #define ACCEPT_LAB      1 /* at least 1 in np_ */
+#else
+       #define ACCEPT_LAB      0 /* 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
+#define PROG_LAB       0 /* progress labels */
+uchar *accpstate[6];
+uchar *progstate[6];
+uchar *loopstate[6];
+uchar *reached[6];
+uchar *stopstate[6];
+uchar *visstate[6];
+short *mapstate[6];
+#ifdef HAS_CODE
+int NrStates[6];
+#endif
+#define NQS    0
+short q_flds[1];
+short q_max[1];
+typedef struct Q0 {    /* generic q */
+       uchar Qlen;     /* q_size */
+       uchar _t;
+} Q0;
+
+/** function prototypes **/
+char *emalloc(unsigned long);
+char *Malloc(unsigned long);
+int Boundcheck(int, int, int, int, Trans *);
+int addqueue(int, int);
+/* int atoi(char *); */
+/* int abort(void); */
+int close(int);
+int delproc(int, int);
+int endstate(void);
+int hstore(char *, int);
+#ifdef MA
+int gstore(char *, int, uchar);
+#endif
+int q_cond(short, Trans *);
+int q_full(int);
+int q_len(int);
+int q_zero(int);
+int qrecv(int, int, int, int);
+int unsend(int);
+/* void *sbrk(int); */
+void Uerror(char *);
+void assert(int, char *, int, int, Trans *);
+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(const char *, int);
+void sfh(const char *, int);
+void d_hash(uchar *, int);
+void s_hash(uchar *, int);
+void r_hash(uchar *, int);
+void delq(int);
+void do_reach(void);
+void pan_exit(int);
+void exit(int);
+void hinit(void);
+void imed(Trans *, int, int, int);
+void new_state(void);
+void p_restor(int);
+void putpeg(int, int);
+void putrail(void);
+void q_restor(void);
+void retrans(int, int, int, short *, uchar *, uchar *);
+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 do_dfs(int, int, int, short *, uchar *, uchar *);
+void uerror(char *);
+void unrecv(int, int, int, int, int);
+void usage(FILE *);
+void wrap_stats(void);
+#if defined(FULLSTACK) && defined(BITSTATE)
+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];
+#endif
+void qsend(int, int, int);
+#define Addproc(x)     addproc(x)
+#define LOCAL  1
+#define Q_FULL_F       2
+#define Q_EMPT_F       3
+#define Q_EMPT_T       4
+#define Q_FULL_T       5
+#define TIMEOUT_F      6
+#define GLOBAL 7
+#define BAD    8
+#define ALPHA_F        9
+#define NTRANS 66
+#ifdef PEG
+long peg[NTRANS];
+#endif
diff --git a/trunk/verif/examples/pan.m b/trunk/verif/examples/pan.m
new file mode 100644 (file)
index 0000000..5d40303
--- /dev/null
@@ -0,0 +1,1039 @@
+#define rand   pan_rand
+#if defined(HAS_CODE) && defined(VERBOSE)
+       cpu_printf("Pr: %d Tr: %d\n", II, t->forw);
+#endif
+       switch (t->forw) {
+       default: Uerror("bad forward move");
+       case 0: /* if without executable clauses */
+               continue;
+       case 1: /* generic 'goto' or 'skip' */
+               IfNotBlocked
+               _m = 3; goto P999;
+       case 2: /* generic 'else' */
+               IfNotBlocked
+               if (trpt->o_pm&1) continue;
+               _m = 3; goto P999;
+
+                /* PROC :init: */
+       case 3: /* STATE 1 - line 225 "buffer.spin" - [i = 0] (0:0:1 - 1) */
+               IfNotBlocked
+               reached[4][1] = 1;
+               (trpt+1)->bup.oval = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               _m = 3; goto P999; /* 0 */
+       case 4: /* STATE 2 - line 227 "buffer.spin" - [((i<2))] (8:0:3 - 1) */
+               IfNotBlocked
+               reached[4][2] = 1;
+               if (!((((int)((P4 *)this)->i)<2)))
+                       continue;
+               /* merge: commit_count[i] = 0(8, 3, 8) */
+               reached[4][3] = 1;
+               (trpt+1)->bup.ovals = grab_ints(3);
+               (trpt+1)->bup.ovals[0] = ((int)now.commit_count[ Index(((int)((P4 *)this)->i), 2) ]);
+               now.commit_count[ Index(((P4 *)this)->i, 2) ] = 0;
+#ifdef VAR_RANGES
+               logval("commit_count[:init::i]", ((int)now.commit_count[ Index(((int)((P4 *)this)->i), 2) ]));
+#endif
+               ;
+               /* merge: retrieve_count[i] = 0(8, 4, 8) */
+               reached[4][4] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)now.retrieve_count[ Index(((int)((P4 *)this)->i), 2) ]);
+               now.retrieve_count[ Index(((P4 *)this)->i, 2) ] = 0;
+#ifdef VAR_RANGES
+               logval("retrieve_count[:init::i]", ((int)now.retrieve_count[ Index(((int)((P4 *)this)->i), 2) ]));
+#endif
+               ;
+               /* merge: i = (i+1)(8, 5, 8) */
+               reached[4][5] = 1;
+               (trpt+1)->bup.ovals[2] = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = (((int)((P4 *)this)->i)+1);
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 9, 8) */
+               reached[4][9] = 1;
+               ;
+               _m = 3; goto P999; /* 4 */
+       case 5: /* STATE 6 - line 231 "buffer.spin" - [((i>=2))] (17:0:2 - 1) */
+               IfNotBlocked
+               reached[4][6] = 1;
+               if (!((((int)((P4 *)this)->i)>=2)))
+                       continue;
+               /* dead 1: i */  (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((P4 *)this)->i;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P4 *)this)->i = 0;
+               /* merge: goto :b6(17, 7, 17) */
+               reached[4][7] = 1;
+               ;
+               /* merge: i = 0(17, 11, 17) */
+               reached[4][11] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 18, 17) */
+               reached[4][18] = 1;
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 6: /* STATE 11 - line 233 "buffer.spin" - [i = 0] (0:17:1 - 3) */
+               IfNotBlocked
+               reached[4][11] = 1;
+               (trpt+1)->bup.oval = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 18, 17) */
+               reached[4][18] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 7: /* STATE 12 - line 235 "buffer.spin" - [((i<4))] (17:0:2 - 1) */
+               IfNotBlocked
+               reached[4][12] = 1;
+               if (!((((int)((P4 *)this)->i)<4)))
+                       continue;
+               /* merge: buffer_use[i] = 0(17, 13, 17) */
+               reached[4][13] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)now.buffer_use[ Index(((int)((P4 *)this)->i), 4) ]);
+               now.buffer_use[ Index(((P4 *)this)->i, 4) ] = 0;
+#ifdef VAR_RANGES
+               logval("buffer_use[:init::i]", ((int)now.buffer_use[ Index(((int)((P4 *)this)->i), 4) ]));
+#endif
+               ;
+               /* merge: i = (i+1)(17, 14, 17) */
+               reached[4][14] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = (((int)((P4 *)this)->i)+1);
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 18, 17) */
+               reached[4][18] = 1;
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 8: /* STATE 15 - line 238 "buffer.spin" - [((i>=4))] (0:0:1 - 1) */
+               IfNotBlocked
+               reached[4][15] = 1;
+               if (!((((int)((P4 *)this)->i)>=4)))
+                       continue;
+               /* dead 1: i */  (trpt+1)->bup.oval = ((P4 *)this)->i;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P4 *)this)->i = 0;
+               _m = 3; goto P999; /* 0 */
+       case 9: /* STATE 20 - line 240 "buffer.spin" - [(run reader())] (0:0:0 - 3) */
+               IfNotBlocked
+               reached[4][20] = 1;
+               if (!(addproc(2)))
+                       continue;
+               _m = 3; goto P999; /* 0 */
+       case 10: /* STATE 21 - line 241 "buffer.spin" - [(run cleaner())] (29:0:1 - 1) */
+               IfNotBlocked
+               reached[4][21] = 1;
+               if (!(addproc(3)))
+                       continue;
+               /* merge: i = 0(0, 22, 29) */
+               reached[4][22] = 1;
+               (trpt+1)->bup.oval = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 30, 29) */
+               reached[4][30] = 1;
+               ;
+               _m = 3; goto P999; /* 2 */
+       case 11: /* STATE 23 - line 244 "buffer.spin" - [((i<4))] (25:0:1 - 1) */
+               IfNotBlocked
+               reached[4][23] = 1;
+               if (!((((int)((P4 *)this)->i)<4)))
+                       continue;
+               /* merge: refcount = (refcount+1)(0, 24, 25) */
+               reached[4][24] = 1;
+               (trpt+1)->bup.oval = ((int)now.refcount);
+               now.refcount = (((int)now.refcount)+1);
+#ifdef VAR_RANGES
+               logval("refcount", ((int)now.refcount));
+#endif
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 12: /* STATE 25 - line 246 "buffer.spin" - [(run tracer())] (29:0:1 - 1) */
+               IfNotBlocked
+               reached[4][25] = 1;
+               if (!(addproc(1)))
+                       continue;
+               /* merge: i = (i+1)(0, 26, 29) */
+               reached[4][26] = 1;
+               (trpt+1)->bup.oval = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = (((int)((P4 *)this)->i)+1);
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 30, 29) */
+               reached[4][30] = 1;
+               ;
+               _m = 3; goto P999; /* 2 */
+       case 13: /* STATE 27 - line 248 "buffer.spin" - [((i>=4))] (39:0:2 - 1) */
+               IfNotBlocked
+               reached[4][27] = 1;
+               if (!((((int)((P4 *)this)->i)>=4)))
+                       continue;
+               /* dead 1: i */  (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((P4 *)this)->i;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P4 *)this)->i = 0;
+               /* merge: goto :b8(39, 28, 39) */
+               reached[4][28] = 1;
+               ;
+               /* merge: i = 0(39, 32, 39) */
+               reached[4][32] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 40, 39) */
+               reached[4][40] = 1;
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 14: /* STATE 32 - line 250 "buffer.spin" - [i = 0] (0:39:1 - 3) */
+               IfNotBlocked
+               reached[4][32] = 1;
+               (trpt+1)->bup.oval = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 40, 39) */
+               reached[4][40] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 15: /* STATE 33 - line 252 "buffer.spin" - [((i<1))] (35:0:1 - 1) */
+               IfNotBlocked
+               reached[4][33] = 1;
+               if (!((((int)((P4 *)this)->i)<1)))
+                       continue;
+               /* merge: refcount = (refcount+1)(0, 34, 35) */
+               reached[4][34] = 1;
+               (trpt+1)->bup.oval = ((int)now.refcount);
+               now.refcount = (((int)now.refcount)+1);
+#ifdef VAR_RANGES
+               logval("refcount", ((int)now.refcount));
+#endif
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 16: /* STATE 35 - line 254 "buffer.spin" - [(run switcher())] (39:0:1 - 1) */
+               IfNotBlocked
+               reached[4][35] = 1;
+               if (!(addproc(0)))
+                       continue;
+               /* merge: i = (i+1)(0, 36, 39) */
+               reached[4][36] = 1;
+               (trpt+1)->bup.oval = ((int)((P4 *)this)->i);
+               ((P4 *)this)->i = (((int)((P4 *)this)->i)+1);
+#ifdef VAR_RANGES
+               logval(":init::i", ((int)((P4 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 40, 39) */
+               reached[4][40] = 1;
+               ;
+               _m = 3; goto P999; /* 2 */
+       case 17: /* STATE 37 - line 256 "buffer.spin" - [((i>=1))] (41:0:1 - 1) */
+               IfNotBlocked
+               reached[4][37] = 1;
+               if (!((((int)((P4 *)this)->i)>=1)))
+                       continue;
+               /* dead 1: i */  (trpt+1)->bup.oval = ((P4 *)this)->i;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P4 *)this)->i = 0;
+               /* merge: goto :b9(0, 38, 41) */
+               reached[4][38] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 18: /* STATE 43 - line 262 "buffer.spin" - [assert((((write_off-read_off)>=0)&&((write_off-read_off)<(255/2))))] (0:52:2 - 1) */
+               IfNotBlocked
+               reached[4][43] = 1;
+               assert((((((int)now.write_off)-((int)now.read_off))>=0)&&((((int)now.write_off)-((int)now.read_off))<(255/2))), "(((write_off-read_off)>=0)&&((write_off-read_off)<(255/2)))", II, tt, t);
+               /* merge: j = 0(52, 44, 52) */
+               reached[4][44] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)((P4 *)this)->j);
+               ((P4 *)this)->j = 0;
+#ifdef VAR_RANGES
+               logval(":init::j", ((int)((P4 *)this)->j));
+#endif
+               ;
+               /* merge: commit_sum = 0(52, 45, 52) */
+               reached[4][45] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P4 *)this)->commit_sum);
+               ((P4 *)this)->commit_sum = 0;
+#ifdef VAR_RANGES
+               logval(":init::commit_sum", ((int)((P4 *)this)->commit_sum));
+#endif
+               ;
+               /* merge: .(goto)(0, 53, 52) */
+               reached[4][53] = 1;
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 19: /* STATE 46 - line 266 "buffer.spin" - [((j<2))] (52:0:2 - 1) */
+               IfNotBlocked
+               reached[4][46] = 1;
+               if (!((((int)((P4 *)this)->j)<2)))
+                       continue;
+               /* merge: commit_sum = (commit_sum+commit_count[j])(52, 47, 52) */
+               reached[4][47] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)((P4 *)this)->commit_sum);
+               ((P4 *)this)->commit_sum = (((int)((P4 *)this)->commit_sum)+((int)now.commit_count[ Index(((int)((P4 *)this)->j), 2) ]));
+#ifdef VAR_RANGES
+               logval(":init::commit_sum", ((int)((P4 *)this)->commit_sum));
+#endif
+               ;
+               /* merge: assert((((commit_count[j]-retrieve_count[j])>=0)&&((commit_count[j]-retrieve_count[j])<(255/2))))(52, 48, 52) */
+               reached[4][48] = 1;
+               assert((((((int)now.commit_count[ Index(((int)((P4 *)this)->j), 2) ])-((int)now.retrieve_count[ Index(((int)((P4 *)this)->j), 2) ]))>=0)&&((((int)now.commit_count[ Index(((int)((P4 *)this)->j), 2) ])-((int)now.retrieve_count[ Index(((int)((P4 *)this)->j), 2) ]))<(255/2))), "(((commit_count[j]-retrieve_count[j])>=0)&&((commit_count[j]-retrieve_count[j])<(255/2)))", II, tt, t);
+               /* merge: j = (j+1)(52, 49, 52) */
+               reached[4][49] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P4 *)this)->j);
+               ((P4 *)this)->j = (((int)((P4 *)this)->j)+1);
+#ifdef VAR_RANGES
+               logval(":init::j", ((int)((P4 *)this)->j));
+#endif
+               ;
+               /* merge: .(goto)(0, 53, 52) */
+               reached[4][53] = 1;
+               ;
+               _m = 3; goto P999; /* 4 */
+       case 20: /* STATE 50 - line 273 "buffer.spin" - [((j>=2))] (58:0:1 - 1) */
+               IfNotBlocked
+               reached[4][50] = 1;
+               if (!((((int)((P4 *)this)->j)>=2)))
+                       continue;
+               /* dead 1: j */  (trpt+1)->bup.oval = ((P4 *)this)->j;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P4 *)this)->j = 0;
+               /* merge: goto :b10(58, 51, 58) */
+               reached[4][51] = 1;
+               ;
+               /* merge: assert((((write_off-commit_sum)>=0)&&((write_off-commit_sum)<(255/2))))(58, 55, 58) */
+               reached[4][55] = 1;
+               assert((((((int)now.write_off)-((int)((P4 *)this)->commit_sum))>=0)&&((((int)now.write_off)-((int)((P4 *)this)->commit_sum))<(255/2))), "(((write_off-commit_sum)>=0)&&((write_off-commit_sum)<(255/2)))", II, tt, t);
+               /* merge: assert((((4+1)>4)||(events_lost==0)))(58, 56, 58) */
+               reached[4][56] = 1;
+               assert((((4+1)>4)||(((int)now.events_lost)==0)), "(((4+1)>4)||(events_lost==0))", II, tt, t);
+               _m = 3; goto P999; /* 3 */
+       case 21: /* STATE 55 - line 278 "buffer.spin" - [assert((((write_off-commit_sum)>=0)&&((write_off-commit_sum)<(255/2))))] (0:58:0 - 3) */
+               IfNotBlocked
+               reached[4][55] = 1;
+               assert((((((int)now.write_off)-((int)((P4 *)this)->commit_sum))>=0)&&((((int)now.write_off)-((int)((P4 *)this)->commit_sum))<(255/2))), "(((write_off-commit_sum)>=0)&&((write_off-commit_sum)<(255/2)))", II, tt, t);
+               /* merge: assert((((4+1)>4)||(events_lost==0)))(58, 56, 58) */
+               reached[4][56] = 1;
+               assert((((4+1)>4)||(((int)now.events_lost)==0)), "(((4+1)>4)||(events_lost==0))", II, tt, t);
+               _m = 3; goto P999; /* 1 */
+       case 22: /* STATE 58 - line 284 "buffer.spin" - [-end-] (0:0:0 - 1) */
+               IfNotBlocked
+               reached[4][58] = 1;
+               if (!delproc(1, II)) continue;
+               _m = 3; goto P999; /* 0 */
+
+                /* PROC cleaner */
+       case 23: /* STATE 1 - line 210 "buffer.spin" - [((refcount==0))] (3:0:1 - 1) */
+               IfNotBlocked
+               reached[3][1] = 1;
+               if (!((((int)now.refcount)==0)))
+                       continue;
+               /* merge: refcount = (refcount+1)(0, 2, 3) */
+               reached[3][2] = 1;
+               (trpt+1)->bup.oval = ((int)now.refcount);
+               now.refcount = (((int)now.refcount)+1);
+#ifdef VAR_RANGES
+               logval("refcount", ((int)now.refcount));
+#endif
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 24: /* STATE 3 - line 212 "buffer.spin" - [(run switcher())] (7:0:0 - 1) */
+               IfNotBlocked
+               reached[3][3] = 1;
+               if (!(addproc(0)))
+                       continue;
+               /* merge: goto :b5(0, 4, 7) */
+               reached[3][4] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 25: /* STATE 9 - line 216 "buffer.spin" - [-end-] (0:0:0 - 1) */
+               IfNotBlocked
+               reached[3][9] = 1;
+               if (!delproc(1, II)) continue;
+               _m = 3; goto P999; /* 0 */
+
+                /* PROC reader */
+       case 26: /* STATE 1 - line 169 "buffer.spin" - [((((((write_off/(4/2))-(read_off/(4/2)))>0)&&(((write_off/(4/2))-(read_off/(4/2)))<(255/2)))&&((commit_count[((read_off%4)/(4/2))]-retrieve_count[((read_off%4)/(4/2))])==(4/2))))] (0:0:0 - 1) */
+               IfNotBlocked
+               reached[2][1] = 1;
+               if (!((((((((int)now.write_off)/(4/2))-(((int)now.read_off)/(4/2)))>0)&&(((((int)now.write_off)/(4/2))-(((int)now.read_off)/(4/2)))<(255/2)))&&((((int)now.commit_count[ Index(((((int)now.read_off)%4)/(4/2)), 2) ])-((int)now.retrieve_count[ Index(((((int)now.read_off)%4)/(4/2)), 2) ]))==(4/2)))))
+                       continue;
+               _m = 3; goto P999; /* 0 */
+       case 27: /* STATE 2 - line 171 "buffer.spin" - [i = 0] (0:0:1 - 1) */
+               IfNotBlocked
+               reached[2][2] = 1;
+               (trpt+1)->bup.oval = ((int)((P2 *)this)->i);
+               ((P2 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval("reader:i", ((int)((P2 *)this)->i));
+#endif
+               ;
+               _m = 3; goto P999; /* 0 */
+       case 28: /* STATE 3 - line 173 "buffer.spin" - [((i<(4/2)))] (9:0:2 - 1) */
+               IfNotBlocked
+               reached[2][3] = 1;
+               if (!((((int)((P2 *)this)->i)<(4/2))))
+                       continue;
+               /* merge: assert((buffer_use[((read_off+i)%4)]==0))(9, 4, 9) */
+               reached[2][4] = 1;
+               assert((((int)now.buffer_use[ Index(((((int)now.read_off)+((int)((P2 *)this)->i))%4), 4) ])==0), "(buffer_use[((read_off+i)%4)]==0)", II, tt, t);
+               /* merge: buffer_use[((read_off+i)%4)] = 1(9, 5, 9) */
+               reached[2][5] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)now.buffer_use[ Index(((((int)now.read_off)+((int)((P2 *)this)->i))%4), 4) ]);
+               now.buffer_use[ Index(((now.read_off+((P2 *)this)->i)%4), 4) ] = 1;
+#ifdef VAR_RANGES
+               logval("buffer_use[((read_off+reader:i)%4)]", ((int)now.buffer_use[ Index(((((int)now.read_off)+((int)((P2 *)this)->i))%4), 4) ]));
+#endif
+               ;
+               /* merge: i = (i+1)(9, 6, 9) */
+               reached[2][6] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P2 *)this)->i);
+               ((P2 *)this)->i = (((int)((P2 *)this)->i)+1);
+#ifdef VAR_RANGES
+               logval("reader:i", ((int)((P2 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 10, 9) */
+               reached[2][10] = 1;
+               ;
+               _m = 3; goto P999; /* 4 */
+       case 29: /* STATE 7 - line 177 "buffer.spin" - [((i>=(4/2)))] (11:0:1 - 1) */
+               IfNotBlocked
+               reached[2][7] = 1;
+               if (!((((int)((P2 *)this)->i)>=(4/2))))
+                       continue;
+               /* dead 1: i */  (trpt+1)->bup.oval = ((P2 *)this)->i;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P2 *)this)->i = 0;
+               /* merge: goto :b3(0, 8, 11) */
+               reached[2][8] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+/* STATE 13 - line 187 "buffer.spin" - [i = 0] (0:0 - 1) same as 27 (0:0 - 1) */
+       case 30: /* STATE 14 - line 189 "buffer.spin" - [((i<(4/2)))] (19:0:2 - 1) */
+               IfNotBlocked
+               reached[2][14] = 1;
+               if (!((((int)((P2 *)this)->i)<(4/2))))
+                       continue;
+               /* merge: buffer_use[((read_off+i)%4)] = 0(19, 15, 19) */
+               reached[2][15] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)now.buffer_use[ Index(((((int)now.read_off)+((int)((P2 *)this)->i))%4), 4) ]);
+               now.buffer_use[ Index(((now.read_off+((P2 *)this)->i)%4), 4) ] = 0;
+#ifdef VAR_RANGES
+               logval("buffer_use[((read_off+reader:i)%4)]", ((int)now.buffer_use[ Index(((((int)now.read_off)+((int)((P2 *)this)->i))%4), 4) ]));
+#endif
+               ;
+               /* merge: i = (i+1)(19, 16, 19) */
+               reached[2][16] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P2 *)this)->i);
+               ((P2 *)this)->i = (((int)((P2 *)this)->i)+1);
+#ifdef VAR_RANGES
+               logval("reader:i", ((int)((P2 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 20, 19) */
+               reached[2][20] = 1;
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 31: /* STATE 17 - line 192 "buffer.spin" - [((i>=(4/2)))] (28:0:4 - 1) */
+               IfNotBlocked
+               reached[2][17] = 1;
+               if (!((((int)((P2 *)this)->i)>=(4/2))))
+                       continue;
+               /* dead 1: i */  (trpt+1)->bup.ovals = grab_ints(4);
+               (trpt+1)->bup.ovals[0] = ((P2 *)this)->i;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P2 *)this)->i = 0;
+               /* merge: goto :b4(28, 18, 28) */
+               reached[2][18] = 1;
+               ;
+               /* merge: tmp_retrieve = (retrieve_count[((read_off%4)/(4/2))]+(4/2))(28, 22, 28) */
+               reached[2][22] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P2 *)this)->tmp_retrieve);
+               ((P2 *)this)->tmp_retrieve = (((int)now.retrieve_count[ Index(((((int)now.read_off)%4)/(4/2)), 2) ])+(4/2));
+#ifdef VAR_RANGES
+               logval("reader:tmp_retrieve", ((int)((P2 *)this)->tmp_retrieve));
+#endif
+               ;
+               /* merge: retrieve_count[((read_off%4)/(4/2))] = tmp_retrieve(28, 23, 28) */
+               reached[2][23] = 1;
+               (trpt+1)->bup.ovals[2] = ((int)now.retrieve_count[ Index(((((int)now.read_off)%4)/(4/2)), 2) ]);
+               now.retrieve_count[ Index(((now.read_off%4)/(4/2)), 2) ] = ((int)((P2 *)this)->tmp_retrieve);
+#ifdef VAR_RANGES
+               logval("retrieve_count[((read_off%4)/(4/2))]", ((int)now.retrieve_count[ Index(((((int)now.read_off)%4)/(4/2)), 2) ]));
+#endif
+               ;
+               /* merge: read_off = (read_off+(4/2))(28, 24, 28) */
+               reached[2][24] = 1;
+               (trpt+1)->bup.ovals[3] = ((int)now.read_off);
+               now.read_off = (((int)now.read_off)+(4/2));
+#ifdef VAR_RANGES
+               logval("read_off", ((int)now.read_off));
+#endif
+               ;
+               /* merge: .(goto)(0, 29, 28) */
+               reached[2][29] = 1;
+               ;
+               _m = 3; goto P999; /* 5 */
+       case 32: /* STATE 22 - line 194 "buffer.spin" - [tmp_retrieve = (retrieve_count[((read_off%4)/(4/2))]+(4/2))] (0:28:3 - 3) */
+               IfNotBlocked
+               reached[2][22] = 1;
+               (trpt+1)->bup.ovals = grab_ints(3);
+               (trpt+1)->bup.ovals[0] = ((int)((P2 *)this)->tmp_retrieve);
+               ((P2 *)this)->tmp_retrieve = (((int)now.retrieve_count[ Index(((((int)now.read_off)%4)/(4/2)), 2) ])+(4/2));
+#ifdef VAR_RANGES
+               logval("reader:tmp_retrieve", ((int)((P2 *)this)->tmp_retrieve));
+#endif
+               ;
+               /* merge: retrieve_count[((read_off%4)/(4/2))] = tmp_retrieve(28, 23, 28) */
+               reached[2][23] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)now.retrieve_count[ Index(((((int)now.read_off)%4)/(4/2)), 2) ]);
+               now.retrieve_count[ Index(((now.read_off%4)/(4/2)), 2) ] = ((int)((P2 *)this)->tmp_retrieve);
+#ifdef VAR_RANGES
+               logval("retrieve_count[((read_off%4)/(4/2))]", ((int)now.retrieve_count[ Index(((((int)now.read_off)%4)/(4/2)), 2) ]));
+#endif
+               ;
+               /* merge: read_off = (read_off+(4/2))(28, 24, 28) */
+               reached[2][24] = 1;
+               (trpt+1)->bup.ovals[2] = ((int)now.read_off);
+               now.read_off = (((int)now.read_off)+(4/2));
+#ifdef VAR_RANGES
+               logval("read_off", ((int)now.read_off));
+#endif
+               ;
+               /* merge: .(goto)(0, 29, 28) */
+               reached[2][29] = 1;
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 33: /* STATE 26 - line 199 "buffer.spin" - [((read_off>=(4-events_lost)))] (0:0:0 - 1) */
+               IfNotBlocked
+               reached[2][26] = 1;
+               if (!((((int)now.read_off)>=(4-((int)now.events_lost)))))
+                       continue;
+               _m = 3; goto P999; /* 0 */
+       case 34: /* STATE 31 - line 201 "buffer.spin" - [-end-] (0:0:0 - 3) */
+               IfNotBlocked
+               reached[2][31] = 1;
+               if (!delproc(1, II)) continue;
+               _m = 3; goto P999; /* 0 */
+
+                /* PROC tracer */
+       case 35: /* STATE 1 - line 99 "buffer.spin" - [prev_off = write_off] (0:10:2 - 1) */
+               IfNotBlocked
+               reached[1][1] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)((P1 *)this)->prev_off);
+               ((P1 *)this)->prev_off = ((int)now.write_off);
+#ifdef VAR_RANGES
+               logval("tracer:prev_off", ((int)((P1 *)this)->prev_off));
+#endif
+               ;
+               /* merge: new_off = (prev_off+size)(10, 2, 10) */
+               reached[1][2] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P1 *)this)->new_off);
+               ((P1 *)this)->new_off = (((int)((P1 *)this)->prev_off)+((int)((P1 *)this)->size));
+#ifdef VAR_RANGES
+               logval("tracer:new_off", ((int)((P1 *)this)->new_off));
+#endif
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 36: /* STATE 4 - line 104 "buffer.spin" - [((((new_off-read_off)>4)&&((new_off-read_off)<(255/2))))] (0:0:1 - 1) */
+               IfNotBlocked
+               reached[1][4] = 1;
+               if (!((((((int)((P1 *)this)->new_off)-((int)now.read_off))>4)&&((((int)((P1 *)this)->new_off)-((int)now.read_off))<(255/2)))))
+                       continue;
+               /* dead 1: new_off */  (trpt+1)->bup.oval = ((P1 *)this)->new_off;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P1 *)this)->new_off = 0;
+               _m = 3; goto P999; /* 0 */
+       case 37: /* STATE 7 - line 106 "buffer.spin" - [(1)] (27:0:0 - 1) */
+               IfNotBlocked
+               reached[1][7] = 1;
+               if (!(1))
+                       continue;
+               /* merge: .(goto)(0, 9, 27) */
+               reached[1][9] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 38: /* STATE 11 - line 111 "buffer.spin" - [((prev_off!=write_off))] (3:0:1 - 1) */
+               IfNotBlocked
+               reached[1][11] = 1;
+               if (!((((int)((P1 *)this)->prev_off)!=((int)now.write_off))))
+                       continue;
+               /* dead 1: prev_off */  (trpt+1)->bup.oval = ((P1 *)this)->prev_off;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P1 *)this)->prev_off = 0;
+               /* merge: goto cmpxchg_loop(0, 12, 3) */
+               reached[1][12] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 39: /* STATE 14 - line 112 "buffer.spin" - [write_off = new_off] (0:24:2 - 1) */
+               IfNotBlocked
+               reached[1][14] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)now.write_off);
+               now.write_off = ((int)((P1 *)this)->new_off);
+#ifdef VAR_RANGES
+               logval("write_off", ((int)now.write_off));
+#endif
+               ;
+               /* merge: .(goto)(24, 16, 24) */
+               reached[1][16] = 1;
+               ;
+               /* merge: i = 0(24, 17, 24) */
+               reached[1][17] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P1 *)this)->i);
+               ((P1 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval("tracer:i", ((int)((P1 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 25, 24) */
+               reached[1][25] = 1;
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 40: /* STATE 17 - line 114 "buffer.spin" - [i = 0] (0:24:1 - 2) */
+               IfNotBlocked
+               reached[1][17] = 1;
+               (trpt+1)->bup.oval = ((int)((P1 *)this)->i);
+               ((P1 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval("tracer:i", ((int)((P1 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 25, 24) */
+               reached[1][25] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 41: /* STATE 18 - line 116 "buffer.spin" - [((i<size))] (24:0:2 - 1) */
+               IfNotBlocked
+               reached[1][18] = 1;
+               if (!((((int)((P1 *)this)->i)<((int)((P1 *)this)->size))))
+                       continue;
+               /* merge: assert((buffer_use[((prev_off+i)%4)]==0))(24, 19, 24) */
+               reached[1][19] = 1;
+               assert((((int)now.buffer_use[ Index(((((int)((P1 *)this)->prev_off)+((int)((P1 *)this)->i))%4), 4) ])==0), "(buffer_use[((prev_off+i)%4)]==0)", II, tt, t);
+               /* merge: buffer_use[((prev_off+i)%4)] = 1(24, 20, 24) */
+               reached[1][20] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)now.buffer_use[ Index(((((int)((P1 *)this)->prev_off)+((int)((P1 *)this)->i))%4), 4) ]);
+               now.buffer_use[ Index(((((P1 *)this)->prev_off+((P1 *)this)->i)%4), 4) ] = 1;
+#ifdef VAR_RANGES
+               logval("buffer_use[((tracer:prev_off+tracer:i)%4)]", ((int)now.buffer_use[ Index(((((int)((P1 *)this)->prev_off)+((int)((P1 *)this)->i))%4), 4) ]));
+#endif
+               ;
+               /* merge: i = (i+1)(24, 21, 24) */
+               reached[1][21] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P1 *)this)->i);
+               ((P1 *)this)->i = (((int)((P1 *)this)->i)+1);
+#ifdef VAR_RANGES
+               logval("tracer:i", ((int)((P1 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 25, 24) */
+               reached[1][25] = 1;
+               ;
+               _m = 3; goto P999; /* 4 */
+       case 42: /* STATE 22 - line 120 "buffer.spin" - [((i>=size))] (26:0:1 - 1) */
+               IfNotBlocked
+               reached[1][22] = 1;
+               if (!((((int)((P1 *)this)->i)>=((int)((P1 *)this)->size))))
+                       continue;
+               /* dead 1: i */  (trpt+1)->bup.oval = ((P1 *)this)->i;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P1 *)this)->i = 0;
+               /* merge: goto :b0(0, 23, 26) */
+               reached[1][23] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 43: /* STATE 28 - line 127 "buffer.spin" - [i = 0] (0:0:1 - 1) */
+               IfNotBlocked
+               reached[1][28] = 1;
+               (trpt+1)->bup.oval = ((int)((P1 *)this)->i);
+               ((P1 *)this)->i = 0;
+#ifdef VAR_RANGES
+               logval("tracer:i", ((int)((P1 *)this)->i));
+#endif
+               ;
+               _m = 3; goto P999; /* 0 */
+       case 44: /* STATE 29 - line 129 "buffer.spin" - [((i<size))] (34:0:2 - 1) */
+               IfNotBlocked
+               reached[1][29] = 1;
+               if (!((((int)((P1 *)this)->i)<((int)((P1 *)this)->size))))
+                       continue;
+               /* merge: buffer_use[((prev_off+i)%4)] = 0(34, 30, 34) */
+               reached[1][30] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)now.buffer_use[ Index(((((int)((P1 *)this)->prev_off)+((int)((P1 *)this)->i))%4), 4) ]);
+               now.buffer_use[ Index(((((P1 *)this)->prev_off+((P1 *)this)->i)%4), 4) ] = 0;
+#ifdef VAR_RANGES
+               logval("buffer_use[((tracer:prev_off+tracer:i)%4)]", ((int)now.buffer_use[ Index(((((int)((P1 *)this)->prev_off)+((int)((P1 *)this)->i))%4), 4) ]));
+#endif
+               ;
+               /* merge: i = (i+1)(34, 31, 34) */
+               reached[1][31] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P1 *)this)->i);
+               ((P1 *)this)->i = (((int)((P1 *)this)->i)+1);
+#ifdef VAR_RANGES
+               logval("tracer:i", ((int)((P1 *)this)->i));
+#endif
+               ;
+               /* merge: .(goto)(0, 35, 34) */
+               reached[1][35] = 1;
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 45: /* STATE 32 - line 132 "buffer.spin" - [((i>=size))] (43:0:3 - 1) */
+               IfNotBlocked
+               reached[1][32] = 1;
+               if (!((((int)((P1 *)this)->i)>=((int)((P1 *)this)->size))))
+                       continue;
+               /* dead 1: i */  (trpt+1)->bup.ovals = grab_ints(3);
+               (trpt+1)->bup.ovals[0] = ((P1 *)this)->i;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P1 *)this)->i = 0;
+               /* merge: goto :b1(43, 33, 43) */
+               reached[1][33] = 1;
+               ;
+               /* merge: tmp_commit = (commit_count[((prev_off%4)/(4/2))]+size)(43, 37, 43) */
+               reached[1][37] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P1 *)this)->tmp_commit);
+               ((P1 *)this)->tmp_commit = (((int)now.commit_count[ Index(((((int)((P1 *)this)->prev_off)%4)/(4/2)), 2) ])+((int)((P1 *)this)->size));
+#ifdef VAR_RANGES
+               logval("tracer:tmp_commit", ((int)((P1 *)this)->tmp_commit));
+#endif
+               ;
+               /* merge: commit_count[((prev_off%4)/(4/2))] = tmp_commit(43, 38, 43) */
+               reached[1][38] = 1;
+               (trpt+1)->bup.ovals[2] = ((int)now.commit_count[ Index(((((int)((P1 *)this)->prev_off)%4)/(4/2)), 2) ]);
+               now.commit_count[ Index(((((P1 *)this)->prev_off%4)/(4/2)), 2) ] = ((int)((P1 *)this)->tmp_commit);
+#ifdef VAR_RANGES
+               logval("commit_count[((tracer:prev_off%4)/(4/2))]", ((int)now.commit_count[ Index(((((int)((P1 *)this)->prev_off)%4)/(4/2)), 2) ]));
+#endif
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 46: /* STATE 37 - line 134 "buffer.spin" - [tmp_commit = (commit_count[((prev_off%4)/(4/2))]+size)] (0:43:2 - 3) */
+               IfNotBlocked
+               reached[1][37] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)((P1 *)this)->tmp_commit);
+               ((P1 *)this)->tmp_commit = (((int)now.commit_count[ Index(((((int)((P1 *)this)->prev_off)%4)/(4/2)), 2) ])+((int)((P1 *)this)->size));
+#ifdef VAR_RANGES
+               logval("tracer:tmp_commit", ((int)((P1 *)this)->tmp_commit));
+#endif
+               ;
+               /* merge: commit_count[((prev_off%4)/(4/2))] = tmp_commit(43, 38, 43) */
+               reached[1][38] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)now.commit_count[ Index(((((int)((P1 *)this)->prev_off)%4)/(4/2)), 2) ]);
+               now.commit_count[ Index(((((P1 *)this)->prev_off%4)/(4/2)), 2) ] = ((int)((P1 *)this)->tmp_commit);
+#ifdef VAR_RANGES
+               logval("commit_count[((tracer:prev_off%4)/(4/2))]", ((int)now.commit_count[ Index(((((int)((P1 *)this)->prev_off)%4)/(4/2)), 2) ]));
+#endif
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 47: /* STATE 39 - line 137 "buffer.spin" - [(((tmp_commit%(4/2))==0))] (49:0:2 - 1) */
+               IfNotBlocked
+               reached[1][39] = 1;
+               if (!(((((int)((P1 *)this)->tmp_commit)%(4/2))==0)))
+                       continue;
+               /* dead 1: tmp_commit */  (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((P1 *)this)->tmp_commit;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P1 *)this)->tmp_commit = 0;
+               /* merge: deliver = 1(49, 40, 49) */
+               reached[1][40] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)deliver);
+               deliver = 1;
+#ifdef VAR_RANGES
+               logval("deliver", ((int)deliver));
+#endif
+               ;
+               /* merge: .(goto)(49, 44, 49) */
+               reached[1][44] = 1;
+               ;
+               _m = 3; goto P999; /* 2 */
+       case 48: /* STATE 44 - line 140 "buffer.spin" - [.(goto)] (0:49:0 - 2) */
+               IfNotBlocked
+               reached[1][44] = 1;
+               ;
+               _m = 3; goto P999; /* 0 */
+       case 49: /* STATE 42 - line 138 "buffer.spin" - [(1)] (49:0:0 - 1) */
+               IfNotBlocked
+               reached[1][42] = 1;
+               if (!(1))
+                       continue;
+               /* merge: .(goto)(49, 44, 49) */
+               reached[1][44] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 50: /* STATE 47 - line 144 "buffer.spin" - [events_lost = (events_lost+1)] (0:0:1 - 2) */
+               IfNotBlocked
+               reached[1][47] = 1;
+               (trpt+1)->bup.oval = ((int)now.events_lost);
+               now.events_lost = (((int)now.events_lost)+1);
+#ifdef VAR_RANGES
+               logval("events_lost", ((int)now.events_lost));
+#endif
+               ;
+               _m = 3; goto P999; /* 0 */
+       case 51: /* STATE 48 - line 146 "buffer.spin" - [refcount = (refcount-1)] (0:0:1 - 2) */
+               IfNotBlocked
+               reached[1][48] = 1;
+               (trpt+1)->bup.oval = ((int)now.refcount);
+               now.refcount = (((int)now.refcount)-1);
+#ifdef VAR_RANGES
+               logval("refcount", ((int)now.refcount));
+#endif
+               ;
+               _m = 3; goto P999; /* 0 */
+       case 52: /* STATE 50 - line 148 "buffer.spin" - [-end-] (0:0:0 - 1) */
+               IfNotBlocked
+               reached[1][50] = 1;
+               if (!delproc(1, II)) continue;
+               _m = 3; goto P999; /* 0 */
+
+                /* PROC switcher */
+       case 53: /* STATE 1 - line 56 "buffer.spin" - [prev_off = write_off] (0:9:3 - 1) */
+               IfNotBlocked
+               reached[0][1] = 1;
+               (trpt+1)->bup.ovals = grab_ints(3);
+               (trpt+1)->bup.ovals[0] = ((int)((P0 *)this)->prev_off);
+               ((P0 *)this)->prev_off = ((int)now.write_off);
+#ifdef VAR_RANGES
+               logval("switcher:prev_off", ((int)((P0 *)this)->prev_off));
+#endif
+               ;
+               /* merge: size = ((4/2)-(prev_off%(4/2)))(9, 2, 9) */
+               reached[0][2] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)((P0 *)this)->size);
+               ((P0 *)this)->size = ((4/2)-(((int)((P0 *)this)->prev_off)%(4/2)));
+#ifdef VAR_RANGES
+               logval("switcher:size", ((int)((P0 *)this)->size));
+#endif
+               ;
+               /* merge: new_off = (prev_off+size)(9, 3, 9) */
+               reached[0][3] = 1;
+               (trpt+1)->bup.ovals[2] = ((int)((P0 *)this)->new_off);
+               ((P0 *)this)->new_off = (((int)((P0 *)this)->prev_off)+((int)((P0 *)this)->size));
+#ifdef VAR_RANGES
+               logval("switcher:new_off", ((int)((P0 *)this)->new_off));
+#endif
+               ;
+               _m = 3; goto P999; /* 2 */
+       case 54: /* STATE 4 - line 61 "buffer.spin" - [(((((new_off-read_off)>4)&&((new_off-read_off)<(255/2)))||(size==(4/2))))] (29:0:3 - 1) */
+               IfNotBlocked
+               reached[0][4] = 1;
+               if (!(((((((int)((P0 *)this)->new_off)-((int)now.read_off))>4)&&((((int)((P0 *)this)->new_off)-((int)now.read_off))<(255/2)))||(((int)((P0 *)this)->size)==(4/2)))))
+                       continue;
+               /* dead 1: new_off */  (trpt+1)->bup.ovals = grab_ints(3);
+               (trpt+1)->bup.ovals[0] = ((P0 *)this)->new_off;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P0 *)this)->new_off = 0;
+               /* dead 1: size */  (trpt+1)->bup.ovals[1] = ((P0 *)this)->size;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P0 *)this)->size = 0;
+               /* merge: refcount = (refcount-1)(29, 5, 29) */
+               reached[0][5] = 1;
+               (trpt+1)->bup.ovals[2] = ((int)now.refcount);
+               now.refcount = (((int)now.refcount)-1);
+#ifdef VAR_RANGES
+               logval("refcount", ((int)now.refcount));
+#endif
+               ;
+               /* merge: goto not_needed(29, 6, 29) */
+               reached[0][6] = 1;
+               ;
+               _m = 3; goto P999; /* 2 */
+       case 55: /* STATE 8 - line 64 "buffer.spin" - [(1)] (18:0:0 - 1) */
+               IfNotBlocked
+               reached[0][8] = 1;
+               if (!(1))
+                       continue;
+               /* merge: .(goto)(0, 10, 18) */
+               reached[0][10] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 56: /* STATE 12 - line 69 "buffer.spin" - [((prev_off!=write_off))] (11:0:1 - 1) */
+               IfNotBlocked
+               reached[0][12] = 1;
+               if (!((((int)((P0 *)this)->prev_off)!=((int)now.write_off))))
+                       continue;
+               /* dead 1: prev_off */  (trpt+1)->bup.oval = ((P0 *)this)->prev_off;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P0 *)this)->prev_off = 0;
+               /* merge: goto cmpxchg_loop(0, 13, 11) */
+               reached[0][13] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 57: /* STATE 17 - line 72 "buffer.spin" - [.(goto)] (0:28:0 - 1) */
+               IfNotBlocked
+               reached[0][17] = 1;
+               ;
+               _m = 3; goto P999; /* 0 */
+       case 58: /* STATE 15 - line 70 "buffer.spin" - [write_off = new_off] (0:28:1 - 1) */
+               IfNotBlocked
+               reached[0][15] = 1;
+               (trpt+1)->bup.oval = ((int)now.write_off);
+               now.write_off = ((int)((P0 *)this)->new_off);
+#ifdef VAR_RANGES
+               logval("write_off", ((int)now.write_off));
+#endif
+               ;
+               /* merge: .(goto)(28, 17, 28) */
+               reached[0][17] = 1;
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 59: /* STATE 19 - line 75 "buffer.spin" - [tmp_commit = (commit_count[((prev_off%4)/(4/2))]+size)] (0:25:2 - 1) */
+               IfNotBlocked
+               reached[0][19] = 1;
+               (trpt+1)->bup.ovals = grab_ints(2);
+               (trpt+1)->bup.ovals[0] = ((int)((P0 *)this)->tmp_commit);
+               ((P0 *)this)->tmp_commit = (((int)now.commit_count[ Index(((((int)((P0 *)this)->prev_off)%4)/(4/2)), 2) ])+((int)((P0 *)this)->size));
+#ifdef VAR_RANGES
+               logval("switcher:tmp_commit", ((int)((P0 *)this)->tmp_commit));
+#endif
+               ;
+               /* merge: commit_count[((prev_off%4)/(4/2))] = tmp_commit(25, 20, 25) */
+               reached[0][20] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)now.commit_count[ Index(((((int)((P0 *)this)->prev_off)%4)/(4/2)), 2) ]);
+               now.commit_count[ Index(((((P0 *)this)->prev_off%4)/(4/2)), 2) ] = ((int)((P0 *)this)->tmp_commit);
+#ifdef VAR_RANGES
+               logval("commit_count[((switcher:prev_off%4)/(4/2))]", ((int)now.commit_count[ Index(((((int)((P0 *)this)->prev_off)%4)/(4/2)), 2) ]));
+#endif
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 60: /* STATE 21 - line 78 "buffer.spin" - [(((tmp_commit%(4/2))==0))] (29:0:3 - 1) */
+               IfNotBlocked
+               reached[0][21] = 1;
+               if (!(((((int)((P0 *)this)->tmp_commit)%(4/2))==0)))
+                       continue;
+               /* dead 1: tmp_commit */  (trpt+1)->bup.ovals = grab_ints(3);
+               (trpt+1)->bup.ovals[0] = ((P0 *)this)->tmp_commit;
+#ifdef HAS_CODE
+               if (!readtrail)
+#endif
+                       ((P0 *)this)->tmp_commit = 0;
+               /* merge: deliver = 1(29, 22, 29) */
+               reached[0][22] = 1;
+               (trpt+1)->bup.ovals[1] = ((int)deliver);
+               deliver = 1;
+#ifdef VAR_RANGES
+               logval("deliver", ((int)deliver));
+#endif
+               ;
+               /* merge: .(goto)(29, 26, 29) */
+               reached[0][26] = 1;
+               ;
+               /* merge: refcount = (refcount-1)(29, 27, 29) */
+               reached[0][27] = 1;
+               (trpt+1)->bup.ovals[2] = ((int)now.refcount);
+               now.refcount = (((int)now.refcount)-1);
+#ifdef VAR_RANGES
+               logval("refcount", ((int)now.refcount));
+#endif
+               ;
+               _m = 3; goto P999; /* 3 */
+       case 61: /* STATE 26 - line 81 "buffer.spin" - [.(goto)] (0:29:1 - 2) */
+               IfNotBlocked
+               reached[0][26] = 1;
+               ;
+               /* merge: refcount = (refcount-1)(29, 27, 29) */
+               reached[0][27] = 1;
+               (trpt+1)->bup.oval = ((int)now.refcount);
+               now.refcount = (((int)now.refcount)-1);
+#ifdef VAR_RANGES
+               logval("refcount", ((int)now.refcount));
+#endif
+               ;
+               _m = 3; goto P999; /* 1 */
+       case 62: /* STATE 24 - line 79 "buffer.spin" - [(1)] (29:0:1 - 1) */
+               IfNotBlocked
+               reached[0][24] = 1;
+               if (!(1))
+                       continue;
+               /* merge: .(goto)(29, 26, 29) */
+               reached[0][26] = 1;
+               ;
+               /* merge: refcount = (refcount-1)(29, 27, 29) */
+               reached[0][27] = 1;
+               (trpt+1)->bup.oval = ((int)now.refcount);
+               now.refcount = (((int)now.refcount)-1);
+#ifdef VAR_RANGES
+               logval("refcount", ((int)now.refcount));
+#endif
+               ;
+               _m = 3; goto P999; /* 2 */
+       case 63: /* STATE 30 - line 85 "buffer.spin" - [-end-] (0:0:0 - 1) */
+               IfNotBlocked
+               reached[0][30] = 1;
+               if (!delproc(1, II)) continue;
+               _m = 3; goto P999; /* 0 */
+       case  _T5:      /* np_ */
+               if (!((!(trpt->o_pm&4) && !(trpt->tau&128))))
+                       continue;
+               /* else fall through */
+       case  _T2:      /* true */
+               _m = 3; goto P999;
+#undef rand
+       }
+
diff --git a/trunk/verif/examples/pan.t b/trunk/verif/examples/pan.t
new file mode 100644 (file)
index 0000000..4dc0dfa
--- /dev/null
@@ -0,0 +1,926 @@
+#ifdef PEG
+struct T_SRC {
+       char *fl; int ln;
+} T_SRC[NTRANS];
+
+void
+tr_2_src(int m, char *file, int ln)
+{      T_SRC[m].fl = file;
+       T_SRC[m].ln = ln;
+}
+
+void
+putpeg(int n, int m)
+{      printf("%5d     trans %4d ", m, n);
+       printf("file %s line %3d\n",
+               T_SRC[n].fl, T_SRC[n].ln);
+}
+#endif
+
+void
+settable(void)
+{      Trans *T;
+       Trans *settr(int, int, int, int, int, char *, int, int, int);
+
+       trans = (Trans ***) emalloc(6*sizeof(Trans **));
+
+       /* proctype 4: :init: */
+
+       trans[4] = (Trans **) emalloc(59*sizeof(Trans *));
+
+       T = trans[ 4][42] = settr(161,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(161,2,1,0,0,"ATOMIC", 1, 2, 0);
+       trans[4][1]     = settr(120,2,8,3,3,"i = 0", 1, 2, 0);
+       trans[4][9]     = settr(128,2,8,1,0,".(goto)", 1, 2, 0);
+       T = trans[4][8] = settr(127,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(127,2,2,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(127,2,6,0,0,"DO", 1, 2, 0);
+       trans[4][2]     = settr(121,2,8,4,4,"((i<2))", 1, 2, 0); /* m: 3 -> 8,0 */
+       reached4[3] = 1;
+       trans[4][3]     = settr(0,0,0,0,0,"commit_count[i] = 0",0,0,0);
+       trans[4][4]     = settr(0,0,0,0,0,"retrieve_count[i] = 0",0,0,0);
+       trans[4][5]     = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
+       trans[4][6]     = settr(125,2,17,5,5,"((i>=2))", 1, 2, 0); /* m: 11 -> 17,0 */
+       reached4[11] = 1;
+       trans[4][7]     = settr(126,2,11,1,0,"goto :b6", 1, 2, 0); /* m: 11 -> 0,17 */
+       reached4[11] = 1;
+       trans[4][10]    = settr(129,2,11,1,0,"break", 1, 2, 0);
+       trans[4][11]    = settr(130,2,17,6,6,"i = 0", 1, 2, 0);
+       trans[4][18]    = settr(137,2,17,1,0,".(goto)", 1, 2, 0);
+       T = trans[4][17] = settr(136,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(136,2,12,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(136,2,15,0,0,"DO", 1, 2, 0);
+       trans[4][12]    = settr(131,2,17,7,7,"((i<4))", 1, 2, 0); /* m: 13 -> 17,0 */
+       reached4[13] = 1;
+       trans[4][13]    = settr(0,0,0,0,0,"buffer_use[i] = 0",0,0,0);
+       trans[4][14]    = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
+       trans[4][15]    = settr(134,2,20,8,8,"((i>=4))", 1, 2, 0);
+       trans[4][16]    = settr(135,2,20,1,0,"goto :b7", 1, 2, 0);
+       trans[4][19]    = settr(138,2,20,1,0,"break", 1, 2, 0);
+       trans[4][20]    = settr(139,2,21,9,9,"(run reader())", 1, 2, 0);
+       trans[4][21]    = settr(140,2,29,10,10,"(run cleaner())", 1, 2, 0); /* m: 22 -> 29,0 */
+       reached4[22] = 1;
+       trans[4][22]    = settr(0,0,0,0,0,"i = 0",0,0,0);
+       trans[4][30]    = settr(149,2,29,1,0,".(goto)", 1, 2, 0);
+       T = trans[4][29] = settr(148,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(148,2,23,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(148,2,27,0,0,"DO", 1, 2, 0);
+       trans[4][23]    = settr(142,2,25,11,11,"((i<4))", 1, 2, 0); /* m: 24 -> 25,0 */
+       reached4[24] = 1;
+       trans[4][24]    = settr(0,0,0,0,0,"refcount = (refcount+1)",0,0,0);
+       trans[4][25]    = settr(144,2,29,12,12,"(run tracer())", 1, 2, 0); /* m: 26 -> 29,0 */
+       reached4[26] = 1;
+       trans[4][26]    = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
+       trans[4][27]    = settr(146,2,39,13,13,"((i>=4))", 1, 2, 0); /* m: 32 -> 39,0 */
+       reached4[32] = 1;
+       trans[4][28]    = settr(147,2,32,1,0,"goto :b8", 1, 2, 0); /* m: 32 -> 0,39 */
+       reached4[32] = 1;
+       trans[4][31]    = settr(150,2,32,1,0,"break", 1, 2, 0);
+       trans[4][32]    = settr(151,2,39,14,14,"i = 0", 1, 2, 0);
+       trans[4][40]    = settr(159,2,39,1,0,".(goto)", 1, 2, 0);
+       T = trans[4][39] = settr(158,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(158,2,33,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(158,2,37,0,0,"DO", 1, 2, 0);
+       trans[4][33]    = settr(152,2,35,15,15,"((i<1))", 1, 2, 0); /* m: 34 -> 35,0 */
+       reached4[34] = 1;
+       trans[4][34]    = settr(0,0,0,0,0,"refcount = (refcount+1)",0,0,0);
+       trans[4][35]    = settr(154,2,39,16,16,"(run switcher())", 1, 2, 0); /* m: 36 -> 39,0 */
+       reached4[36] = 1;
+       trans[4][36]    = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
+       trans[4][37]    = settr(156,2,41,17,17,"((i>=1))", 1, 2, 0); /* m: 38 -> 41,0 */
+       reached4[38] = 1;
+       trans[4][38]    = settr(157,2,41,1,0,"goto :b9", 1, 2, 0);
+       trans[4][41]    = settr(160,0,57,1,0,"break", 1, 2, 0);
+       T = trans[ 4][57] = settr(176,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(176,2,43,0,0,"ATOMIC", 1, 2, 0);
+       trans[4][43]    = settr(162,2,52,18,18,"assert((((write_off-read_off)>=0)&&((write_off-read_off)<(255/2))))", 1, 2, 0); /* m: 44 -> 0,52 */
+       reached4[44] = 1;
+       trans[4][44]    = settr(0,0,0,0,0,"j = 0",0,0,0);
+       trans[4][45]    = settr(0,0,0,0,0,"commit_sum = 0",0,0,0);
+       trans[4][53]    = settr(172,2,52,1,0,".(goto)", 1, 2, 0);
+       T = trans[4][52] = settr(171,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(171,2,46,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(171,2,50,0,0,"DO", 1, 2, 0);
+       trans[4][46]    = settr(165,2,52,19,19,"((j<2))", 1, 2, 0); /* m: 47 -> 52,0 */
+       reached4[47] = 1;
+       trans[4][47]    = settr(0,0,0,0,0,"commit_sum = (commit_sum+commit_count[j])",0,0,0);
+       trans[4][48]    = settr(0,0,0,0,0,"assert((((commit_count[j]-retrieve_count[j])>=0)&&((commit_count[j]-retrieve_count[j])<(255/2))))",0,0,0);
+       trans[4][49]    = settr(0,0,0,0,0,"j = (j+1)",0,0,0);
+       trans[4][50]    = settr(169,4,58,20,20,"((j>=2))", 1, 2, 0); /* m: 55 -> 58,0 */
+       reached4[55] = 1;
+       trans[4][51]    = settr(170,2,55,1,0,"goto :b10", 1, 2, 0); /* m: 55 -> 0,58 */
+       reached4[55] = 1;
+       trans[4][54]    = settr(173,2,55,1,0,"break", 1, 2, 0);
+       trans[4][55]    = settr(174,4,58,21,21,"assert((((write_off-commit_sum)>=0)&&((write_off-commit_sum)<(255/2))))", 1, 2, 0); /* m: 56 -> 0,58 */
+       reached4[56] = 1;
+       trans[4][56]    = settr(0,0,0,0,0,"assert((((4+1)>4)||(events_lost==0)))",0,0,0);
+       trans[4][58]    = settr(177,0,0,22,22,"-end-", 0, 3500, 0);
+
+       /* proctype 3: cleaner */
+
+       trans[3] = (Trans **) emalloc(10*sizeof(Trans *));
+
+       T = trans[ 3][8] = settr(118,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(118,2,5,0,0,"ATOMIC", 1, 2, 0);
+       trans[3][6]     = settr(116,2,5,1,0,".(goto)", 1, 2, 0);
+       T = trans[3][5] = settr(115,2,0,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(115,2,1,0,0,"DO", 1, 2, 0);
+       trans[3][1]     = settr(111,2,3,23,23,"((refcount==0))", 1, 2, 0); /* m: 2 -> 3,0 */
+       reached3[2] = 1;
+       trans[3][2]     = settr(0,0,0,0,0,"refcount = (refcount+1)",0,0,0);
+       trans[3][3]     = settr(113,2,7,24,24,"(run switcher())", 1, 2, 0); /* m: 4 -> 7,0 */
+       reached3[4] = 1;
+       trans[3][4]     = settr(114,2,7,1,0,"goto :b5", 1, 2, 0);
+       trans[3][7]     = settr(117,0,9,1,0,"break", 1, 2, 0);
+       trans[3][9]     = settr(119,0,0,25,25,"-end-", 0, 3500, 0);
+
+       /* proctype 2: reader */
+
+       trans[2] = (Trans **) emalloc(32*sizeof(Trans *));
+
+       trans[2][29]    = settr(108,0,28,1,0,".(goto)", 0, 2, 0);
+       T = trans[2][28] = settr(107,0,0,0,0,"DO", 0, 2, 0);
+       T = T->nxt      = settr(107,0,1,0,0,"DO", 0, 2, 0);
+           T->nxt      = settr(107,0,26,0,0,"DO", 0, 2, 0);
+       trans[2][1]     = settr(80,0,12,26,0,"((((((write_off/(4/2))-(read_off/(4/2)))>0)&&(((write_off/(4/2))-(read_off/(4/2)))<(255/2)))&&((commit_count[((read_off%4)/(4/2))]-retrieve_count[((read_off%4)/(4/2))])==(4/2))))", 1, 2, 0);
+       T = trans[ 2][12] = settr(91,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(91,2,2,0,0,"ATOMIC", 1, 2, 0);
+       trans[2][2]     = settr(81,2,9,27,27,"i = 0", 1, 2, 0);
+       trans[2][10]    = settr(89,2,9,1,0,".(goto)", 1, 2, 0);
+       T = trans[2][9] = settr(88,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(88,2,3,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(88,2,7,0,0,"DO", 1, 2, 0);
+       trans[2][3]     = settr(82,2,9,28,28,"((i<(4/2)))", 1, 2, 0); /* m: 4 -> 9,0 */
+       reached2[4] = 1;
+       trans[2][4]     = settr(0,0,0,0,0,"assert((buffer_use[((read_off+i)%4)]==0))",0,0,0);
+       trans[2][5]     = settr(0,0,0,0,0,"buffer_use[((read_off+i)%4)] = 1",0,0,0);
+       trans[2][6]     = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
+       trans[2][7]     = settr(86,2,11,29,29,"((i>=(4/2)))", 1, 2, 0); /* m: 8 -> 11,0 */
+       reached2[8] = 1;
+       trans[2][8]     = settr(87,2,11,1,0,"goto :b3", 1, 2, 0);
+       trans[2][11]    = settr(90,0,25,1,0,"break", 1, 2, 0);
+       T = trans[ 2][25] = settr(104,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(104,2,13,0,0,"ATOMIC", 1, 2, 0);
+       trans[2][13]    = /* c */ settr(92,2,19,27,27,"i = 0", 1, 2, 0);
+       trans[2][20]    = settr(99,2,19,1,0,".(goto)", 1, 2, 0);
+       T = trans[2][19] = settr(98,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(98,2,14,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(98,2,17,0,0,"DO", 1, 2, 0);
+       trans[2][14]    = settr(93,2,19,30,30,"((i<(4/2)))", 1, 2, 0); /* m: 15 -> 19,0 */
+       reached2[15] = 1;
+       trans[2][15]    = settr(0,0,0,0,0,"buffer_use[((read_off+i)%4)] = 0",0,0,0);
+       trans[2][16]    = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
+       trans[2][17]    = settr(96,0,28,31,31,"((i>=(4/2)))", 1, 2, 0); /* m: 22 -> 28,0 */
+       reached2[22] = 1;
+       trans[2][18]    = settr(97,2,22,1,0,"goto :b4", 1, 2, 0); /* m: 22 -> 0,28 */
+       reached2[22] = 1;
+       trans[2][21]    = settr(100,2,22,1,0,"break", 1, 2, 0);
+       trans[2][22]    = settr(101,0,28,32,32,"tmp_retrieve = (retrieve_count[((read_off%4)/(4/2))]+(4/2))", 1, 2, 0); /* m: 23 -> 0,28 */
+       reached2[23] = 1;
+       trans[2][23]    = settr(0,0,0,0,0,"retrieve_count[((read_off%4)/(4/2))] = tmp_retrieve",0,0,0);
+       trans[2][24]    = settr(0,0,0,0,0,"read_off = (read_off+(4/2))",0,0,0);
+       trans[2][26]    = settr(105,0,31,33,0,"((read_off>=(4-events_lost)))", 1, 2, 0);
+       trans[2][27]    = settr(106,0,31,1,0,"goto :b2", 0, 2, 0);
+       trans[2][30]    = settr(109,0,31,1,0,"break", 0, 2, 0);
+       trans[2][31]    = settr(110,0,0,34,34,"-end-", 0, 3500, 0);
+
+       /* proctype 1: tracer */
+
+       trans[1] = (Trans **) emalloc(51*sizeof(Trans *));
+
+       T = trans[ 1][3] = settr(32,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(32,2,1,0,0,"ATOMIC", 1, 2, 0);
+       trans[1][1]     = settr(30,4,10,35,35,"prev_off = write_off", 1, 2, 0); /* m: 2 -> 0,10 */
+       reached1[2] = 1;
+       trans[1][2]     = settr(0,0,0,0,0,"new_off = (prev_off+size)",0,0,0);
+       T = trans[ 1][10] = settr(39,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(39,2,8,0,0,"ATOMIC", 1, 2, 0);
+       T = trans[1][8] = settr(37,2,0,0,0,"IF", 1, 2, 0);
+       T = T->nxt      = settr(37,2,4,0,0,"IF", 1, 2, 0);
+           T->nxt      = settr(37,2,6,0,0,"IF", 1, 2, 0);
+       trans[1][4]     = settr(33,2,47,36,36,"((((new_off-read_off)>4)&&((new_off-read_off)<(255/2))))", 1, 2, 0);
+       trans[1][5]     = settr(34,2,47,1,0,"goto lost", 1, 2, 0);
+       trans[1][9]     = settr(38,0,27,1,0,".(goto)", 1, 2, 0);
+       trans[1][6]     = settr(35,2,7,2,0,"else", 1, 2, 0);
+       trans[1][7]     = settr(36,4,27,37,37,"(1)", 1, 2, 0); /* m: 9 -> 27,0 */
+       reached1[9] = 1;
+       T = trans[ 1][27] = settr(56,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(56,2,15,0,0,"ATOMIC", 1, 2, 0);
+       T = trans[1][15] = settr(44,2,0,0,0,"IF", 1, 2, 0);
+       T = T->nxt      = settr(44,2,11,0,0,"IF", 1, 2, 0);
+           T->nxt      = settr(44,2,13,0,0,"IF", 1, 2, 0);
+       trans[1][11]    = settr(40,4,3,38,38,"((prev_off!=write_off))", 1, 2, 0); /* m: 12 -> 3,0 */
+       reached1[12] = 1;
+       trans[1][12]    = settr(41,0,3,1,0,"goto cmpxchg_loop", 1, 2, 0);
+       trans[1][16]    = settr(45,2,17,1,0,".(goto)", 1, 2, 0); /* m: 17 -> 0,24 */
+       reached1[17] = 1;
+       trans[1][13]    = settr(42,2,14,2,0,"else", 1, 2, 0);
+       trans[1][14]    = settr(43,2,24,39,39,"write_off = new_off", 1, 2, 0); /* m: 17 -> 0,24 */
+       reached1[17] = 1;
+       trans[1][17]    = settr(46,2,24,40,40,"i = 0", 1, 2, 0);
+       trans[1][25]    = settr(54,2,24,1,0,".(goto)", 1, 2, 0);
+       T = trans[1][24] = settr(53,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(53,2,18,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(53,2,22,0,0,"DO", 1, 2, 0);
+       trans[1][18]    = settr(47,2,24,41,41,"((i<size))", 1, 2, 0); /* m: 19 -> 24,0 */
+       reached1[19] = 1;
+       trans[1][19]    = settr(0,0,0,0,0,"assert((buffer_use[((prev_off+i)%4)]==0))",0,0,0);
+       trans[1][20]    = settr(0,0,0,0,0,"buffer_use[((prev_off+i)%4)] = 1",0,0,0);
+       trans[1][21]    = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
+       trans[1][22]    = settr(51,2,26,42,42,"((i>=size))", 1, 2, 0); /* m: 23 -> 26,0 */
+       reached1[23] = 1;
+       trans[1][23]    = settr(52,2,26,1,0,"goto :b0", 1, 2, 0);
+       trans[1][26]    = settr(55,0,45,1,0,"break", 1, 2, 0);
+       T = trans[ 1][45] = settr(74,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(74,2,28,0,0,"ATOMIC", 1, 2, 0);
+       trans[1][28]    = settr(57,2,34,43,43,"i = 0", 1, 2, 0);
+       trans[1][35]    = settr(64,2,34,1,0,".(goto)", 1, 2, 0);
+       T = trans[1][34] = settr(63,2,0,0,0,"DO", 1, 2, 0);
+       T = T->nxt      = settr(63,2,29,0,0,"DO", 1, 2, 0);
+           T->nxt      = settr(63,2,32,0,0,"DO", 1, 2, 0);
+       trans[1][29]    = settr(58,2,34,44,44,"((i<size))", 1, 2, 0); /* m: 30 -> 34,0 */
+       reached1[30] = 1;
+       trans[1][30]    = settr(0,0,0,0,0,"buffer_use[((prev_off+i)%4)] = 0",0,0,0);
+       trans[1][31]    = settr(0,0,0,0,0,"i = (i+1)",0,0,0);
+       trans[1][32]    = settr(61,2,43,45,45,"((i>=size))", 1, 2, 0); /* m: 37 -> 43,0 */
+       reached1[37] = 1;
+       trans[1][33]    = settr(62,2,37,1,0,"goto :b1", 1, 2, 0); /* m: 37 -> 0,43 */
+       reached1[37] = 1;
+       trans[1][36]    = settr(65,2,37,1,0,"break", 1, 2, 0);
+       trans[1][37]    = settr(66,2,43,46,46,"tmp_commit = (commit_count[((prev_off%4)/(4/2))]+size)", 1, 2, 0); /* m: 38 -> 0,43 */
+       reached1[38] = 1;
+       trans[1][38]    = settr(0,0,0,0,0,"commit_count[((prev_off%4)/(4/2))] = tmp_commit",0,0,0);
+       T = trans[1][43] = settr(72,2,0,0,0,"IF", 1, 2, 0);
+       T = T->nxt      = settr(72,2,39,0,0,"IF", 1, 2, 0);
+           T->nxt      = settr(72,2,41,0,0,"IF", 1, 2, 0);
+       trans[1][39]    = settr(68,4,49,47,47,"(((tmp_commit%(4/2))==0))", 1, 2, 0); /* m: 40 -> 49,0 */
+       reached1[40] = 1;
+       trans[1][40]    = settr(0,0,0,0,0,"deliver = 1",0,0,0);
+       trans[1][44]    = settr(73,0,49,48,48,".(goto)", 1, 2, 0);
+       trans[1][41]    = settr(70,2,42,2,0,"else", 1, 2, 0);
+       trans[1][42]    = settr(71,4,49,49,49,"(1)", 1, 2, 0); /* m: 44 -> 49,0 */
+       reached1[44] = 1;
+       T = trans[ 1][49] = settr(78,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(78,2,46,0,0,"ATOMIC", 1, 2, 0);
+       trans[1][46]    = settr(75,2,48,1,0,"goto end", 1, 2, 0);
+       trans[1][47]    = settr(76,2,48,50,50,"events_lost = (events_lost+1)", 1, 2, 0);
+       trans[1][48]    = settr(77,0,50,51,51,"refcount = (refcount-1)", 1, 2, 0);
+       trans[1][50]    = settr(79,0,0,52,52,"-end-", 0, 3500, 0);
+
+       /* proctype 0: switcher */
+
+       trans[0] = (Trans **) emalloc(31*sizeof(Trans *));
+
+       T = trans[ 0][11] = settr(10,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(10,2,1,0,0,"ATOMIC", 1, 2, 0);
+       trans[0][1]     = settr(0,2,9,53,53,"prev_off = write_off", 1, 2, 0); /* m: 2 -> 0,9 */
+       reached0[2] = 1;
+       trans[0][2]     = settr(0,0,0,0,0,"size = ((4/2)-(prev_off%(4/2)))",0,0,0);
+       trans[0][3]     = settr(0,0,0,0,0,"new_off = (prev_off+size)",0,0,0);
+       T = trans[0][9] = settr(8,2,0,0,0,"IF", 1, 2, 0);
+       T = T->nxt      = settr(8,2,4,0,0,"IF", 1, 2, 0);
+           T->nxt      = settr(8,2,7,0,0,"IF", 1, 2, 0);
+       trans[0][4]     = settr(3,4,29,54,54,"(((((new_off-read_off)>4)&&((new_off-read_off)<(255/2)))||(size==(4/2))))", 1, 2, 0); /* m: 5 -> 29,0 */
+       reached0[5] = 1;
+       trans[0][5]     = settr(0,0,0,0,0,"refcount = (refcount-1)",0,0,0);
+       trans[0][6]     = settr(5,0,29,1,0,"goto not_needed", 1, 2, 0);
+       trans[0][10]    = settr(9,0,18,1,0,".(goto)", 1, 2, 0);
+       trans[0][7]     = settr(6,2,8,2,0,"else", 1, 2, 0);
+       trans[0][8]     = settr(7,4,18,55,55,"(1)", 1, 2, 0); /* m: 10 -> 18,0 */
+       reached0[10] = 1;
+       T = trans[ 0][18] = settr(17,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(17,2,16,0,0,"ATOMIC", 1, 2, 0);
+       T = trans[0][16] = settr(15,2,0,0,0,"IF", 1, 2, 0);
+       T = T->nxt      = settr(15,2,12,0,0,"IF", 1, 2, 0);
+           T->nxt      = settr(15,2,14,0,0,"IF", 1, 2, 0);
+       trans[0][12]    = settr(11,4,11,56,56,"((prev_off!=write_off))", 1, 2, 0); /* m: 13 -> 11,0 */
+       reached0[13] = 1;
+       trans[0][13]    = settr(12,0,11,1,0,"goto cmpxchg_loop", 1, 2, 0);
+       trans[0][17]    = settr(16,0,28,57,57,".(goto)", 1, 2, 0);
+       trans[0][14]    = settr(13,2,15,2,0,"else", 1, 2, 0);
+       trans[0][15]    = settr(14,4,28,58,58,"write_off = new_off", 1, 2, 0); /* m: 17 -> 0,28 */
+       reached0[17] = 1;
+       T = trans[ 0][28] = settr(27,2,0,0,0,"ATOMIC", 1, 2, 0);
+       T->nxt  = settr(27,2,19,0,0,"ATOMIC", 1, 2, 0);
+       trans[0][19]    = settr(18,2,25,59,59,"tmp_commit = (commit_count[((prev_off%4)/(4/2))]+size)", 1, 2, 0); /* m: 20 -> 0,25 */
+       reached0[20] = 1;
+       trans[0][20]    = settr(0,0,0,0,0,"commit_count[((prev_off%4)/(4/2))] = tmp_commit",0,0,0);
+       T = trans[0][25] = settr(24,2,0,0,0,"IF", 1, 2, 0);
+       T = T->nxt      = settr(24,2,21,0,0,"IF", 1, 2, 0);
+           T->nxt      = settr(24,2,23,0,0,"IF", 1, 2, 0);
+       trans[0][21]    = settr(20,4,29,60,60,"(((tmp_commit%(4/2))==0))", 1, 2, 0); /* m: 22 -> 29,0 */
+       reached0[22] = 1;
+       trans[0][22]    = settr(0,0,0,0,0,"deliver = 1",0,0,0);
+       trans[0][26]    = settr(25,4,29,61,61,".(goto)", 1, 2, 0); /* m: 27 -> 0,29 */
+       reached0[27] = 1;
+       trans[0][23]    = settr(22,2,24,2,0,"else", 1, 2, 0);
+       trans[0][24]    = settr(23,4,29,62,62,"(1)", 1, 2, 0); /* m: 26 -> 29,0 */
+       reached0[26] = 1;
+       trans[0][27]    = settr(0,0,0,0,0,"refcount = (refcount-1)",0,0,0);
+       trans[0][29]    = settr(28,0,30,1,0,"(1)", 0, 2, 0);
+       trans[0][30]    = settr(29,0,0,63,63,"-end-", 0, 3500, 0);
+       /* np_ demon: */
+       trans[_NP_] = (Trans **) emalloc(2*sizeof(Trans *));
+       T = trans[_NP_][0] = settr(9997,0,1,_T5,0,"(np_)", 1,2,0);
+           T->nxt        = settr(9998,0,0,_T2,0,"(1)",   0,2,0);
+       T = trans[_NP_][1] = settr(9999,0,1,_T5,0,"(np_)", 1,2,0);
+}
+
+Trans *
+settr( int t_id, int a, int b, int c, int d,
+       char *t, int g, int tpe0, int tpe1)
+{      Trans *tmp = (Trans *) emalloc(sizeof(Trans));
+
+       tmp->atom  = a&(6|32);  /* only (2|8|32) have meaning */
+       if (!g) tmp->atom |= 8; /* no global references */
+       tmp->st    = b;
+       tmp->tpe[0] = tpe0;
+       tmp->tpe[1] = tpe1;
+       tmp->tp    = t;
+       tmp->t_id  = t_id;
+       tmp->forw  = c;
+       tmp->back  = d;
+       return tmp;
+}
+
+Trans *
+cpytr(Trans *a)
+{      Trans *tmp = (Trans *) emalloc(sizeof(Trans));
+
+       int i;
+       tmp->atom  = a->atom;
+       tmp->st    = a->st;
+#ifdef HAS_UNLESS
+       tmp->e_trans = a->e_trans;
+       for (i = 0; i < HAS_UNLESS; i++)
+               tmp->escp[i] = a->escp[i];
+#endif
+       tmp->tpe[0] = a->tpe[0];
+       tmp->tpe[1] = a->tpe[1];
+       for (i = 0; i < 6; i++)
+       {       tmp->qu[i] = a->qu[i];
+               tmp->ty[i] = a->ty[i];
+       }
+       tmp->tp    = (char *) emalloc(strlen(a->tp)+1);
+       strcpy(tmp->tp, a->tp);
+       tmp->t_id  = a->t_id;
+       tmp->forw  = a->forw;
+       tmp->back  = a->back;
+       return tmp;
+}
+
+#ifndef NOREDUCE
+int
+srinc_set(int n)
+{      if (n <= 2) return LOCAL;
+       if (n <= 2+  DELTA) return Q_FULL_F; /* 's' or nfull  */
+       if (n <= 2+2*DELTA) return Q_EMPT_F; /* 'r' or nempty */
+       if (n <= 2+3*DELTA) return Q_EMPT_T; /* empty */
+       if (n <= 2+4*DELTA) return Q_FULL_T; /* full  */
+       if (n ==   5*DELTA) return GLOBAL;
+       if (n ==   6*DELTA) return TIMEOUT_F;
+       if (n ==   7*DELTA) return ALPHA_F;
+       Uerror("cannot happen srinc_class");
+       return BAD;
+}
+int
+srunc(int n, int m)
+{      switch(m) {
+       case Q_FULL_F: return n-2;
+       case Q_EMPT_F: return n-2-DELTA;
+       case Q_EMPT_T: return n-2-2*DELTA;
+       case Q_FULL_T: return n-2-3*DELTA;
+       case ALPHA_F:
+       case TIMEOUT_F: return 257; /* non-zero, and > MAXQ */
+       }
+       Uerror("cannot happen srunc");
+       return 0;
+}
+#endif
+int cnt;
+#ifdef HAS_UNLESS
+int
+isthere(Trans *a, int b)
+{      Trans *t;
+       for (t = a; t; t = t->nxt)
+               if (t->t_id == b)
+                       return 1;
+       return 0;
+}
+#endif
+#ifndef NOREDUCE
+int
+mark_safety(Trans *t) /* for conditional safety */
+{      int g = 0, i, j, k;
+
+       if (!t) return 0;
+       if (t->qu[0])
+               return (t->qu[1])?2:1;  /* marked */
+
+       for (i = 0; i < 2; i++)
+       {       j = srinc_set(t->tpe[i]);
+               if (j >= GLOBAL && j != ALPHA_F)
+                       return -1;
+               if (j != LOCAL)
+               {       k = srunc(t->tpe[i], j);
+                       if (g == 0
+                       ||  t->qu[0] != k
+                       ||  t->ty[0] != j)
+                       {       t->qu[g] = k;
+                               t->ty[g] = j;
+                               g++;
+       }       }       }
+       return g;
+}
+#endif
+void
+retrans(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])
+       /* process n, with m states, is=initial state */
+{      Trans *T0, *T1, *T2, *T3;
+       int i, k;
+#ifndef NOREDUCE
+       int g, h, j, aa;
+#endif
+#ifdef HAS_UNLESS
+       int p;
+#endif
+       if (state_tables >= 4)
+       {       printf("STEP 1 proctype %s\n", 
+                       procname[n]);
+               for (i = 1; i < m; i++)
+               for (T0 = trans[n][i]; T0; T0 = T0->nxt)
+                       crack(n, i, T0, srcln);
+               return;
+       }
+       do {
+               for (i = 1, cnt = 0; i < m; i++)
+               {       T2 = trans[n][i];
+                       T1 = T2?T2->nxt:(Trans *)0;
+/* prescan: */         for (T0 = T1; T0; T0 = T0->nxt)
+/* choice in choice */ {       if (T0->st && trans[n][T0->st]
+                               &&  trans[n][T0->st]->nxt)
+                                       break;
+                       }
+#if 0
+               if (T0)
+               printf("\tstate %d / %d: choice in choice\n",
+               i, T0->st);
+#endif
+                       if (T0)
+                       for (T0 = T1; T0; T0 = T0->nxt)
+                       {       T3 = trans[n][T0->st];
+                               if (!T3->nxt)
+                               {       T2->nxt = cpytr(T0);
+                                       T2 = T2->nxt;
+                                       imed(T2, T0->st, n, i);
+                                       continue;
+                               }
+                               do {    T3 = T3->nxt;
+                                       T2->nxt = cpytr(T3);
+                                       T2 = T2->nxt;
+                                       imed(T2, T0->st, n, i);
+                               } while (T3->nxt);
+                               cnt++;
+                       }
+               }
+       } while (cnt);
+       if (state_tables >= 3)
+       {       printf("STEP 2 proctype %s\n", 
+                       procname[n]);
+               for (i = 1; i < m; i++)
+               for (T0 = trans[n][i]; T0; T0 = T0->nxt)
+                       crack(n, i, T0, srcln);
+               return;
+       }
+       for (i = 1; i < m; i++)
+       {       if (trans[n][i] && trans[n][i]->nxt) /* optimize */
+               {       T1 = trans[n][i]->nxt;
+#if 0
+                       printf("\t\tpull %d (%d) to %d\n",
+                       T1->st, T1->forw, i);
+#endif
+                       if (!trans[n][T1->st]) continue;
+                       T0 = cpytr(trans[n][T1->st]);
+                       trans[n][i] = T0;
+                       reach[T1->st] = 1;
+                       imed(T0, T1->st, n, i);
+                       for (T1 = T1->nxt; T1; T1 = T1->nxt)
+                       {
+#if 0
+                       printf("\t\tpull %d (%d) to %d\n",
+                               T1->st, T1->forw, i);
+#endif
+                               if (!trans[n][T1->st]) continue;
+                               T0->nxt = cpytr(trans[n][T1->st]);
+                               T0 = T0->nxt;
+                               reach[T1->st] = 1;
+                               imed(T0, T1->st, n, i);
+       }       }       }
+       if (state_tables >= 2)
+       {       printf("STEP 3 proctype %s\n", 
+                       procname[n]);
+               for (i = 1; i < m; i++)
+               for (T0 = trans[n][i]; T0; T0 = T0->nxt)
+                       crack(n, i, T0, srcln);
+               return;
+       }
+#ifdef HAS_UNLESS
+       for (i = 1; i < m; i++)
+       {       if (!trans[n][i]) continue;
+               /* check for each state i if an
+                * escape to some state p is defined
+                * if so, copy and mark p's transitions
+                * and prepend them to the transition-
+                * list of state i
+                */
+        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)
+                       {       if (isthere(trans[n][i], T1->t_id))
+                                       continue;
+                               T2 = cpytr(T1);
+                               T2->e_trans = p;
+                               T2->nxt = trans[n][i];
+                               trans[n][i] = T2;
+               }       }
+        } else /* outermost unless checked first */
+        {      Trans *T4;
+               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])
+                       for (T1 = trans[n][p]; T1; T1 = T1->nxt)
+                       {       if (isthere(trans[n][i], T1->t_id))
+                                       continue;
+                               T2 = cpytr(T1);
+                               T2->nxt = (Trans *) 0;
+                               T2->e_trans = p;
+                               if (T3) T3->nxt = T2;
+                               else    T4 = T2;
+                               T3 = T2;
+               }       }
+               if (T4)
+               {       T3->nxt = trans[n][i];
+                       trans[n][i] = T4;
+               }
+        }
+       }
+#endif
+#ifndef NOREDUCE
+       for (i = 1; i < m; i++)
+       {       if (a_cycles)
+               { /* moves through these states are visible */
+       #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
+                       if (accpstate[n][i] || visstate[n][i])
+                               goto degrade;
+                       for (T1 = trans[n][i]; T1; T1 = T1->nxt)
+                               if (accpstate[n][T1->st])
+                                       goto degrade;
+               }
+               T1 = trans[n][i];
+               if (!T1) continue;
+               g = mark_safety(T1);    /* V3.3.1 */
+               if (g < 0) goto degrade; /* global */
+               /* check if mixing of guards preserves reduction */
+               if (T1->nxt)
+               {       k = 0;
+                       for (T0 = T1; T0; T0 = T0->nxt)
+                       {       if (!(T0->atom&8))
+                                       goto degrade;
+                               for (aa = 0; aa < 2; aa++)
+                               {       j = srinc_set(T0->tpe[aa]);
+                                       if (j >= GLOBAL && j != ALPHA_F)
+                                               goto degrade;
+                                       if (T0->tpe[aa]
+                                       &&  T0->tpe[aa]
+                                       !=  T1->tpe[0])
+                                               k = 1;
+                       }       }
+                       /* g = 0;       V3.3.1 */
+                       if (k)  /* non-uniform selection */
+                       for (T0 = T1; T0; T0 = T0->nxt)
+                       for (aa = 0; aa < 2; aa++)
+                       {       j = srinc_set(T0->tpe[aa]);
+                               if (j != LOCAL)
+                               {       k = srunc(T0->tpe[aa], j);
+                                       for (h = 0; h < 6; h++)
+                                               if (T1->qu[h] == k
+                                               &&  T1->ty[h] == j)
+                                                       break;
+                                       if (h >= 6)
+                                       {       T1->qu[g%6] = k;
+                                               T1->ty[g%6] = j;
+                                               g++;
+                       }       }       }
+                       if (g > 6)
+                       {       T1->qu[0] = 0;  /* turn it off */
+                               printf("pan: warning, line %d, ",
+                                       srcln[i]);
+                               printf("too many stmnt types (%d)",
+                                       g);
+                               printf(" in selection\n");
+                         goto degrade;
+                       }
+               }
+               /* mark all options global if >=1 is global */
+               for (T1 = trans[n][i]; T1; T1 = T1->nxt)
+                       if (!(T1->atom&8)) break;
+               if (T1)
+degrade:       for (T1 = trans[n][i]; T1; T1 = T1->nxt)
+                       T1->atom &= ~8; /* mark as unsafe */
+               /* can only mix 'r's or 's's if on same chan */
+               /* and not mixed with other local operations */
+               T1 = trans[n][i];
+               if (!T1 || T1->qu[0]) continue;
+               j = T1->tpe[0];
+               if (T1->nxt && T1->atom&8)
+               { if (j == 5*DELTA)
+                 {     printf("warning: line %d ", srcln[i]);
+                       printf("mixed condition ");
+                       printf("(defeats reduction)\n");
+                       goto degrade;
+                 }
+                 for (T0 = T1; T0; T0 = T0->nxt)
+                 for (aa = 0; aa < 2; aa++)
+                 if  (T0->tpe[aa] && T0->tpe[aa] != j)
+                 {     printf("warning: line %d ", srcln[i]);
+                       printf("[%d-%d] mixed %stion ",
+                               T0->tpe[aa], j, 
+                               (j==5*DELTA)?"condi":"selec");
+                       printf("(defeats reduction)\n");
+                       printf("        '%s' <-> '%s'\n",
+                               T1->tp, T0->tp);
+                       goto degrade;
+               } }
+       }
+#endif
+       for (i = 1; i < m; i++)
+       {       T2 = trans[n][i];
+               if (!T2
+               ||  T2->nxt
+               ||  strncmp(T2->tp, ".(goto)", 7)
+               ||  !stopstate[n][i])
+                       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]);
+               for (i = 1; i < m; i++)
+                       reach[i] = 1;
+               tagtable(n, m, is, srcln, reach);
+       } else
+       for (i = 1; i < m; i++)
+       {       int nrelse;
+               if (strcmp(procname[n], ":never:") != 0)
+               {       for (T0 = trans[n][i]; T0; T0 = T0->nxt)
+                       {       if (T0->st == i
+                               && strcmp(T0->tp, "(1)") == 0)
+                               {       printf("error: proctype '%s' ",
+                                               procname[n]);
+                                       printf("line %d, state %d: has un",
+                                               srcln[i], i);
+                                       printf("conditional self-loop\n");
+                                       pan_exit(1);
+               }       }       }
+               nrelse = 0;
+               for (T0 = trans[n][i]; T0; T0 = T0->nxt)
+               {       if (strcmp(T0->tp, "else") == 0)
+                               nrelse++;
+               }
+               if (nrelse > 1)
+               {       printf("error: proctype '%s' state",
+                               procname[n]);
+                       printf(" %d, inherits %d", i, nrelse);
+                       printf(" 'else' stmnts\n");
+                       pan_exit(1);
+       }       }
+       if (!state_tables && strcmp(procname[n], ":never:") == 0)
+       {       int h = 0;
+               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;
+       }
+#ifndef LOOPSTATE
+       if (state_tables)
+#endif
+       do_dfs(n, m, is, srcln, reach, lstate);
+#ifdef T_REVERSE
+       /* process n, with m states, is=initial state -- reverse list */
+       if (!state_tables && strcmp(procname[n], ":never:") != 0)
+       {       for (i = 1; i < m; i++)
+               {       Trans *T4 = (Trans *) 0;
+                       T1 = (Trans *) 0;
+                       T2 = (Trans *) 0;
+                       T3 = (Trans *) 0;
+                       for (T0 = trans[n][i]; T0; T0 = T4)
+                       {       T4 = T0->nxt;
+                               if (strcmp(T0->tp, "else") == 0)
+                               {       T3 = T0;
+                                       T0->nxt = (Trans *) 0;
+                               } else
+                               {       T0->nxt = T1;
+                                       if (!T1) { T2 = T0; }
+                                       T1 = T0;
+                       }       }
+                       if (T2 && T3) { T2->nxt = T3; }
+                       trans[n][i] = T1; /* reversed -- else at end */
+       }       }
+#endif
+}
+void
+imed(Trans *T, int v, int n, int j)    /* set intermediate state */
+{      progstate[n][T->st] |= progstate[n][v];
+       accpstate[n][T->st] |= accpstate[n][v];
+       stopstate[n][T->st] |= stopstate[n][v];
+       mapstate[n][j] = T->st;
+}
+void
+tagtable(int n, int m, int is, short srcln[], uchar reach[])
+{      Trans *z;
+
+       if (is >= m || !trans[n][is]
+       ||  is <= 0 || reach[is] == 0)
+               return;
+       reach[is] = 0;
+       if (state_tables)
+       for (z = trans[n][is]; z; z = z->nxt)
+               crack(n, is, z, srcln);
+       for (z = trans[n][is]; z; z = z->nxt)
+       {
+#ifdef HAS_UNLESS
+               int i, j;
+#endif
+               tagtable(n, m, z->st, srcln, reach);
+#ifdef HAS_UNLESS
+               for (i = 0; i < HAS_UNLESS; i++)
+               {       j = trans[n][is]->escp[i];
+                       if (!j) break;
+                       tagtable(n, m, j, srcln, reach);
+               }
+#endif
+       }
+}
+void
+dfs_table(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])
+{      Trans *z;
+
+       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 */
+               {       lstate[is] = 1;
+                       reach[is] |= 8; /* recorded */
+                       if (state_tables)
+                       {       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)
+       {
+#ifdef HAS_UNLESS
+               int i, j;
+#endif
+               dfs_table(n, m, z->st, srcln, reach, lstate);
+#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, lstate);
+               }
+#endif
+       }
+       reach[is] &= ~16; /* no longer on stack */
+}
+void
+do_dfs(int n, int m, int is, short srcln[], uchar reach[], uchar lstate[])
+{      int i;
+       dfs_table(n, m, is, srcln, reach, lstate);
+       for (i = 0; i < m; i++)
+               reach[i] &= ~(4|8|16);
+}
+void
+crack(int n, int j, Trans *z, short srcln[])
+{      int i;
+
+       if (!z) return;
+       printf("        state %3d -(tr %3d)-> state %3d  ",
+               j, z->forw, z->st);
+       printf("[id %3d tp %3d", z->t_id, z->tpe[0]);
+       if (z->tpe[1]) printf(",%d", z->tpe[1]);
+#ifdef HAS_UNLESS
+       if (z->e_trans)
+               printf(" org %3d", z->e_trans);
+       else if (state_tables >= 2)
+       for (i = 0; i < HAS_UNLESS; i++)
+       {       if (!z->escp[i]) break;
+               printf(" esc %d", z->escp[i]);
+       }
+#endif
+       printf("]");
+       printf(" [%s%s%s%s%s] line %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]);
+       for (i = 0; z->tp[i]; i++)
+               if (z->tp[i] == '\n')
+                       printf("\\n");
+               else
+                       putchar(z->tp[i]);
+       if (z->qu[0])
+       {       printf("\t[");
+               for (i = 0; i < 6; i++)
+                       if (z->qu[i])
+                               printf("(%d,%d)",
+                               z->qu[i], z->ty[i]);
+               printf("]");
+       }
+       printf("\n");
+       fflush(stdout);
+}
+
+#ifdef VAR_RANGES
+#define BYTESIZE       32      /* 2^8 : 2^3 = 256:8 = 32 */
+
+typedef struct Vr_Ptr {
+       char    *nm;
+       uchar   vals[BYTESIZE];
+       struct Vr_Ptr *nxt;
+} Vr_Ptr;
+Vr_Ptr *ranges = (Vr_Ptr *) 0;
+
+void
+logval(char *s, int v)
+{      Vr_Ptr *tmp;
+
+       if (v<0 || v > 255) return;
+       for (tmp = ranges; tmp; tmp = tmp->nxt)
+               if (!strcmp(tmp->nm, s))
+                       goto found;
+       tmp = (Vr_Ptr *) emalloc(sizeof(Vr_Ptr));
+       tmp->nxt = ranges;
+       ranges = tmp;
+       tmp->nm = s;
+found:
+       tmp->vals[(v)/8] |= 1<<((v)%8);
+}
+
+void
+dumpval(uchar X[], int range)
+{      int w, x, i, j = -1;
+
+       for (w = i = 0; w < range; w++)
+       for (x = 0; x < 8; x++, i++)
+       {
+from:          if ((X[w] & (1<<x)))
+               {       printf("%d", i);
+                       j = i;
+                       goto upto;
+       }       }
+       return;
+       for (w = 0; w < range; w++)
+       for (x = 0; x < 8; x++, i++)
+       {
+upto:          if (!(X[w] & (1<<x)))
+               {       if (i-1 == j)
+                               printf(", ");
+                       else
+                               printf("-%d, ", i-1);
+                       goto from;
+       }       }
+       if (j >= 0 && j != 255)
+               printf("-255");
+}
+
+void
+dumpranges(void)
+{      Vr_Ptr *tmp;
+       printf("\nValues assigned within ");
+       printf("interval [0..255]:\n");
+       for (tmp = ranges; tmp; tmp = tmp->nxt)
+       {       printf("\t%s\t: ", tmp->nm);
+               dumpval(tmp->vals, BYTESIZE);
+               printf("\n");
+       }
+}
+#endif
diff --git a/trunk/verif/examples/run b/trunk/verif/examples/run
new file mode 100755 (executable)
index 0000000..5a47e64
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+../Spin/Src5.1.6/spin -a buffer.spin
+cc -DSAFETY -o pan pan.c
+./pan
diff --git a/trunk/verif/examples/run2 b/trunk/verif/examples/run2
new file mode 100755 (executable)
index 0000000..f69a545
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+../Spin/Src5.1.6/spin -t -p buffer.spin |less
diff --git a/trunk/verif/examples/run3 b/trunk/verif/examples/run3
new file mode 100755 (executable)
index 0000000..69ac091
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+../Spin/Src5.1.6/spin -a buffer.spin
+cc -o pan pan.c
+./pan
diff --git a/trunk/verif/examples/spin-increment.spin b/trunk/verif/examples/spin-increment.spin
new file mode 100644 (file)
index 0000000..b308fb5
--- /dev/null
@@ -0,0 +1,40 @@
+#define NUMPROCS 2
+
+byte counter = 0;
+byte progress[NUMPROCS];
+
+proctype incrementer(byte me)
+{
+  int temp;
+
+  temp = counter;
+  counter = temp + 1;
+  progress[me] = 1;
+}
+
+init {
+  int i = 0;
+  int sum = 0;
+
+  atomic {
+    i = 0;
+    do
+    :: i < NUMPROCS ->
+      progress[i] = 0;
+      run incrementer(i);
+      i++
+    :: i >= NUMPROCS -> break
+    od;
+  }
+  atomic {
+    i = 0;
+    sum = 0;
+    do
+    :: i < NUMPROCS ->
+      sum = sum + progress[i];
+      i++
+    :: i >= NUMPROCS -> break
+    od;
+    assert(sum < NUMPROCS || counter == NUMPROCS)
+  }
+}
diff --git a/trunk/verif/examples/spin-increment.spin.trail b/trunk/verif/examples/spin-increment.spin.trail
new file mode 100644 (file)
index 0000000..aff3eba
--- /dev/null
@@ -0,0 +1,22 @@
+-4:-4:-4
+1:0:4
+2:0:5
+3:0:7
+4:0:5
+5:0:7
+6:0:9
+7:0:13
+8:2:0
+9:1:0
+10:2:1
+11:2:2
+12:2:3
+13:1:1
+14:1:2
+15:1:3
+16:0:15
+17:0:17
+18:0:17
+19:0:20
+20:0:24
+21:0:25
diff --git a/trunk/verif/spin516.tar.gz b/trunk/verif/spin516.tar.gz
new file mode 100644 (file)
index 0000000..2843959
Binary files /dev/null and b/trunk/verif/spin516.tar.gz differ
This page took 0.951166 seconds and 4 git commands to generate.