#!/bin/sh
########################################################
# The main SPIN source tarfile are updated only        #
# between major new releases (e.g., from 2.0 to 2.1).  #
#                                                      #
# Minor releases, for bug fixes or minor changes,      #
# that do not affect overall functionality, are        #
# distributed through changes in this Upgrades file.   #
#                                                      #
# To apply all the necessary fixes, and no more,       #
# for precisely the version of SPIN that you now have  #
# installed (even if you have already applied previous #
# upgrades in the same manner) do this:                #
# 1. go to the directory with the SPIN sources         #
#       cd Src                                         #
# 2. execute this file with the bourne shell           #
#       /bin/sh ../upgrades                            #
# 3. recompile the spin executable                     #
#       make                                           #
# 4. reinstall the executable, for instance as:        #
#       cp spin /usr/bin/spin                          #
########################################################

if [ ! -r spin.h ]
then
	echo "--> Cannot find file spin.h"
	echo "--> Please cd to the SPIN  Src  directory from the"
	echo "--> distribution and execute this program from there."
	exit 1
fi

v_id=`grep Version spin.h | /usr/bin/awk '	{ print $5 }'`
o_id=$v_id

while true
do
case $v_id in

2.1)
	echo "updating pangen1.c to version 2.1.1"
	/bin/ed - pangen1.c << '-*-END-*-'
215a
		if (sp->type == STRUCT)
		{	/* struct may contain a chan */
			char gather[128];
			char pregat[128]; Symbol *z = (Symbol *)0;
			int nc, ov=0, last;
			sprintf(pregat, "%s%s", s, sp->name);
			do {
				strcpy(gather, pregat);
				nc = fill_struct(sp, 0, ov, gather, &z);
				if (z && last != z->Nid)
				{	last = z->Nid;
					if (nc < 0)
					do_var(INIV, gather, z);
				}
				ov = -nc;
			} while (nc < 0);
			break;
		}
.
w
q
-*-END-*-

	echo "updating pangen2.c to version 2.1.1"
	/bin/ed - pangen2.c << '-*-END-*-'
329c
				ov = -nc;
.
327c
					Done_case(gather, z);
.
238c
			fprintf(tc, "%s(%s%s", BB[j].CC, nm, z->name);
.
230a
	int nid = z->Nid;
	int qln = z->nel;
.
229c
Done_case(char *nm, Symbol *z)
.
w
q
-*-END-*-

	echo "updating structures.c to version 2.1.1"
	/bin/ed - structures.c << '-*-END-*-'
414c
			return -nv-1;
.
410,412c
		{	strcat(gather, ".");
.
w
q
-*-END-*-

	echo "updating spin.h to version 2.1.1"
	/bin/ed - spin.h << '-*-END-*-'
16c
#define Version	"Spin Version 2.1.1 -- 17 February 1995"
.
w
q
-*-END-*-

	v_id=2.1.1
	;;

2.1.1)

	echo "updating main.c to version 2.2"
	/bin/ed - main.c << '-*-END-*-'
280a
	case PNAME:	printf("process name"); break;
.
63a
			  printf("\t-i interactive (random simulation)\n");
.
45a
		case 'i': Interactive = 1; break;
.
30a
int	Interactive = 0;
.
w
q
-*-END-*-
	echo "updating pangen1.h to version 2.2"
	/bin/ed - pangen1.h << '-*-END-*-'
1884a
	"#endif",
	"#ifdef REACH",
	"	tmp->D = depth;",
.
1862a
	"#ifdef REACH",
	"			if (tmp->D > depth)",
	"			{	tmp->D = depth;",
		"#ifdef CHECK",
	"			printf(\"\t\tReVisiting (from smaller depth)\\n\");",
		"#endif",
	"				nstates--;",
	"				return 0;",
	"			}",
	"#endif",
.
1167a
	"#if defined(BITSTATE) && defined(REACH)",
	"	fprintf(efd, \"warning: -DREACH has no effect in a bitstate search\\n\");",
	"#endif",
.
w
q
-*-END-*-
	echo "updating pangen2.c to version 2.2"
	/bin/ed - pangen2.c << '-*-END-*-'
1115c
					putname(fd, "[((Q0 *)qptr(", now->lft, m, "-1))->_t]");
