xref: /plan9/sys/src/cmd/spin/dstep.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
1219b2ee8SDavid du Colombier /***** spin: dstep.c *****/
2219b2ee8SDavid du Colombier 
3312a1df1SDavid du Colombier /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
47dd7cddfSDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9312a1df1SDavid du Colombier /*             http://spinroot.com/                                       */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11219b2ee8SDavid du Colombier 
12219b2ee8SDavid du Colombier #include "spin.h"
13219b2ee8SDavid du Colombier #include "y.tab.h"
147dd7cddfSDavid du Colombier 
15*00d97012SDavid du Colombier #define MAXDSTEP	2048	/* was 512 */
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier char	*NextLab[64];
18219b2ee8SDavid du Colombier int	Level=0, GenCode=0, IsGuard=0, TestOnly=0;
19219b2ee8SDavid du Colombier 
207dd7cddfSDavid du Colombier static int	Tj=0, Jt=0, LastGoto=0;
217dd7cddfSDavid du Colombier static int	Tojump[MAXDSTEP], Jumpto[MAXDSTEP], Special[MAXDSTEP];
227dd7cddfSDavid du Colombier static void	putCode(FILE *, Element *, Element *, Element *, int);
237dd7cddfSDavid du Colombier 
24*00d97012SDavid du Colombier extern int	Pid, separate, OkBreak;
257dd7cddfSDavid du Colombier 
267dd7cddfSDavid du Colombier static void
Sourced(int n,int special)27219b2ee8SDavid du Colombier Sourced(int n, int special)
28219b2ee8SDavid du Colombier {	int i;
29219b2ee8SDavid du Colombier 	for (i = 0; i < Tj; i++)
30219b2ee8SDavid du Colombier 		if (Tojump[i] == n)
31219b2ee8SDavid du Colombier 			return;
327dd7cddfSDavid du Colombier 	if (Tj >= MAXDSTEP)
337dd7cddfSDavid du Colombier 		fatal("d_step sequence too long", (char *)0);
34219b2ee8SDavid du Colombier 	Special[Tj] = special;
35219b2ee8SDavid du Colombier 	Tojump[Tj++] = n;
36219b2ee8SDavid du Colombier }
37219b2ee8SDavid du Colombier 
387dd7cddfSDavid du Colombier static void
Dested(int n)39219b2ee8SDavid du Colombier Dested(int n)
40219b2ee8SDavid du Colombier {	int i;
41219b2ee8SDavid du Colombier 	for (i = 0; i < Tj; i++)
42219b2ee8SDavid du Colombier 		if (Tojump[i] == n)
43219b2ee8SDavid du Colombier 			return;
44219b2ee8SDavid du Colombier 	for (i = 0; i < Jt; i++)
45219b2ee8SDavid du Colombier 		if (Jumpto[i] == n)
46219b2ee8SDavid du Colombier 			return;
477dd7cddfSDavid du Colombier 	if (Jt >= MAXDSTEP)
487dd7cddfSDavid du Colombier 		fatal("d_step sequence too long", (char *)0);
49219b2ee8SDavid du Colombier 	Jumpto[Jt++] = n;
507dd7cddfSDavid du Colombier 	LastGoto = 1;
51219b2ee8SDavid du Colombier }
52219b2ee8SDavid du Colombier 
537dd7cddfSDavid du Colombier static void
Mopup(FILE * fd)54219b2ee8SDavid du Colombier Mopup(FILE *fd)
55312a1df1SDavid du Colombier {	int i, j;
567dd7cddfSDavid du Colombier 
57219b2ee8SDavid du Colombier 	for (i = 0; i < Jt; i++)
58219b2ee8SDavid du Colombier 	{	for (j = 0; j < Tj; j++)
597dd7cddfSDavid du Colombier 			if (Tojump[j] == Jumpto[i])
60219b2ee8SDavid du Colombier 				break;
61219b2ee8SDavid du Colombier 		if (j == Tj)
62*00d97012SDavid du Colombier 		{	char buf[16];
637dd7cddfSDavid du Colombier 			if (Jumpto[i] == OkBreak)
647dd7cddfSDavid du Colombier 			{	if (!LastGoto)
657dd7cddfSDavid du Colombier 				fprintf(fd, "S_%.3d_0:	/* break-dest */\n",
667dd7cddfSDavid du Colombier 					OkBreak);
677dd7cddfSDavid du Colombier 			} else {
68219b2ee8SDavid du Colombier 				sprintf(buf, "S_%.3d_0", Jumpto[i]);
69219b2ee8SDavid du Colombier 				non_fatal("goto %s breaks from d_step seq", buf);
707dd7cddfSDavid du Colombier 	}	}	}
71219b2ee8SDavid du Colombier 	for (j = 0; j < Tj; j++)
72219b2ee8SDavid du Colombier 	{	for (i = 0; i < Jt; i++)
737dd7cddfSDavid du Colombier 			if (Tojump[j] == Jumpto[i])
74219b2ee8SDavid du Colombier 				break;
75219b2ee8SDavid du Colombier #ifdef DEBUG
76219b2ee8SDavid du Colombier 		if (i == Jt && !Special[i])
777dd7cddfSDavid du Colombier 			fprintf(fd, "\t\t/* no goto's to S_%.3d_0 */\n",
78219b2ee8SDavid du Colombier 			Tojump[j]);
79219b2ee8SDavid du Colombier #endif
80219b2ee8SDavid du Colombier 	}
81219b2ee8SDavid du Colombier 	for (j = i = 0; j < Tj; j++)
827dd7cddfSDavid du Colombier 		if (Special[j])
83219b2ee8SDavid du Colombier 		{	Tojump[i] = Tojump[j];
84219b2ee8SDavid du Colombier 			Special[i] = 2;
857dd7cddfSDavid du Colombier 			if (i >= MAXDSTEP)
867dd7cddfSDavid du Colombier 			fatal("cannot happen (dstep.c)", (char *)0);
87219b2ee8SDavid du Colombier 			i++;
887dd7cddfSDavid du Colombier 		}
89219b2ee8SDavid du Colombier 	Tj = i;	/* keep only the global exit-labels */
90219b2ee8SDavid du Colombier 	Jt = 0;
91219b2ee8SDavid du Colombier }
92219b2ee8SDavid du Colombier 
937dd7cddfSDavid du Colombier static int
FirstTime(int n)94219b2ee8SDavid du Colombier FirstTime(int n)
95219b2ee8SDavid du Colombier {	int i;
96219b2ee8SDavid du Colombier 	for (i = 0; i < Tj; i++)
97219b2ee8SDavid du Colombier 		if (Tojump[i] == n)
98219b2ee8SDavid du Colombier 			return (Special[i] <= 1);
99219b2ee8SDavid du Colombier 	return 1;
100219b2ee8SDavid du Colombier }
101219b2ee8SDavid du Colombier 
1027dd7cddfSDavid du Colombier static void
illegal(Element * e,char * str)103219b2ee8SDavid du Colombier illegal(Element *e, char *str)
104219b2ee8SDavid du Colombier {
1057dd7cddfSDavid du Colombier 	printf("illegal operator in 'd_step:' '");
106219b2ee8SDavid du Colombier 	comment(stdout, e->n, 0);
107219b2ee8SDavid du Colombier 	printf("'\n");
1087dd7cddfSDavid du Colombier 	fatal("'%s'", str);
109219b2ee8SDavid du Colombier }
110219b2ee8SDavid du Colombier 
1117dd7cddfSDavid du Colombier static void
filterbad(Element * e)112219b2ee8SDavid du Colombier filterbad(Element *e)
113219b2ee8SDavid du Colombier {
114219b2ee8SDavid du Colombier 	switch (e->n->ntyp) {
115219b2ee8SDavid du Colombier 	case ASSERT:
116219b2ee8SDavid du Colombier 	case PRINT:
117219b2ee8SDavid du Colombier 	case 'c':
118219b2ee8SDavid du Colombier 		/* run cannot be completely undone
119219b2ee8SDavid du Colombier 		 * with sv_save-sv_restor
120219b2ee8SDavid du Colombier 		 */
121219b2ee8SDavid du Colombier 		if (any_oper(e->n->lft, RUN))
1227dd7cddfSDavid du Colombier 			illegal(e, "run operator in d_step");
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier 		/* remote refs inside d_step sequences
1257dd7cddfSDavid du Colombier 		 * would be okay, but they cannot always
1267dd7cddfSDavid du Colombier 		 * be interpreted by the simulator the
1277dd7cddfSDavid du Colombier 		 * same as by the verifier (e.g., for an
1287dd7cddfSDavid du Colombier 		 * error trail)
1297dd7cddfSDavid du Colombier 		 */
1307dd7cddfSDavid du Colombier 		if (any_oper(e->n->lft, 'p'))
1317dd7cddfSDavid du Colombier 			illegal(e, "remote reference in d_step");
132219b2ee8SDavid du Colombier 		break;
133219b2ee8SDavid du Colombier 	case '@':
134219b2ee8SDavid du Colombier 		illegal(e, "process termination");
135219b2ee8SDavid du Colombier 		break;
136219b2ee8SDavid du Colombier 	case D_STEP:
137219b2ee8SDavid du Colombier 		illegal(e, "nested d_step sequence");
138219b2ee8SDavid du Colombier 		break;
139219b2ee8SDavid du Colombier 	case ATOMIC:
140219b2ee8SDavid du Colombier 		illegal(e, "nested atomic sequence");
141219b2ee8SDavid du Colombier 		break;
142219b2ee8SDavid du Colombier 	default:
143219b2ee8SDavid du Colombier 		break;
144219b2ee8SDavid du Colombier 	}
145219b2ee8SDavid du Colombier }
146219b2ee8SDavid du Colombier 
1477dd7cddfSDavid du Colombier static int
CollectGuards(FILE * fd,Element * e,int inh)148219b2ee8SDavid du Colombier CollectGuards(FILE *fd, Element *e, int inh)
149219b2ee8SDavid du Colombier {	SeqList *h; Element *ee;
150219b2ee8SDavid du Colombier 
151219b2ee8SDavid du Colombier 	for (h = e->sub; h; h = h->nxt)
152219b2ee8SDavid du Colombier 	{	ee = huntstart(h->this->frst);
153219b2ee8SDavid du Colombier 		filterbad(ee);
154219b2ee8SDavid du Colombier 		switch (ee->n->ntyp) {
1557dd7cddfSDavid du Colombier 		case NON_ATOMIC:
1567dd7cddfSDavid du Colombier 			inh += CollectGuards(fd, ee->n->sl->this->frst, inh);
1577dd7cddfSDavid du Colombier 			break;
158219b2ee8SDavid du Colombier 		case  IF:
159219b2ee8SDavid du Colombier 			inh += CollectGuards(fd, ee, inh);
160219b2ee8SDavid du Colombier 			break;
161219b2ee8SDavid du Colombier 		case '.':
162219b2ee8SDavid du Colombier 			if (ee->nxt->n->ntyp == DO)
163219b2ee8SDavid du Colombier 				inh += CollectGuards(fd, ee->nxt, inh);
164219b2ee8SDavid du Colombier 			break;
165219b2ee8SDavid du Colombier 		case ELSE:
166219b2ee8SDavid du Colombier 			if (inh++ > 0) fprintf(fd, " || ");
167*00d97012SDavid du Colombier /* 4.2.5 */		if (!pid_is_claim(Pid))
168f3793cddSDavid du Colombier 				fprintf(fd, "(boq == -1 /* else */)");
169f3793cddSDavid du Colombier 			else
170219b2ee8SDavid du Colombier 				fprintf(fd, "(1 /* else */)");
171219b2ee8SDavid du Colombier 			break;
1727dd7cddfSDavid du Colombier 		case 'R':
173312a1df1SDavid du Colombier 			if (inh++ > 0) fprintf(fd, " || ");
174312a1df1SDavid du Colombier 			fprintf(fd, "("); TestOnly=1;
175312a1df1SDavid du Colombier 			putstmnt(fd, ee->n, ee->seqno);
176312a1df1SDavid du Colombier 			fprintf(fd, ")"); TestOnly=0;
177312a1df1SDavid du Colombier 			break;
1787dd7cddfSDavid du Colombier 		case 'r':
179312a1df1SDavid du Colombier 			if (inh++ > 0) fprintf(fd, " || ");
180312a1df1SDavid du Colombier 			fprintf(fd, "("); TestOnly=1;
181312a1df1SDavid du Colombier 			putstmnt(fd, ee->n, ee->seqno);
182312a1df1SDavid du Colombier 			fprintf(fd, ")"); TestOnly=0;
183312a1df1SDavid du Colombier 			break;
1847dd7cddfSDavid du Colombier 		case 's':
1857dd7cddfSDavid du Colombier 			if (inh++ > 0) fprintf(fd, " || ");
1867dd7cddfSDavid du Colombier 			fprintf(fd, "("); TestOnly=1;
187*00d97012SDavid du Colombier /* 4.2.1 */		if (!pid_is_claim(Pid)) fprintf(fd, "(boq == -1) && ");
1887dd7cddfSDavid du Colombier 			putstmnt(fd, ee->n, ee->seqno);
1897dd7cddfSDavid du Colombier 			fprintf(fd, ")"); TestOnly=0;
1907dd7cddfSDavid du Colombier 			break;
191219b2ee8SDavid du Colombier 		case 'c':
192219b2ee8SDavid du Colombier 			if (inh++ > 0) fprintf(fd, " || ");
193219b2ee8SDavid du Colombier 			fprintf(fd, "("); TestOnly=1;
194*00d97012SDavid du Colombier 			if (!pid_is_claim(Pid))
1957dd7cddfSDavid du Colombier 				fprintf(fd, "(boq == -1 && ");
196219b2ee8SDavid du Colombier 			putstmnt(fd, ee->n->lft, e->seqno);
197*00d97012SDavid du Colombier 			if (!pid_is_claim(Pid))
1987dd7cddfSDavid du Colombier 				fprintf(fd, ")");
199219b2ee8SDavid du Colombier 			fprintf(fd, ")"); TestOnly=0;
200219b2ee8SDavid du Colombier 			break;
2017dd7cddfSDavid du Colombier 	}	}
202219b2ee8SDavid du Colombier 	return inh;
203219b2ee8SDavid du Colombier }
204219b2ee8SDavid du Colombier 
205219b2ee8SDavid du Colombier int
putcode(FILE * fd,Sequence * s,Element * nxt,int justguards,int ln,int seqno)206312a1df1SDavid du Colombier putcode(FILE *fd, Sequence *s, Element *nxt, int justguards, int ln, int seqno)
2077dd7cddfSDavid du Colombier {	int isg=0; char buf[64];
208219b2ee8SDavid du Colombier 
209219b2ee8SDavid du Colombier 	NextLab[0] = "continue";
210219b2ee8SDavid du Colombier 	filterbad(s->frst);
211219b2ee8SDavid du Colombier 
212219b2ee8SDavid du Colombier 	switch (s->frst->n->ntyp) {
213219b2ee8SDavid du Colombier 	case UNLESS:
214219b2ee8SDavid du Colombier 		non_fatal("'unless' inside d_step - ignored", (char *) 0);
215312a1df1SDavid du Colombier 		return putcode(fd, s->frst->n->sl->this, nxt, 0, ln, seqno);
216219b2ee8SDavid du Colombier 	case NON_ATOMIC:
217312a1df1SDavid du Colombier 		(void) putcode(fd, s->frst->n->sl->this, ZE, 1, ln, seqno);
218219b2ee8SDavid du Colombier 		break;
219219b2ee8SDavid du Colombier 	case IF:
220219b2ee8SDavid du Colombier 		fprintf(fd, "if (!(");
221312a1df1SDavid du Colombier 		if (!CollectGuards(fd, s->frst, 0))	/* what about boq? */
222219b2ee8SDavid du Colombier 			fprintf(fd, "1");
223219b2ee8SDavid du Colombier 		fprintf(fd, "))\n\t\t\tcontinue;");
224219b2ee8SDavid du Colombier 		isg = 1;
225219b2ee8SDavid du Colombier 		break;
226219b2ee8SDavid du Colombier 	case '.':
227219b2ee8SDavid du Colombier 		if (s->frst->nxt->n->ntyp == DO)
228219b2ee8SDavid du Colombier 		{	fprintf(fd, "if (!(");
229219b2ee8SDavid du Colombier 			if (!CollectGuards(fd, s->frst->nxt, 0))
230219b2ee8SDavid du Colombier 				fprintf(fd, "1");
231219b2ee8SDavid du Colombier 			fprintf(fd, "))\n\t\t\tcontinue;");
232219b2ee8SDavid du Colombier 			isg = 1;
233219b2ee8SDavid du Colombier 		}
234219b2ee8SDavid du Colombier 		break;
2357dd7cddfSDavid du Colombier 	case 'R': /* <- can't really happen (it's part of a 'c') */
236219b2ee8SDavid du Colombier 		fprintf(fd, "if (!("); TestOnly=1;
237219b2ee8SDavid du Colombier 		putstmnt(fd, s->frst->n, s->frst->seqno);
238219b2ee8SDavid du Colombier 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
239219b2ee8SDavid du Colombier 		break;
240312a1df1SDavid du Colombier 	case 'r':
241312a1df1SDavid du Colombier 		fprintf(fd, "if (!("); TestOnly=1;
242312a1df1SDavid du Colombier 		putstmnt(fd, s->frst->n, s->frst->seqno);
243312a1df1SDavid du Colombier 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
244312a1df1SDavid du Colombier 		break;
245312a1df1SDavid du Colombier 	case 's':
246312a1df1SDavid du Colombier 		fprintf(fd, "if (");
247312a1df1SDavid du Colombier #if 1
248*00d97012SDavid du Colombier /* 4.2.1 */	if (!pid_is_claim(Pid)) fprintf(fd, "(boq != -1) || ");
249312a1df1SDavid du Colombier #endif
250312a1df1SDavid du Colombier 		fprintf(fd, "!("); TestOnly=1;
251312a1df1SDavid du Colombier 		putstmnt(fd, s->frst->n, s->frst->seqno);
252312a1df1SDavid du Colombier 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
253312a1df1SDavid du Colombier 		break;
254219b2ee8SDavid du Colombier 	case 'c':
2557dd7cddfSDavid du Colombier 		fprintf(fd, "if (!(");
256*00d97012SDavid du Colombier 		if (!pid_is_claim(Pid)) fprintf(fd, "boq == -1 && ");
2577dd7cddfSDavid du Colombier 		TestOnly=1;
258219b2ee8SDavid du Colombier 		putstmnt(fd, s->frst->n->lft, s->frst->seqno);
259219b2ee8SDavid du Colombier 		fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0;
260219b2ee8SDavid du Colombier 		break;
261312a1df1SDavid du Colombier 	case ELSE:
262312a1df1SDavid du Colombier 		fprintf(fd, "if (boq != -1 || (");
263312a1df1SDavid du Colombier 		if (separate != 2) fprintf(fd, "trpt->");
264312a1df1SDavid du Colombier 		fprintf(fd, "o_pm&1))\n\t\t\tcontinue;");
265312a1df1SDavid du Colombier 		break;
2667dd7cddfSDavid du Colombier 	case ASGN:	/* new 3.0.8 */
2677dd7cddfSDavid du Colombier 		fprintf(fd, "IfNotBlocked");
2687dd7cddfSDavid du Colombier 		break;
269219b2ee8SDavid du Colombier 	}
270219b2ee8SDavid du Colombier 	if (justguards) return 0;
271219b2ee8SDavid du Colombier 
272312a1df1SDavid du Colombier 	fprintf(fd, "\n\t\tsv_save();\n\t\t");
273312a1df1SDavid du Colombier #if 1
274312a1df1SDavid du Colombier 	fprintf(fd, "reached[%d][%d] = 1;\n\t\t", Pid, seqno);
275312a1df1SDavid du Colombier 	fprintf(fd, "reached[%d][t->st] = 1;\n\t\t", Pid);	/* true next state */
276312a1df1SDavid du Colombier 	fprintf(fd, "reached[%d][tt] = 1;\n", Pid);		/* true current state */
277312a1df1SDavid du Colombier #endif
2787dd7cddfSDavid du Colombier 	sprintf(buf, "Uerror(\"block in d_step seq, line %d\")", ln);
2797dd7cddfSDavid du Colombier 	NextLab[0] = buf;
280219b2ee8SDavid du Colombier 	putCode(fd, s->frst, s->extent, nxt, isg);
281219b2ee8SDavid du Colombier 
282219b2ee8SDavid du Colombier 	if (nxt)
283312a1df1SDavid du Colombier 	{	extern Symbol *Fname;
284312a1df1SDavid du Colombier 		extern int lineno;
285312a1df1SDavid du Colombier 
286312a1df1SDavid du Colombier 		if (FirstTime(nxt->Seqno)
287219b2ee8SDavid du Colombier 		&& (!(nxt->status & DONE2) || !(nxt->status & D_ATOM)))
288219b2ee8SDavid du Colombier 		{	fprintf(fd, "S_%.3d_0: /* 1 */\n", nxt->Seqno);
289219b2ee8SDavid du Colombier 			nxt->status |= DONE2;
290219b2ee8SDavid du Colombier 			LastGoto = 0;
291219b2ee8SDavid du Colombier 		}
292219b2ee8SDavid du Colombier 		Sourced(nxt->Seqno, 1);
293312a1df1SDavid du Colombier 		lineno = ln;
294312a1df1SDavid du Colombier 		Fname = nxt->n->fn;
295219b2ee8SDavid du Colombier 		Mopup(fd);
296219b2ee8SDavid du Colombier 	}
297219b2ee8SDavid du Colombier 	unskip(s->frst->seqno);
298219b2ee8SDavid du Colombier 	return LastGoto;
299219b2ee8SDavid du Colombier }
300219b2ee8SDavid du Colombier 
3017dd7cddfSDavid du Colombier static void
putCode(FILE * fd,Element * f,Element * last,Element * next,int isguard)302219b2ee8SDavid du Colombier putCode(FILE *fd, Element *f, Element *last, Element *next, int isguard)
303219b2ee8SDavid du Colombier {	Element *e, *N;
304219b2ee8SDavid du Colombier 	SeqList *h; int i;
3057dd7cddfSDavid du Colombier 	char NextOpt[64];
3067dd7cddfSDavid du Colombier 	static int bno = 0;
307219b2ee8SDavid du Colombier 
308219b2ee8SDavid du Colombier 	for (e = f; e; e = e->nxt)
309219b2ee8SDavid du Colombier 	{	if (e->status & DONE2)
310219b2ee8SDavid du Colombier 			continue;
311219b2ee8SDavid du Colombier 		e->status |= DONE2;
312219b2ee8SDavid du Colombier 
313219b2ee8SDavid du Colombier 		if (!(e->status & D_ATOM))
314219b2ee8SDavid du Colombier 		{	if (!LastGoto)
3157dd7cddfSDavid du Colombier 			{	fprintf(fd, "\t\tgoto S_%.3d_0;\n",
3167dd7cddfSDavid du Colombier 					e->Seqno);
317219b2ee8SDavid du Colombier 				Dested(e->Seqno);
318219b2ee8SDavid du Colombier 			}
319219b2ee8SDavid du Colombier 			break;
320219b2ee8SDavid du Colombier 		}
321219b2ee8SDavid du Colombier 		fprintf(fd, "S_%.3d_0: /* 2 */\n", e->Seqno);
3227dd7cddfSDavid du Colombier 		LastGoto = 0;
323219b2ee8SDavid du Colombier 		Sourced(e->Seqno, 0);
324219b2ee8SDavid du Colombier 
325219b2ee8SDavid du Colombier 		if (!e->sub)
326219b2ee8SDavid du Colombier 		{	filterbad(e);
327219b2ee8SDavid du Colombier 			switch (e->n->ntyp) {
328219b2ee8SDavid du Colombier 			case NON_ATOMIC:
329219b2ee8SDavid du Colombier 				h = e->n->sl;
3307dd7cddfSDavid du Colombier 				putCode(fd, h->this->frst,
3317dd7cddfSDavid du Colombier 					h->this->extent, e->nxt, 0);
332219b2ee8SDavid du Colombier 				break;
333219b2ee8SDavid du Colombier 			case BREAK:
334219b2ee8SDavid du Colombier 				if (LastGoto) break;
3357dd7cddfSDavid du Colombier 				if (e->nxt)
3367dd7cddfSDavid du Colombier 				{	i = target( huntele(e->nxt,
337312a1df1SDavid du Colombier 						e->status, -1))->Seqno;
3387dd7cddfSDavid du Colombier 					fprintf(fd, "\t\tgoto S_%.3d_0;	", i);
3397dd7cddfSDavid du Colombier 					fprintf(fd, "/* 'break' */\n");
340219b2ee8SDavid du Colombier 					Dested(i);
3417dd7cddfSDavid du Colombier 				} else
3427dd7cddfSDavid du Colombier 				{	if (next)
3437dd7cddfSDavid du Colombier 					{	fprintf(fd, "\t\tgoto S_%.3d_0;",
3447dd7cddfSDavid du Colombier 							next->Seqno);
3457dd7cddfSDavid du Colombier 						fprintf(fd, " /* NEXT */\n");
3467dd7cddfSDavid du Colombier 						Dested(next->Seqno);
3477dd7cddfSDavid du Colombier 					} else
3487dd7cddfSDavid du Colombier 					fatal("cannot interpret d_step", 0);
3497dd7cddfSDavid du Colombier 				}
350219b2ee8SDavid du Colombier 				break;
351219b2ee8SDavid du Colombier 			case GOTO:
352219b2ee8SDavid du Colombier 				if (LastGoto) break;
3537dd7cddfSDavid du Colombier 				i = huntele( get_lab(e->n,1),
354312a1df1SDavid du Colombier 					e->status, -1)->Seqno;
3557dd7cddfSDavid du Colombier 				fprintf(fd, "\t\tgoto S_%.3d_0;	", i);
3567dd7cddfSDavid du Colombier 				fprintf(fd, "/* 'goto' */\n");
357219b2ee8SDavid du Colombier 				Dested(i);
358219b2ee8SDavid du Colombier 				break;
359219b2ee8SDavid du Colombier 			case '.':
360219b2ee8SDavid du Colombier 				if (LastGoto) break;
3617dd7cddfSDavid du Colombier 				if (e->nxt && (e->nxt->status & DONE2))
362219b2ee8SDavid du Colombier 				{	i = e->nxt?e->nxt->Seqno:0;
3637dd7cddfSDavid du Colombier 					fprintf(fd, "\t\tgoto S_%.3d_0;", i);
3647dd7cddfSDavid du Colombier 					fprintf(fd, " /* '.' */\n");
365219b2ee8SDavid du Colombier 					Dested(i);
366219b2ee8SDavid du Colombier 				}
367219b2ee8SDavid du Colombier 				break;
368219b2ee8SDavid du Colombier 			default:
369219b2ee8SDavid du Colombier 				putskip(e->seqno);
370219b2ee8SDavid du Colombier 				GenCode = 1; IsGuard = isguard;
371219b2ee8SDavid du Colombier 				fprintf(fd, "\t\t");
372219b2ee8SDavid du Colombier 				putstmnt(fd, e->n, e->seqno);
373219b2ee8SDavid du Colombier 				fprintf(fd, ";\n");
374219b2ee8SDavid du Colombier 				GenCode = IsGuard = isguard = LastGoto = 0;
375219b2ee8SDavid du Colombier 				break;
376219b2ee8SDavid du Colombier 			}
377219b2ee8SDavid du Colombier 			i = e->nxt?e->nxt->Seqno:0;
378219b2ee8SDavid du Colombier 			if (e->nxt && e->nxt->status & DONE2 && !LastGoto)
3797dd7cddfSDavid du Colombier 			{	fprintf(fd, "\t\tgoto S_%.3d_0; ", i);
3807dd7cddfSDavid du Colombier 				fprintf(fd, "/* ';' */\n");
381219b2ee8SDavid du Colombier 				Dested(i);
382219b2ee8SDavid du Colombier 				break;
383219b2ee8SDavid du Colombier 			}
384219b2ee8SDavid du Colombier 		} else
385219b2ee8SDavid du Colombier 		{	for (h = e->sub, i=1; h; h = h->nxt, i++)
3867dd7cddfSDavid du Colombier 			{	sprintf(NextOpt, "goto S_%.3d_%d",
3877dd7cddfSDavid du Colombier 					e->Seqno, i);
388219b2ee8SDavid du Colombier 				NextLab[++Level] = NextOpt;
389f3793cddSDavid du Colombier 				N = (e->n && e->n->ntyp == DO) ? e : e->nxt;
3907dd7cddfSDavid du Colombier 				putCode(fd, h->this->frst,
3917dd7cddfSDavid du Colombier 					h->this->extent, N, 1);
392219b2ee8SDavid du Colombier 				Level--;
393219b2ee8SDavid du Colombier 				fprintf(fd, "%s: /* 3 */\n", &NextOpt[5]);
3947dd7cddfSDavid du Colombier 				LastGoto = 0;
395219b2ee8SDavid du Colombier 			}
396219b2ee8SDavid du Colombier 			if (!LastGoto)
3977dd7cddfSDavid du Colombier 			{	fprintf(fd, "\t\tUerror(\"blocking sel ");
3987dd7cddfSDavid du Colombier 				fprintf(fd, "in d_step (nr.%d, near line %d)\");\n",
3997dd7cddfSDavid du Colombier 				bno++, (e->n)?e->n->ln:0);
400219b2ee8SDavid du Colombier 				LastGoto = 0;
401219b2ee8SDavid du Colombier 			}
402219b2ee8SDavid du Colombier 		}
403219b2ee8SDavid du Colombier 		if (e == last)
404219b2ee8SDavid du Colombier 		{	if (!LastGoto && next)
4057dd7cddfSDavid du Colombier 			{	fprintf(fd, "\t\tgoto S_%.3d_0;\n",
4067dd7cddfSDavid du Colombier 					next->Seqno);
407219b2ee8SDavid du Colombier 				Dested(next->Seqno);
408219b2ee8SDavid du Colombier 			}
409219b2ee8SDavid du Colombier 			break;
410219b2ee8SDavid du Colombier 	}	}
411219b2ee8SDavid du Colombier }
412