.
w
q
-*-END-*-
	echo "updating pangen2.h to version 2.2"
	/bin/ed - pangen2.h << '-*-END-*-'
47a
	"#ifdef REACH",
	"	unsigned D;",
	"#endif",
.
w
q
-*-END-*-
	echo "updating pangen4.c to version 2.2"
	/bin/ed - pangen4.c << '-*-END-*-'
63c
				putname(tb, "[((Q0 *)qptr(", now->lft, m, "-1))->_t]");
.
w
q
-*-END-*-
	echo "updating run.c to version 2.2"
	/bin/ed - run.c << '-*-END-*-'
118,119c
			}	}
.
116c
						printf("\tEscape taken\n");
.
113,114c
			{	if (g = eval_sub(x->this->frst))
.
108,111c
					printf("]\n");
			}	}
.
106c
				{	printf("\t[");
.
104c
				printf("] - can be escaped by\n");
.
102c
			{	printf("Statement [");
.
100d
71,73c
			if (i >= k)
			{	if (f = eval_sub(z->this->frst))
					return f;
				else if (Interactive)
				{	printf("\tunexecutable\n");
					return ZE;
			}	}
.
61,63c
		{	j++;
			if (Interactive && !SubChoice && z->this->frst)
			{	printf("\tchoice %d: ", j);
				comment(stdout, z->this->frst->n, 0);
				printf("\n");
		}	}
		if (Interactive)
		{	if (!SubChoice)
			{	if (xspin)
					printf("Make Selection %d\n\n", j);
				else
					printf("Select [0-%d]: ", j);
				fflush(stdout);
				scanf("%d", &k);
			} else
			{	k = SubChoice;
				SubChoice = 0;
			}
			if (k < 1 || k > j)
			{	printf("\tchoice outside range\n");
				return ZE;
			}
			k--;
		} else
			k = Rand()%j;	/* nondeterminism */
.
59a
		if (Interactive && !SubChoice)
		{	printf("Select stmnt (");
			whoruns(0); printf(")\n");
			printf("\tchoice 0: other process\n");
		}
.
18c
extern int	Rvous, lineno, Tval, Interactive, SubChoice;
extern int	TstOnly, verbose, s_trail, xspin;
.
96,98c
				if (!Interactive)
				{	z = (z->nxt)?z->nxt:e->sub;
					continue;
			}	}
.
w
q
-*-END-*-
	echo "updating sched.c to version 2.2"
	/bin/ed - sched.c << '-*-END-*-'
233,237c
		if (Interactive)
		{
try_again:		printf("Select a statement\n");
			for (X = run, k = 1; X; X = X->nxt)
			{	if (X->pid > 255) break;
				Choices[X->pid] = 0;
				if (!X->pc)
					continue;
				Choices[X->pid] = k;
				if (!X->pc->sub && X->pc->n)
				{	printf("\tchoice %d: ", k++);
					p_talk(X->pc, 0);
					printf(" [");
					comment(stdout, X->pc->n, 0);
					printf("]\n");
				} else
				for (z = X->pc->sub, j=0; z; z = z->nxt)
				{	Element *y = z->this->frst;
					if (!y) continue;

					printf("\tchoice %d: ", k++);
					p_talk(X->pc, 0);
					printf(" [");
					comment(stdout, y->n, 0);
					printf("]\n");
			}	}
			X = run;
			if (xspin)
				printf("Make Selection %d\n\n", k-1);
			else
				printf("Select [1-%d]: ", k-1);
			fflush(stdout);
			scanf("%d", &j);
			if (j < 1 || j >= k)
			{	printf("\tchoice is outside range\n");
				goto try_again;
			}
			SubChoice = 0;
			for (X = run; X; X = X->nxt)
			{	if (!X->nxt
				||   X->nxt->pid > 255
				||   j < Choices[X->nxt->pid])
				{
					SubChoice = 1+j-Choices[X->pid];
					break;
				}
			}
		} else
		{	j = (int) Rand()%(nproc-nstop);
			while (j-- >= 0)
			{	X = X->nxt;
				if (!X) X = run;
		}	}
.
157c
	SeqList *z;
	int j, k;
	short Choices[256];
.
28c
int		Rvous=0, depth=0, nrRdy=0, SubChoice;
.
20c
extern int	has_enabled, u_sync, Elcnt, Interactive;
.
231c
					Tval = 1;
.
229c
			{	if (!Interactive && p_blocked(X->pid))
.
225c
				if (!Interactive) Tval = 0;
.
219c
				nstop++;
.
205c
			oX->pc = e; LastX = X;
			if (!Interactive) Tval = 0;
.
182a
	if (Interactive) Tval = 1;

.
w
q
-*-END-*-
	echo "updating spin.h to version 2.2"
	/bin/ed - spin.h << '-*-END-*-'
16c
#define Version	"Spin Version 2.2 -- 22 February 1995"
.
w
q
-*-END-*-
	v_id=2.2
	;;

2.2)
	echo "updating run.c to version 2.2.1"
	/bin/ed - run.c << '-*-END-*-'
310a
}

/* new */

int
Enabled1(Lextok *n)
{	int i; int v = verbose;

	if (n)
	switch (n->ntyp) {
	default:	/* side-effect free */
		return eval(n);

	case PRINT:  case  ASGN:
	case ASSERT: case   RUN:
		return 1;

	case 's':	/* guesses for rv */
		if (q_is_sync(n)) return !Rvous;
		return (!qfull(n));
	case 'r':	/* guesses for rv */
		if (q_is_sync(n)) return Rvous;
		n->ntyp = 'R'; verbose = 0;
		i = eval(n);
		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 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;
	}
	if (Rvous)
	{	if (e->n->ntyp != 'r'
		||  !q_is_sync(e->n))
			return 0;
		return Enabled1(e->n);
	}
	for (z = e->esc; z; z = z->nxt)
	{	if (Enabled0(z->this->frst))
			return 1;
	}
	return Enabled1(e->n);
.
69a
				if (!Enabled0(z->this->frst->n))
					printf("unexecutable, ");
.
68c
			if (Interactive
			&& !SubChoice
			&& z->this->frst
			&& (xspin || Enabled0(z->this->frst->n)))
.
371,376d
327c
		verbose = 0;
		i = eval(n);
		verbose = v;
		return i;
.
w
q
-*-END-*-
	echo "updating sched.c to version 2.2.1"
	/bin/ed - sched.c << '-*-END-*-'
259a
					if (!Enabled0(y))
						printf(" unexecutable,");
.
257a
					if (!xspin && !Enabled0(y))
					{	k++;
						continue;
					}
.
249a
					if (!Enabled0(X->pc))
						printf(" unexecutable,");
.
248c
				{	if (!xspin && !Enabled0(X->pc))
					{	k++;
						continue;
					}
					printf("\tchoice %d: ", k++);
.
246a
				X->pc = silent_moves(X->pc);
.
151a
Element *
silent_moves(Element *e)
{	Element *f;

	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 e->nxt;
	}
	return e;
}

.
w
q
-*-END-*-
	echo "updating spin.h to version 2.2.1"
	/bin/ed - spin.h << '-*-END-*-'
19c
	unsigned short	ntyp;	/* node type */
.
16c
#define Version	"Spin Version 2.2.1 -- 23 February 1995"
.
w
q
-*-END-*-
	v_id=2.2.1
	;;

2.2.1)
	echo "updating run.c to version 2.2.2"
	/bin/ed - run.c << '-*-END-*-'
73c
				if (!Enabled0(z->this->frst))
.
71c
			&& (xspin || Enabled0(z->this->frst)))
.
w
q
-*-END-*-
	echo "updating spin.h to version 2.2.2"
	/bin/ed - spin.h << '-*-END-*-'
194a
int Enabled0(Element *);
int Enabled1(Lextok *);
.
16c
#define Version	"Spin Version 2.2.2 -- 24 February 1995"
.
w
q
-*-END-*-
	v_id=2.2.2
	;;

2.2.2)
	case $o_id in
	2.2.2)
		echo "The SPIN sources are already up to date."
		echo "--> no further action is needed."
		;;
	*)
		echo "The SPIN sources are now up to date."
		echo "--> type make and reinstall spin."
		;;
	esac
	exit 0
	;;
*)
	echo "Outdated version ($v_id) of SPIN."
	echo "This version cannot be upgraded with this script."
	echo "--> retrieve latest version via anonymous ftp"
	echo "--> from netlib.att.com in directory /netlib/spin"
	exit 1
	;;
esac
done

echo "Error: cannot get here; complain to gerard@research.att.com"
exit 2
