xref: /plan9/sys/src/cmd/spin/flow.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
1219b2ee8SDavid du Colombier /***** spin: flow.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 
157dd7cddfSDavid du Colombier extern Symbol	*Fname;
16*00d97012SDavid du Colombier extern int	nr_errs, lineno, verbose, in_for;
17*00d97012SDavid du Colombier extern short	has_unless, has_badelse, has_xu;
18*00d97012SDavid du Colombier extern char CurScope[MAXSCOPESZ];
19219b2ee8SDavid du Colombier 
20219b2ee8SDavid du Colombier Element *Al_El = ZE;
21219b2ee8SDavid du Colombier Label	*labtab = (Label *) 0;
227dd7cddfSDavid du Colombier int	Unique = 0, Elcnt = 0, DstepStart = -1;
23*00d97012SDavid du Colombier int	initialization_ok = 1;
24219b2ee8SDavid du Colombier 
257dd7cddfSDavid du Colombier static Lbreak	*breakstack = (Lbreak *) 0;
267dd7cddfSDavid du Colombier static Lextok	*innermost;
277dd7cddfSDavid du Colombier static SeqList	*cur_s = (SeqList *) 0;
287dd7cddfSDavid du Colombier static int	break_id=0;
297dd7cddfSDavid du Colombier 
307dd7cddfSDavid du Colombier static Element	*if_seq(Lextok *);
317dd7cddfSDavid du Colombier static Element	*new_el(Lextok *);
327dd7cddfSDavid du Colombier static Element	*unless_seq(Lextok *);
337dd7cddfSDavid du Colombier static void	add_el(Element *, Sequence *);
347dd7cddfSDavid du Colombier static void	attach_escape(Sequence *, Sequence *);
357dd7cddfSDavid du Colombier static void	mov_lab(Symbol *, Element *, Element *);
367dd7cddfSDavid du Colombier static void	walk_atomic(Element *, Element *, int);
37219b2ee8SDavid du Colombier 
38219b2ee8SDavid du Colombier void
open_seq(int top)39219b2ee8SDavid du Colombier open_seq(int top)
40219b2ee8SDavid du Colombier {	SeqList *t;
41219b2ee8SDavid du Colombier 	Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
42219b2ee8SDavid du Colombier 
43219b2ee8SDavid du Colombier 	t = seqlist(s, cur_s);
44219b2ee8SDavid du Colombier 	cur_s = t;
45*00d97012SDavid du Colombier 	if (top)
46*00d97012SDavid du Colombier 	{	Elcnt = 1;
47*00d97012SDavid du Colombier 		initialization_ok = 1;
48*00d97012SDavid du Colombier 	}
49219b2ee8SDavid du Colombier }
50219b2ee8SDavid du Colombier 
51219b2ee8SDavid du Colombier void
rem_Seq(void)52219b2ee8SDavid du Colombier rem_Seq(void)
53219b2ee8SDavid du Colombier {
54219b2ee8SDavid du Colombier 	DstepStart = Unique;
55219b2ee8SDavid du Colombier }
56219b2ee8SDavid du Colombier 
57219b2ee8SDavid du Colombier void
unrem_Seq(void)58219b2ee8SDavid du Colombier unrem_Seq(void)
59219b2ee8SDavid du Colombier {
60219b2ee8SDavid du Colombier 	DstepStart = -1;
61219b2ee8SDavid du Colombier }
62219b2ee8SDavid du Colombier 
637dd7cddfSDavid du Colombier static int
Rjumpslocal(Element * q,Element * stop)64219b2ee8SDavid du Colombier Rjumpslocal(Element *q, Element *stop)
65219b2ee8SDavid du Colombier {	Element *lb, *f;
66219b2ee8SDavid du Colombier 	SeqList *h;
67219b2ee8SDavid du Colombier 
68219b2ee8SDavid du Colombier 	/* allow no jumps out of a d_step sequence */
69219b2ee8SDavid du Colombier 	for (f = q; f && f != stop; f = f->nxt)
70219b2ee8SDavid du Colombier 	{	if (f && f->n && f->n->ntyp == GOTO)
71219b2ee8SDavid du Colombier 		{	lb = get_lab(f->n, 0);
72219b2ee8SDavid du Colombier 			if (!lb || lb->Seqno < DstepStart)
73219b2ee8SDavid du Colombier 			{	lineno = f->n->ln;
74219b2ee8SDavid du Colombier 				Fname = f->n->fn;
75219b2ee8SDavid du Colombier 				return 0;
76219b2ee8SDavid du Colombier 		}	}
77219b2ee8SDavid du Colombier 		for (h = f->sub; h; h = h->nxt)
78219b2ee8SDavid du Colombier 		{	if (!Rjumpslocal(h->this->frst, h->this->last))
79219b2ee8SDavid du Colombier 				return 0;
80219b2ee8SDavid du Colombier 
81219b2ee8SDavid du Colombier 	}	}
82219b2ee8SDavid du Colombier 	return 1;
83219b2ee8SDavid du Colombier }
84219b2ee8SDavid du Colombier 
85219b2ee8SDavid du Colombier void
cross_dsteps(Lextok * a,Lextok * b)86219b2ee8SDavid du Colombier cross_dsteps(Lextok *a, Lextok *b)
87219b2ee8SDavid du Colombier {
88219b2ee8SDavid du Colombier 	if (a && b
89219b2ee8SDavid du Colombier 	&&  a->indstep != b->indstep)
90219b2ee8SDavid du Colombier 	{	lineno = a->ln;
91219b2ee8SDavid du Colombier 		Fname  = a->fn;
92219b2ee8SDavid du Colombier 		fatal("jump into d_step sequence", (char *) 0);
93219b2ee8SDavid du Colombier 	}
94219b2ee8SDavid du Colombier }
95219b2ee8SDavid du Colombier 
967dd7cddfSDavid du Colombier int
is_skip(Lextok * n)977dd7cddfSDavid du Colombier is_skip(Lextok *n)
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier 	return (n->ntyp == PRINT
100312a1df1SDavid du Colombier 	||	n->ntyp == PRINTM
1017dd7cddfSDavid du Colombier 	||	(n->ntyp == 'c'
1027dd7cddfSDavid du Colombier 		&& n->lft
1037dd7cddfSDavid du Colombier 		&& n->lft->ntyp == CONST
1047dd7cddfSDavid du Colombier 		&& n->lft->val  == 1));
1057dd7cddfSDavid du Colombier }
1067dd7cddfSDavid du Colombier 
1077dd7cddfSDavid du Colombier void
check_sequence(Sequence * s)1087dd7cddfSDavid du Colombier check_sequence(Sequence *s)
1097dd7cddfSDavid du Colombier {	Element *e, *le = ZE;
1107dd7cddfSDavid du Colombier 	Lextok *n;
1117dd7cddfSDavid du Colombier 	int cnt = 0;
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	for (e = s->frst; e; le = e, e = e->nxt)
1147dd7cddfSDavid du Colombier 	{	n = e->n;
1157dd7cddfSDavid du Colombier 		if (is_skip(n) && !has_lab(e, 0))
1167dd7cddfSDavid du Colombier 		{	cnt++;
117312a1df1SDavid du Colombier 			if (cnt > 1
118312a1df1SDavid du Colombier 			&&  n->ntyp != PRINT
119312a1df1SDavid du Colombier 			&&  n->ntyp != PRINTM)
1207dd7cddfSDavid du Colombier 			{	if (verbose&32)
121*00d97012SDavid du Colombier 					printf("spin: %s:%d, redundant skip\n",
122*00d97012SDavid du Colombier 						n->fn->name, n->ln);
123312a1df1SDavid du Colombier 				if (e != s->frst
124312a1df1SDavid du Colombier 				&&  e != s->last
125312a1df1SDavid du Colombier 				&&  e != s->extent)
1267dd7cddfSDavid du Colombier 				{	e->status |= DONE;	/* not unreachable */
1277dd7cddfSDavid du Colombier 					le->nxt = e->nxt;	/* remove it */
1287dd7cddfSDavid du Colombier 					e = le;
129312a1df1SDavid du Colombier 				}
1307dd7cddfSDavid du Colombier 			}
1317dd7cddfSDavid du Colombier 		} else
1327dd7cddfSDavid du Colombier 			cnt = 0;
1337dd7cddfSDavid du Colombier 	}
1347dd7cddfSDavid du Colombier }
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier void
prune_opts(Lextok * n)1377dd7cddfSDavid du Colombier prune_opts(Lextok *n)
1387dd7cddfSDavid du Colombier {	SeqList *l;
1397dd7cddfSDavid du Colombier 	extern Symbol *context;
1407dd7cddfSDavid du Colombier 	extern char *claimproc;
1417dd7cddfSDavid du Colombier 
1427dd7cddfSDavid du Colombier 	if (!n
1437dd7cddfSDavid du Colombier 	|| (context && claimproc && strcmp(context->name, claimproc) == 0))
1447dd7cddfSDavid du Colombier 		return;
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier 	for (l = n->sl; l; l = l->nxt)	/* find sequences of unlabeled skips */
1477dd7cddfSDavid du Colombier 		check_sequence(l->this);
1487dd7cddfSDavid du Colombier }
1497dd7cddfSDavid du Colombier 
150219b2ee8SDavid du Colombier Sequence *
close_seq(int nottop)151219b2ee8SDavid du Colombier close_seq(int nottop)
152219b2ee8SDavid du Colombier {	Sequence *s = cur_s->this;
153219b2ee8SDavid du Colombier 	Symbol *z;
154219b2ee8SDavid du Colombier 
155*00d97012SDavid du Colombier 	if (nottop == 0)	/* end of proctype body */
156*00d97012SDavid du Colombier 	{	initialization_ok = 1;
157*00d97012SDavid du Colombier 	}
158*00d97012SDavid du Colombier 
1597dd7cddfSDavid du Colombier 	if (nottop > 0 && (z = has_lab(s->frst, 0)))
160219b2ee8SDavid du Colombier 	{	printf("error: (%s:%d) label %s placed incorrectly\n",
161219b2ee8SDavid du Colombier 			(s->frst->n)?s->frst->n->fn->name:"-",
162219b2ee8SDavid du Colombier 			(s->frst->n)?s->frst->n->ln:0,
163219b2ee8SDavid du Colombier 			z->name);
164219b2ee8SDavid du Colombier 		switch (nottop) {
165219b2ee8SDavid du Colombier 		case 1:
166219b2ee8SDavid du Colombier 			printf("=====> stmnt unless Label: stmnt\n");
167219b2ee8SDavid du Colombier 			printf("sorry, cannot jump to the guard of an\n");
168219b2ee8SDavid du Colombier 			printf("escape (it is not a unique state)\n");
169219b2ee8SDavid du Colombier 			break;
170219b2ee8SDavid du Colombier 		case 2:
171219b2ee8SDavid du Colombier 			printf("=====> instead of  ");
172219b2ee8SDavid du Colombier 			printf("\"Label: stmnt unless stmnt\"\n");
173219b2ee8SDavid du Colombier 			printf("=====> always use  ");
174219b2ee8SDavid du Colombier 			printf("\"Label: { stmnt unless stmnt }\"\n");
175219b2ee8SDavid du Colombier 			break;
176219b2ee8SDavid du Colombier 		case 3:
177219b2ee8SDavid du Colombier 			printf("=====> instead of  ");
178219b2ee8SDavid du Colombier 			printf("\"atomic { Label: statement ... }\"\n");
179219b2ee8SDavid du Colombier 			printf("=====> always use  ");
180219b2ee8SDavid du Colombier 			printf("\"Label: atomic { statement ... }\"\n");
181219b2ee8SDavid du Colombier 			break;
182219b2ee8SDavid du Colombier 		case 4:
183219b2ee8SDavid du Colombier 			printf("=====> instead of  ");
184219b2ee8SDavid du Colombier 			printf("\"d_step { Label: statement ... }\"\n");
185219b2ee8SDavid du Colombier 			printf("=====> always use  ");
186219b2ee8SDavid du Colombier 			printf("\"Label: d_step { statement ... }\"\n");
187219b2ee8SDavid du Colombier 			break;
188219b2ee8SDavid du Colombier 		case 5:
189219b2ee8SDavid du Colombier 			printf("=====> instead of  ");
190219b2ee8SDavid du Colombier 			printf("\"{ Label: statement ... }\"\n");
191219b2ee8SDavid du Colombier 			printf("=====> always use  ");
192219b2ee8SDavid du Colombier 			printf("\"Label: { statement ... }\"\n");
193219b2ee8SDavid du Colombier 			break;
194219b2ee8SDavid du Colombier 		case 6:
195219b2ee8SDavid du Colombier 			printf("=====>instead of\n");
196219b2ee8SDavid du Colombier 			printf("	do (or if)\n");
197219b2ee8SDavid du Colombier 			printf("	:: ...\n");
198219b2ee8SDavid du Colombier 			printf("	:: Label: statement\n");
199219b2ee8SDavid du Colombier 			printf("	od (of fi)\n");
200219b2ee8SDavid du Colombier 			printf("=====>always use\n");
201219b2ee8SDavid du Colombier 			printf("Label:	do (or if)\n");
202219b2ee8SDavid du Colombier 			printf("	:: ...\n");
203219b2ee8SDavid du Colombier 			printf("	:: statement\n");
204219b2ee8SDavid du Colombier 			printf("	od (or fi)\n");
205219b2ee8SDavid du Colombier 			break;
206219b2ee8SDavid du Colombier 		case 7:
207219b2ee8SDavid du Colombier 			printf("cannot happen - labels\n");
208219b2ee8SDavid du Colombier 			break;
209219b2ee8SDavid du Colombier 		}
2107dd7cddfSDavid du Colombier 		alldone(1);
211219b2ee8SDavid du Colombier 	}
212219b2ee8SDavid du Colombier 
213219b2ee8SDavid du Colombier 	if (nottop == 4
214219b2ee8SDavid du Colombier 	&& !Rjumpslocal(s->frst, s->last))
215219b2ee8SDavid du Colombier 		fatal("non_local jump in d_step sequence", (char *) 0);
216219b2ee8SDavid du Colombier 
217219b2ee8SDavid du Colombier 	cur_s = cur_s->nxt;
218219b2ee8SDavid du Colombier 	s->maxel = Elcnt;
219219b2ee8SDavid du Colombier 	s->extent = s->last;
2207dd7cddfSDavid du Colombier 	if (!s->last)
2217dd7cddfSDavid du Colombier 		fatal("sequence must have at least one statement", (char *) 0);
222219b2ee8SDavid du Colombier 	return s;
223219b2ee8SDavid du Colombier }
224219b2ee8SDavid du Colombier 
225219b2ee8SDavid du Colombier Lextok *
do_unless(Lextok * No,Lextok * Es)226219b2ee8SDavid du Colombier do_unless(Lextok *No, Lextok *Es)
227219b2ee8SDavid du Colombier {	SeqList *Sl;
228219b2ee8SDavid du Colombier 	Lextok *Re = nn(ZN, UNLESS, ZN, ZN);
229219b2ee8SDavid du Colombier 	Re->ln = No->ln;
230219b2ee8SDavid du Colombier 	Re->fn = No->fn;
231219b2ee8SDavid du Colombier 
232219b2ee8SDavid du Colombier 	has_unless++;
233219b2ee8SDavid du Colombier 	if (Es->ntyp == NON_ATOMIC)
234219b2ee8SDavid du Colombier 		Sl = Es->sl;
235219b2ee8SDavid du Colombier 	else
236219b2ee8SDavid du Colombier 	{	open_seq(0); add_seq(Es);
237219b2ee8SDavid du Colombier 		Sl = seqlist(close_seq(1), 0);
238219b2ee8SDavid du Colombier 	}
239219b2ee8SDavid du Colombier 
240219b2ee8SDavid du Colombier 	if (No->ntyp == NON_ATOMIC)
241219b2ee8SDavid du Colombier 	{	No->sl->nxt = Sl;
242219b2ee8SDavid du Colombier 		Sl = No->sl;
243219b2ee8SDavid du Colombier 	} else	if (No->ntyp == ':'
244219b2ee8SDavid du Colombier 		&& (No->lft->ntyp == NON_ATOMIC
245219b2ee8SDavid du Colombier 		||  No->lft->ntyp == ATOMIC
246219b2ee8SDavid du Colombier 		||  No->lft->ntyp == D_STEP))
247219b2ee8SDavid du Colombier 	{
248219b2ee8SDavid du Colombier 		int tok = No->lft->ntyp;
249219b2ee8SDavid du Colombier 
250219b2ee8SDavid du Colombier 		No->lft->sl->nxt = Sl;
251219b2ee8SDavid du Colombier 		Re->sl = No->lft->sl;
252219b2ee8SDavid du Colombier 
253219b2ee8SDavid du Colombier 		open_seq(0); add_seq(Re);
254219b2ee8SDavid du Colombier 		Re = nn(ZN, tok, ZN, ZN);
255219b2ee8SDavid du Colombier 		Re->sl = seqlist(close_seq(7), 0);
256219b2ee8SDavid du Colombier 		Re->ln = No->ln;
257219b2ee8SDavid du Colombier 		Re->fn = No->fn;
258219b2ee8SDavid du Colombier 
259219b2ee8SDavid du Colombier 		Re = nn(No, ':', Re, ZN);	/* lift label */
260219b2ee8SDavid du Colombier 		Re->ln = No->ln;
261219b2ee8SDavid du Colombier 		Re->fn = No->fn;
262219b2ee8SDavid du Colombier 		return Re;
263219b2ee8SDavid du Colombier 	} else
264219b2ee8SDavid du Colombier 	{	open_seq(0); add_seq(No);
265219b2ee8SDavid du Colombier 		Sl = seqlist(close_seq(2), Sl);
266219b2ee8SDavid du Colombier 	}
267219b2ee8SDavid du Colombier 
268219b2ee8SDavid du Colombier 	Re->sl = Sl;
269219b2ee8SDavid du Colombier 	return Re;
270219b2ee8SDavid du Colombier }
271219b2ee8SDavid du Colombier 
272219b2ee8SDavid du Colombier SeqList *
seqlist(Sequence * s,SeqList * r)273219b2ee8SDavid du Colombier seqlist(Sequence *s, SeqList *r)
274219b2ee8SDavid du Colombier {	SeqList *t = (SeqList *) emalloc(sizeof(SeqList));
275219b2ee8SDavid du Colombier 
276219b2ee8SDavid du Colombier 	t->this = s;
277219b2ee8SDavid du Colombier 	t->nxt = r;
278219b2ee8SDavid du Colombier 	return t;
279219b2ee8SDavid du Colombier }
280219b2ee8SDavid du Colombier 
2817dd7cddfSDavid du Colombier static Element *
new_el(Lextok * n)282219b2ee8SDavid du Colombier new_el(Lextok *n)
283219b2ee8SDavid du Colombier {	Element *m;
284219b2ee8SDavid du Colombier 
285219b2ee8SDavid du Colombier 	if (n)
286219b2ee8SDavid du Colombier 	{	if (n->ntyp == IF || n->ntyp == DO)
287219b2ee8SDavid du Colombier 			return if_seq(n);
288219b2ee8SDavid du Colombier 		if (n->ntyp == UNLESS)
289219b2ee8SDavid du Colombier 			return unless_seq(n);
290219b2ee8SDavid du Colombier 	}
291219b2ee8SDavid du Colombier 	m = (Element *) emalloc(sizeof(Element));
292219b2ee8SDavid du Colombier 	m->n = n;
293219b2ee8SDavid du Colombier 	m->seqno = Elcnt++;
294219b2ee8SDavid du Colombier 	m->Seqno = Unique++;
295219b2ee8SDavid du Colombier 	m->Nxt = Al_El; Al_El = m;
296219b2ee8SDavid du Colombier 	return m;
297219b2ee8SDavid du Colombier }
298219b2ee8SDavid du Colombier 
2997dd7cddfSDavid du Colombier static int
has_chanref(Lextok * n)3007dd7cddfSDavid du Colombier has_chanref(Lextok *n)
3017dd7cddfSDavid du Colombier {
3027dd7cddfSDavid du Colombier 	if (!n) return 0;
3037dd7cddfSDavid du Colombier 
3047dd7cddfSDavid du Colombier 	switch (n->ntyp) {
3057dd7cddfSDavid du Colombier 	case 's':	case 'r':
3067dd7cddfSDavid du Colombier #if 0
3077dd7cddfSDavid du Colombier 	case 'R':	case LEN:
3087dd7cddfSDavid du Colombier #endif
3097dd7cddfSDavid du Colombier 	case FULL:	case NFULL:
3107dd7cddfSDavid du Colombier 	case EMPTY:	case NEMPTY:
3117dd7cddfSDavid du Colombier 		return 1;
3127dd7cddfSDavid du Colombier 	default:
3137dd7cddfSDavid du Colombier 		break;
3147dd7cddfSDavid du Colombier 	}
3157dd7cddfSDavid du Colombier 	if (has_chanref(n->lft))
3167dd7cddfSDavid du Colombier 		return 1;
3177dd7cddfSDavid du Colombier 
3187dd7cddfSDavid du Colombier 	return has_chanref(n->rgt);
3197dd7cddfSDavid du Colombier }
3207dd7cddfSDavid du Colombier 
321312a1df1SDavid du Colombier void
loose_ends(void)322312a1df1SDavid du Colombier loose_ends(void)	/* properly tie-up ends of sub-sequences */
323312a1df1SDavid du Colombier {	Element *e, *f;
324312a1df1SDavid du Colombier 
325312a1df1SDavid du Colombier 	for (e = Al_El; e; e = e->Nxt)
326312a1df1SDavid du Colombier 	{	if (!e->n
327312a1df1SDavid du Colombier 		||  !e->nxt)
328312a1df1SDavid du Colombier 			continue;
329312a1df1SDavid du Colombier 		switch (e->n->ntyp) {
330312a1df1SDavid du Colombier 		case ATOMIC:
331312a1df1SDavid du Colombier 		case NON_ATOMIC:
332312a1df1SDavid du Colombier 		case D_STEP:
333312a1df1SDavid du Colombier 			f = e->nxt;
334312a1df1SDavid du Colombier 			while (f && f->n->ntyp == '.')
335312a1df1SDavid du Colombier 				f = f->nxt;
336312a1df1SDavid du Colombier 			if (0) printf("link %d, {%d .. %d} -> %d (ntyp=%d) was %d\n",
337312a1df1SDavid du Colombier 				e->seqno,
338312a1df1SDavid du Colombier 				e->n->sl->this->frst->seqno,
339312a1df1SDavid du Colombier 				e->n->sl->this->last->seqno,
340312a1df1SDavid du Colombier 				f?f->seqno:-1, f?f->n->ntyp:-1,
341312a1df1SDavid du Colombier 				e->n->sl->this->last->nxt?e->n->sl->this->last->nxt->seqno:-1);
342312a1df1SDavid du Colombier 			if (!e->n->sl->this->last->nxt)
343312a1df1SDavid du Colombier 				e->n->sl->this->last->nxt = f;
344312a1df1SDavid du Colombier 			else
345312a1df1SDavid du Colombier 			{	if (e->n->sl->this->last->nxt->n->ntyp != GOTO)
346312a1df1SDavid du Colombier 				{	if (!f || e->n->sl->this->last->nxt->seqno != f->seqno)
347312a1df1SDavid du Colombier 					non_fatal("unexpected: loose ends", (char *)0);
348312a1df1SDavid du Colombier 				} else
349312a1df1SDavid du Colombier 					e->n->sl->this->last = e->n->sl->this->last->nxt;
350312a1df1SDavid du Colombier 				/*
351312a1df1SDavid du Colombier 				 * fix_dest can push a goto into the nxt position
352312a1df1SDavid du Colombier 				 * in that case the goto wins and f is not needed
353312a1df1SDavid du Colombier 				 * but the last fields needs adjusting
354312a1df1SDavid du Colombier 				 */
355312a1df1SDavid du Colombier 			}
356312a1df1SDavid du Colombier 			break;
357312a1df1SDavid du Colombier 	}	}
358312a1df1SDavid du Colombier }
359312a1df1SDavid du Colombier 
3607dd7cddfSDavid du Colombier static Element *
if_seq(Lextok * n)361219b2ee8SDavid du Colombier if_seq(Lextok *n)
362219b2ee8SDavid du Colombier {	int	tok = n->ntyp;
363219b2ee8SDavid du Colombier 	SeqList	*s  = n->sl;
364219b2ee8SDavid du Colombier 	Element	*e  = new_el(ZN);
365219b2ee8SDavid du Colombier 	Element	*t  = new_el(nn(ZN,'.',ZN,ZN)); /* target */
366219b2ee8SDavid du Colombier 	SeqList	*z, *prev_z = (SeqList *) 0;
367219b2ee8SDavid du Colombier 	SeqList *move_else  = (SeqList *) 0;	/* to end of optionlist */
3687dd7cddfSDavid du Colombier 	int	ref_chans = 0;
369219b2ee8SDavid du Colombier 
370219b2ee8SDavid du Colombier 	for (z = s; z; z = z->nxt)
3717dd7cddfSDavid du Colombier 	{	if (!z->this->frst)
3727dd7cddfSDavid du Colombier 			continue;
3737dd7cddfSDavid du Colombier 		if (z->this->frst->n->ntyp == ELSE)
374219b2ee8SDavid du Colombier 		{	if (move_else)
375219b2ee8SDavid du Colombier 				fatal("duplicate `else'", (char *) 0);
376219b2ee8SDavid du Colombier 			if (z->nxt)	/* is not already at the end */
377219b2ee8SDavid du Colombier 			{	move_else = z;
378219b2ee8SDavid du Colombier 				if (prev_z)
379219b2ee8SDavid du Colombier 					prev_z->nxt = z->nxt;
380219b2ee8SDavid du Colombier 				else
381219b2ee8SDavid du Colombier 					s = n->sl = z->nxt;
382219b2ee8SDavid du Colombier 				continue;
383219b2ee8SDavid du Colombier 			}
384219b2ee8SDavid du Colombier 		} else
3857dd7cddfSDavid du Colombier 			ref_chans |= has_chanref(z->this->frst->n);
386219b2ee8SDavid du Colombier 		prev_z = z;
387219b2ee8SDavid du Colombier 	}
388219b2ee8SDavid du Colombier 	if (move_else)
389219b2ee8SDavid du Colombier 	{	move_else->nxt = (SeqList *) 0;
390219b2ee8SDavid du Colombier 		/* if there is no prev, then else was at the end */
391219b2ee8SDavid du Colombier 		if (!prev_z) fatal("cannot happen - if_seq", (char *) 0);
392219b2ee8SDavid du Colombier 		prev_z->nxt = move_else;
393219b2ee8SDavid du Colombier 		prev_z = move_else;
394219b2ee8SDavid du Colombier 	}
395219b2ee8SDavid du Colombier 	if (prev_z
3967dd7cddfSDavid du Colombier 	&&  ref_chans
397219b2ee8SDavid du Colombier 	&&  prev_z->this->frst->n->ntyp == ELSE)
3987dd7cddfSDavid du Colombier 	{	prev_z->this->frst->n->val = 1;
3997dd7cddfSDavid du Colombier 		has_badelse++;
400*00d97012SDavid du Colombier 		if (has_xu)
401*00d97012SDavid du Colombier 		{	fatal("invalid use of 'else' combined with i/o and xr/xs assertions,",
4027dd7cddfSDavid du Colombier 				(char *)0);
403*00d97012SDavid du Colombier 		} else
404*00d97012SDavid du Colombier 		{	non_fatal("dubious use of 'else' combined with i/o,",
405*00d97012SDavid du Colombier 				(char *)0);
406*00d97012SDavid du Colombier 		}
4077dd7cddfSDavid du Colombier 		nr_errs--;
4087dd7cddfSDavid du Colombier 	}
409219b2ee8SDavid du Colombier 
410219b2ee8SDavid du Colombier 	e->n = nn(n, tok, ZN, ZN);
411219b2ee8SDavid du Colombier 	e->n->sl = s;			/* preserve as info only */
412219b2ee8SDavid du Colombier 	e->sub = s;
413219b2ee8SDavid du Colombier 	for (z = s; z; prev_z = z, z = z->nxt)
414219b2ee8SDavid du Colombier 		add_el(t, z->this);	/* append target */
415219b2ee8SDavid du Colombier 	if (tok == DO)
416219b2ee8SDavid du Colombier 	{	add_el(t, cur_s->this); /* target upfront */
417219b2ee8SDavid du Colombier 		t = new_el(nn(n, BREAK, ZN, ZN)); /* break target */
418219b2ee8SDavid du Colombier 		set_lab(break_dest(), t);	/* new exit  */
419219b2ee8SDavid du Colombier 		breakstack = breakstack->nxt;	/* pop stack */
420219b2ee8SDavid du Colombier 	}
421219b2ee8SDavid du Colombier 	add_el(e, cur_s->this);
422219b2ee8SDavid du Colombier 	add_el(t, cur_s->this);
423219b2ee8SDavid du Colombier 	return e;			/* destination node for label */
424219b2ee8SDavid du Colombier }
425219b2ee8SDavid du Colombier 
4267dd7cddfSDavid du Colombier static void
escape_el(Element * f,Sequence * e)4277dd7cddfSDavid du Colombier escape_el(Element *f, Sequence *e)
4287dd7cddfSDavid du Colombier {	SeqList *z;
429219b2ee8SDavid du Colombier 
4307dd7cddfSDavid du Colombier 	for (z = f->esc; z; z = z->nxt)
4317dd7cddfSDavid du Colombier 		if (z->this == e)
4327dd7cddfSDavid du Colombier 			return;	/* already there */
4337dd7cddfSDavid du Colombier 
4347dd7cddfSDavid du Colombier 	/* cover the lower-level escapes of this state */
4357dd7cddfSDavid du Colombier 	for (z = f->esc; z; z = z->nxt)
4367dd7cddfSDavid du Colombier 		attach_escape(z->this, e);
4377dd7cddfSDavid du Colombier 
4387dd7cddfSDavid du Colombier 	/* now attach escape to the state itself */
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier 	f->esc = seqlist(e, f->esc);	/* in lifo order... */
441219b2ee8SDavid du Colombier #ifdef DEBUG
442219b2ee8SDavid du Colombier 	printf("attach %d (", e->frst->Seqno);
443219b2ee8SDavid du Colombier 	comment(stdout, e->frst->n, 0);
444219b2ee8SDavid du Colombier 	printf(")	to %d (", f->Seqno);
445219b2ee8SDavid du Colombier 	comment(stdout, f->n, 0);
446219b2ee8SDavid du Colombier 	printf(")\n");
447219b2ee8SDavid du Colombier #endif
4487dd7cddfSDavid du Colombier 	switch (f->n->ntyp) {
4497dd7cddfSDavid du Colombier 	case UNLESS:
4507dd7cddfSDavid du Colombier 		attach_escape(f->sub->this, e);
4517dd7cddfSDavid du Colombier 		break;
4527dd7cddfSDavid du Colombier 	case IF:
4537dd7cddfSDavid du Colombier 	case DO:
4547dd7cddfSDavid du Colombier 		for (z = f->sub; z; z = z->nxt)
455219b2ee8SDavid du Colombier 			attach_escape(z->this, e);
4567dd7cddfSDavid du Colombier 		break;
4577dd7cddfSDavid du Colombier 	case D_STEP:
4587dd7cddfSDavid du Colombier 		/* attach only to the guard stmnt */
4597dd7cddfSDavid du Colombier 		escape_el(f->n->sl->this->frst, e);
4607dd7cddfSDavid du Colombier 		break;
4617dd7cddfSDavid du Colombier 	case ATOMIC:
4627dd7cddfSDavid du Colombier 	case NON_ATOMIC:
4637dd7cddfSDavid du Colombier 		/* attach to all stmnts */
4647dd7cddfSDavid du Colombier 		attach_escape(f->n->sl->this, e);
4657dd7cddfSDavid du Colombier 		break;
466219b2ee8SDavid du Colombier 	}
467219b2ee8SDavid du Colombier }
468219b2ee8SDavid du Colombier 
4697dd7cddfSDavid du Colombier static void
attach_escape(Sequence * n,Sequence * e)4707dd7cddfSDavid du Colombier attach_escape(Sequence *n, Sequence *e)
4717dd7cddfSDavid du Colombier {	Element *f;
4727dd7cddfSDavid du Colombier 
4737dd7cddfSDavid du Colombier 	for (f = n->frst; f; f = f->nxt)
4747dd7cddfSDavid du Colombier 	{	escape_el(f, e);
4757dd7cddfSDavid du Colombier 		if (f == n->extent)
4767dd7cddfSDavid du Colombier 			break;
4777dd7cddfSDavid du Colombier 	}
4787dd7cddfSDavid du Colombier }
4797dd7cddfSDavid du Colombier 
4807dd7cddfSDavid du Colombier static Element *
unless_seq(Lextok * n)481219b2ee8SDavid du Colombier unless_seq(Lextok *n)
482219b2ee8SDavid du Colombier {	SeqList	*s  = n->sl;
483219b2ee8SDavid du Colombier 	Element	*e  = new_el(ZN);
484219b2ee8SDavid du Colombier 	Element	*t  = new_el(nn(ZN,'.',ZN,ZN)); /* target */
485219b2ee8SDavid du Colombier 	SeqList	*z;
486219b2ee8SDavid du Colombier 
487219b2ee8SDavid du Colombier 	e->n = nn(n, UNLESS, ZN, ZN);
488219b2ee8SDavid du Colombier 	e->n->sl = s;			/* info only */
489219b2ee8SDavid du Colombier 	e->sub = s;
490219b2ee8SDavid du Colombier 
4917dd7cddfSDavid du Colombier 	/* need 2 sequences: normal execution and escape */
492219b2ee8SDavid du Colombier 	if (!s || !s->nxt || s->nxt->nxt)
493219b2ee8SDavid du Colombier 		fatal("unexpected unless structure", (char *)0);
4947dd7cddfSDavid du Colombier 
4957dd7cddfSDavid du Colombier 	/* append the target state to both */
496219b2ee8SDavid du Colombier 	for (z = s; z; z = z->nxt)
497219b2ee8SDavid du Colombier 		add_el(t, z->this);
4987dd7cddfSDavid du Colombier 
4997dd7cddfSDavid du Colombier 	/* attach escapes to all states in normal sequence */
500219b2ee8SDavid du Colombier 	attach_escape(s->this, s->nxt->this);
501219b2ee8SDavid du Colombier 
502219b2ee8SDavid du Colombier 	add_el(e, cur_s->this);
503219b2ee8SDavid du Colombier 	add_el(t, cur_s->this);
504219b2ee8SDavid du Colombier #ifdef DEBUG
505219b2ee8SDavid du Colombier 	printf("unless element (%d,%d):\n", e->Seqno, t->Seqno);
506219b2ee8SDavid du Colombier 	for (z = s; z; z = z->nxt)
507219b2ee8SDavid du Colombier 	{	Element *x; printf("\t%d,%d,%d :: ",
508219b2ee8SDavid du Colombier 		z->this->frst->Seqno,
509219b2ee8SDavid du Colombier 		z->this->extent->Seqno,
510219b2ee8SDavid du Colombier 		z->this->last->Seqno);
511219b2ee8SDavid du Colombier 		for (x = z->this->frst; x; x = x->nxt)
512219b2ee8SDavid du Colombier 			printf("(%d)", x->Seqno);
513219b2ee8SDavid du Colombier 		printf("\n");
514219b2ee8SDavid du Colombier 	}
515219b2ee8SDavid du Colombier #endif
516219b2ee8SDavid du Colombier 	return e;
517219b2ee8SDavid du Colombier }
518219b2ee8SDavid du Colombier 
519219b2ee8SDavid du Colombier Element *
mk_skip(void)520219b2ee8SDavid du Colombier mk_skip(void)
521219b2ee8SDavid du Colombier {	Lextok  *t = nn(ZN, CONST, ZN, ZN);
522219b2ee8SDavid du Colombier 	t->val = 1;
523219b2ee8SDavid du Colombier 	return new_el(nn(ZN, 'c', t, ZN));
524219b2ee8SDavid du Colombier }
525219b2ee8SDavid du Colombier 
5267dd7cddfSDavid du Colombier static void
add_el(Element * e,Sequence * s)527219b2ee8SDavid du Colombier add_el(Element *e, Sequence *s)
528219b2ee8SDavid du Colombier {
529219b2ee8SDavid du Colombier 	if (e->n->ntyp == GOTO)
5307dd7cddfSDavid du Colombier 	{	Symbol *z = has_lab(e, (1|2|4));
5317dd7cddfSDavid du Colombier 		if (z)
532219b2ee8SDavid du Colombier 		{	Element *y; /* insert a skip */
533219b2ee8SDavid du Colombier 			y = mk_skip();
534219b2ee8SDavid du Colombier 			mov_lab(z, e, y); /* inherit label */
535219b2ee8SDavid du Colombier 			add_el(y, s);
536219b2ee8SDavid du Colombier 	}	}
537219b2ee8SDavid du Colombier #ifdef DEBUG
538219b2ee8SDavid du Colombier 	printf("add_el %d after %d -- ",
539219b2ee8SDavid du Colombier 	e->Seqno, (s->last)?s->last->Seqno:-1);
540219b2ee8SDavid du Colombier 	comment(stdout, e->n, 0);
541219b2ee8SDavid du Colombier 	printf("\n");
542219b2ee8SDavid du Colombier #endif
543219b2ee8SDavid du Colombier 	if (!s->frst)
544219b2ee8SDavid du Colombier 		s->frst = e;
545219b2ee8SDavid du Colombier 	else
546219b2ee8SDavid du Colombier 		s->last->nxt = e;
547219b2ee8SDavid du Colombier 	s->last = e;
548219b2ee8SDavid du Colombier }
549219b2ee8SDavid du Colombier 
5507dd7cddfSDavid du Colombier static Element *
colons(Lextok * n)551219b2ee8SDavid du Colombier colons(Lextok *n)
552219b2ee8SDavid du Colombier {
553219b2ee8SDavid du Colombier 	if (!n)
554219b2ee8SDavid du Colombier 		return ZE;
555219b2ee8SDavid du Colombier 	if (n->ntyp == ':')
556219b2ee8SDavid du Colombier 	{	Element *e = colons(n->lft);
557219b2ee8SDavid du Colombier 		set_lab(n->sym, e);
558219b2ee8SDavid du Colombier 		return e;
559219b2ee8SDavid du Colombier 	}
560219b2ee8SDavid du Colombier 	innermost = n;
561219b2ee8SDavid du Colombier 	return new_el(n);
562219b2ee8SDavid du Colombier }
563219b2ee8SDavid du Colombier 
564219b2ee8SDavid du Colombier void
add_seq(Lextok * n)565219b2ee8SDavid du Colombier add_seq(Lextok *n)
566219b2ee8SDavid du Colombier {	Element *e;
567219b2ee8SDavid du Colombier 
568219b2ee8SDavid du Colombier 	if (!n) return;
569219b2ee8SDavid du Colombier 	innermost = n;
570219b2ee8SDavid du Colombier 	e = colons(n);
571219b2ee8SDavid du Colombier 	if (innermost->ntyp != IF
572219b2ee8SDavid du Colombier 	&&  innermost->ntyp != DO
573219b2ee8SDavid du Colombier 	&&  innermost->ntyp != UNLESS)
574219b2ee8SDavid du Colombier 		add_el(e, cur_s->this);
575219b2ee8SDavid du Colombier }
576219b2ee8SDavid du Colombier 
577219b2ee8SDavid du Colombier void
show_lab(void)578*00d97012SDavid du Colombier show_lab(void)
579*00d97012SDavid du Colombier {	Label *l;
580*00d97012SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
581*00d97012SDavid du Colombier 		printf("label %s\n", l->s->name);
582*00d97012SDavid du Colombier }
583*00d97012SDavid du Colombier 
584*00d97012SDavid du Colombier void
set_lab(Symbol * s,Element * e)585219b2ee8SDavid du Colombier set_lab(Symbol *s, Element *e)
586219b2ee8SDavid du Colombier {	Label *l; extern Symbol *context;
587*00d97012SDavid du Colombier 	int cur_uiid = is_inline();
588219b2ee8SDavid du Colombier 
589219b2ee8SDavid du Colombier 	if (!s) return;
590*00d97012SDavid du Colombier 
5917dd7cddfSDavid du Colombier 	for (l = labtab; l; l = l->nxt)
592*00d97012SDavid du Colombier 	{	if (strcmp(l->s->name, s->name) == 0
593*00d97012SDavid du Colombier 		&&  l->c == context
594*00d97012SDavid du Colombier 		&&  l->uiid == cur_uiid)
5957dd7cddfSDavid du Colombier 		{	non_fatal("label %s redeclared", s->name);
5967dd7cddfSDavid du Colombier 			break;
597*00d97012SDavid du Colombier 	}	}
598*00d97012SDavid du Colombier 
599219b2ee8SDavid du Colombier 	l = (Label *) emalloc(sizeof(Label));
600219b2ee8SDavid du Colombier 	l->s = s;
601219b2ee8SDavid du Colombier 	l->c = context;
602219b2ee8SDavid du Colombier 	l->e = e;
603*00d97012SDavid du Colombier 	l->uiid = cur_uiid;
604219b2ee8SDavid du Colombier 	l->nxt = labtab;
605219b2ee8SDavid du Colombier 	labtab = l;
606219b2ee8SDavid du Colombier }
607219b2ee8SDavid du Colombier 
608*00d97012SDavid du Colombier static Label *
get_labspec(Lextok * n)609*00d97012SDavid du Colombier get_labspec(Lextok *n)
610*00d97012SDavid du Colombier {	Symbol *s = n->sym;
611*00d97012SDavid du Colombier 	Label *l, *anymatch = (Label *) 0;
612*00d97012SDavid du Colombier 	int cur_uiid = n->uiid;
613*00d97012SDavid du Colombier 	/*
614*00d97012SDavid du Colombier 	 * try to find a label with the same uiid
615*00d97012SDavid du Colombier 	 * but if it doesn't exist, return any other
616*00d97012SDavid du Colombier 	 * that is defined within the same scope
617*00d97012SDavid du Colombier 	 */
618*00d97012SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
619*00d97012SDavid du Colombier 	{	if (strcmp(s->name, l->s->name) == 0
620*00d97012SDavid du Colombier 		&&  s->context == l->s->context)
621*00d97012SDavid du Colombier 		{	anymatch = l;
622*00d97012SDavid du Colombier 			if (cur_uiid == l->uiid) /* best match */
623*00d97012SDavid du Colombier 			{	return l;
624*00d97012SDavid du Colombier 	}	}	}
625*00d97012SDavid du Colombier 
626*00d97012SDavid du Colombier 	return anymatch; /* likely to be 0 */
627*00d97012SDavid du Colombier }
628*00d97012SDavid du Colombier 
629219b2ee8SDavid du Colombier Element *
get_lab(Lextok * n,int md)630219b2ee8SDavid du Colombier get_lab(Lextok *n, int md)
631*00d97012SDavid du Colombier {	Label *l = get_labspec(n);
632219b2ee8SDavid du Colombier 
633*00d97012SDavid du Colombier 	if (l != (Label *) 0)
634*00d97012SDavid du Colombier 	{	return (l->e);
635*00d97012SDavid du Colombier 	}
636312a1df1SDavid du Colombier 
637*00d97012SDavid du Colombier 	if (md)
638*00d97012SDavid du Colombier 	{	lineno = n->ln;
639219b2ee8SDavid du Colombier 		Fname  = n->fn;
640*00d97012SDavid du Colombier 		fatal("undefined label %s", n->sym->name);
641*00d97012SDavid du Colombier 	}
642*00d97012SDavid du Colombier 
643219b2ee8SDavid du Colombier 	return ZE;
644219b2ee8SDavid du Colombier }
645219b2ee8SDavid du Colombier 
646219b2ee8SDavid du Colombier Symbol *
has_lab(Element * e,int special)6477dd7cddfSDavid du Colombier has_lab(Element *e, int special)
648219b2ee8SDavid du Colombier {	Label *l;
649219b2ee8SDavid du Colombier 
650219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
6517dd7cddfSDavid du Colombier 	{	if (e != l->e)
6527dd7cddfSDavid du Colombier 			continue;
6537dd7cddfSDavid du Colombier 		if (special == 0
6547dd7cddfSDavid du Colombier 		||  ((special&1) && !strncmp(l->s->name, "accept", 6))
6557dd7cddfSDavid du Colombier 		||  ((special&2) && !strncmp(l->s->name, "end", 3))
6567dd7cddfSDavid du Colombier 		||  ((special&4) && !strncmp(l->s->name, "progress", 8)))
657219b2ee8SDavid du Colombier 			return (l->s);
6587dd7cddfSDavid du Colombier 	}
659219b2ee8SDavid du Colombier 	return ZS;
660219b2ee8SDavid du Colombier }
661219b2ee8SDavid du Colombier 
6627dd7cddfSDavid du Colombier static void
mov_lab(Symbol * z,Element * e,Element * y)663219b2ee8SDavid du Colombier mov_lab(Symbol *z, Element *e, Element *y)
664219b2ee8SDavid du Colombier {	Label *l;
665219b2ee8SDavid du Colombier 
666219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
667219b2ee8SDavid du Colombier 		if (e == l->e)
668219b2ee8SDavid du Colombier 		{	l->e = y;
669219b2ee8SDavid du Colombier 			return;
670219b2ee8SDavid du Colombier 		}
671219b2ee8SDavid du Colombier 	if (e->n)
672219b2ee8SDavid du Colombier 	{	lineno = e->n->ln;
673219b2ee8SDavid du Colombier 		Fname  = e->n->fn;
674219b2ee8SDavid du Colombier 	}
675219b2ee8SDavid du Colombier 	fatal("cannot happen - mov_lab %s", z->name);
676219b2ee8SDavid du Colombier }
677219b2ee8SDavid du Colombier 
678219b2ee8SDavid du Colombier void
fix_dest(Symbol * c,Symbol * a)679312a1df1SDavid du Colombier fix_dest(Symbol *c, Symbol *a)		/* c:label name, a:proctype name */
6807dd7cddfSDavid du Colombier {	Label *l; extern Symbol *context;
681219b2ee8SDavid du Colombier 
682312a1df1SDavid du Colombier #if 0
683312a1df1SDavid du Colombier 	printf("ref to label '%s' in proctype '%s', search:\n",
684312a1df1SDavid du Colombier 		c->name, a->name);
685312a1df1SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
686312a1df1SDavid du Colombier 		printf("	%s in	%s\n", l->s->name, l->c->name);
687312a1df1SDavid du Colombier #endif
688312a1df1SDavid du Colombier 
689219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
690219b2ee8SDavid du Colombier 	{	if (strcmp(c->name, l->s->name) == 0
691312a1df1SDavid du Colombier 		&&  strcmp(a->name, l->c->name) == 0)	/* ? */
692219b2ee8SDavid du Colombier 			break;
693219b2ee8SDavid du Colombier 	}
694219b2ee8SDavid du Colombier 	if (!l)
6957dd7cddfSDavid du Colombier 	{	printf("spin: label '%s' (proctype %s)\n", c->name, a->name);
6967dd7cddfSDavid du Colombier 		non_fatal("unknown label '%s'", c->name);
6977dd7cddfSDavid du Colombier 		if (context == a)
6987dd7cddfSDavid du Colombier 		printf("spin: cannot remote ref a label inside the same proctype\n");
699219b2ee8SDavid du Colombier 		return;
700219b2ee8SDavid du Colombier 	}
701219b2ee8SDavid du Colombier 	if (!l->e || !l->e->n)
702219b2ee8SDavid du Colombier 		fatal("fix_dest error (%s)", c->name);
703219b2ee8SDavid du Colombier 	if (l->e->n->ntyp == GOTO)
704219b2ee8SDavid du Colombier 	{	Element	*y = (Element *) emalloc(sizeof(Element));
705219b2ee8SDavid du Colombier 		int	keep_ln = l->e->n->ln;
706219b2ee8SDavid du Colombier 		Symbol	*keep_fn = l->e->n->fn;
707219b2ee8SDavid du Colombier 
708219b2ee8SDavid du Colombier 		/* insert skip - or target is optimized away */
709219b2ee8SDavid du Colombier 		y->n = l->e->n;		  /* copy of the goto   */
710219b2ee8SDavid du Colombier 		y->seqno = find_maxel(a); /* unique seqno within proc */
711219b2ee8SDavid du Colombier 		y->nxt = l->e->nxt;
712219b2ee8SDavid du Colombier 		y->Seqno = Unique++; y->Nxt = Al_El; Al_El = y;
713219b2ee8SDavid du Colombier 
714219b2ee8SDavid du Colombier 		/* turn the original element+seqno into a skip */
715219b2ee8SDavid du Colombier 		l->e->n = nn(ZN, 'c', nn(ZN, CONST, ZN, ZN), ZN);
716219b2ee8SDavid du Colombier 		l->e->n->ln = l->e->n->lft->ln = keep_ln;
717219b2ee8SDavid du Colombier 		l->e->n->fn = l->e->n->lft->fn = keep_fn;
718219b2ee8SDavid du Colombier 		l->e->n->lft->val = 1;
719219b2ee8SDavid du Colombier 		l->e->nxt = y;		/* append the goto  */
720219b2ee8SDavid du Colombier 	}
7217dd7cddfSDavid du Colombier 	l->e->status |= CHECK2;	/* treat as if global */
722312a1df1SDavid du Colombier 	if (l->e->status & (ATOM | L_ATOM | D_ATOM))
723312a1df1SDavid du Colombier 	{	non_fatal("cannot reference label inside atomic or d_step (%s)",
724312a1df1SDavid du Colombier 			c->name);
725312a1df1SDavid du Colombier 	}
726219b2ee8SDavid du Colombier }
727219b2ee8SDavid du Colombier 
728219b2ee8SDavid du Colombier int
find_lab(Symbol * s,Symbol * c,int markit)7297dd7cddfSDavid du Colombier find_lab(Symbol *s, Symbol *c, int markit)
730219b2ee8SDavid du Colombier {	Label *l;
731219b2ee8SDavid du Colombier 
732219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
733219b2ee8SDavid du Colombier 	{	if (strcmp(s->name, l->s->name) == 0
734219b2ee8SDavid du Colombier 		&&  strcmp(c->name, l->c->name) == 0)
7357dd7cddfSDavid du Colombier 		{	l->visible |= markit;
736219b2ee8SDavid du Colombier 			return (l->e->seqno);
7377dd7cddfSDavid du Colombier 	}	}
738219b2ee8SDavid du Colombier 	return 0;
739219b2ee8SDavid du Colombier }
740219b2ee8SDavid du Colombier 
741219b2ee8SDavid du Colombier void
pushbreak(void)742219b2ee8SDavid du Colombier pushbreak(void)
743219b2ee8SDavid du Colombier {	Lbreak *r = (Lbreak *) emalloc(sizeof(Lbreak));
744219b2ee8SDavid du Colombier 	Symbol *l;
7457dd7cddfSDavid du Colombier 	char buf[64];
746219b2ee8SDavid du Colombier 
747219b2ee8SDavid du Colombier 	sprintf(buf, ":b%d", break_id++);
748219b2ee8SDavid du Colombier 	l = lookup(buf);
749219b2ee8SDavid du Colombier 	r->l = l;
750219b2ee8SDavid du Colombier 	r->nxt = breakstack;
751219b2ee8SDavid du Colombier 	breakstack = r;
752219b2ee8SDavid du Colombier }
753219b2ee8SDavid du Colombier 
754219b2ee8SDavid du Colombier Symbol *
break_dest(void)755219b2ee8SDavid du Colombier break_dest(void)
756219b2ee8SDavid du Colombier {
757219b2ee8SDavid du Colombier 	if (!breakstack)
758219b2ee8SDavid du Colombier 		fatal("misplaced break statement", (char *)0);
759219b2ee8SDavid du Colombier 	return breakstack->l;
760219b2ee8SDavid du Colombier }
761219b2ee8SDavid du Colombier 
762219b2ee8SDavid du Colombier void
make_atomic(Sequence * s,int added)763219b2ee8SDavid du Colombier make_atomic(Sequence *s, int added)
764312a1df1SDavid du Colombier {	Element *f;
765312a1df1SDavid du Colombier 
766219b2ee8SDavid du Colombier 	walk_atomic(s->frst, s->last, added);
767312a1df1SDavid du Colombier 
768312a1df1SDavid du Colombier 	f = s->last;
769312a1df1SDavid du Colombier 	switch (f->n->ntyp) {	/* is last step basic stmnt or sequence ? */
770312a1df1SDavid du Colombier 	case NON_ATOMIC:
771312a1df1SDavid du Colombier 	case ATOMIC:
772312a1df1SDavid du Colombier 		/* redo and search for the last step of that sequence */
773312a1df1SDavid du Colombier 		make_atomic(f->n->sl->this, added);
774312a1df1SDavid du Colombier 		break;
775312a1df1SDavid du Colombier 
776312a1df1SDavid du Colombier 	case UNLESS:
777312a1df1SDavid du Colombier 		/* escapes are folded into main sequence */
778312a1df1SDavid du Colombier 		make_atomic(f->sub->this, added);
779312a1df1SDavid du Colombier 		break;
780312a1df1SDavid du Colombier 
781312a1df1SDavid du Colombier 	default:
782312a1df1SDavid du Colombier 		f->status &= ~ATOM;
783312a1df1SDavid du Colombier 		f->status |= L_ATOM;
784312a1df1SDavid du Colombier 		break;
785312a1df1SDavid du Colombier 	}
786219b2ee8SDavid du Colombier }
787219b2ee8SDavid du Colombier 
788*00d97012SDavid du Colombier #if 0
789*00d97012SDavid du Colombier static int depth = 0;
790*00d97012SDavid du Colombier void dump_sym(Symbol *, char *);
791*00d97012SDavid du Colombier 
792*00d97012SDavid du Colombier void
793*00d97012SDavid du Colombier dump_lex(Lextok *t, char *s)
794*00d97012SDavid du Colombier {	int i;
795*00d97012SDavid du Colombier 
796*00d97012SDavid du Colombier 	depth++;
797*00d97012SDavid du Colombier 	printf(s);
798*00d97012SDavid du Colombier 	for (i = 0; i < depth; i++)
799*00d97012SDavid du Colombier 		printf("\t");
800*00d97012SDavid du Colombier 	explain(t->ntyp);
801*00d97012SDavid du Colombier 	if (t->ntyp == NAME) printf(" %s ", t->sym->name);
802*00d97012SDavid du Colombier 	if (t->ntyp == CONST) printf(" %d ", t->val);
803*00d97012SDavid du Colombier 	if (t->ntyp == STRUCT)
804*00d97012SDavid du Colombier 	{	dump_sym(t->sym, "\n:Z:");
805*00d97012SDavid du Colombier 	}
806*00d97012SDavid du Colombier 	if (t->lft)
807*00d97012SDavid du Colombier 	{	dump_lex(t->lft, "\nL");
808*00d97012SDavid du Colombier 	}
809*00d97012SDavid du Colombier 	if (t->rgt)
810*00d97012SDavid du Colombier 	{	dump_lex(t->rgt, "\nR");
811*00d97012SDavid du Colombier 	}
812*00d97012SDavid du Colombier 	depth--;
813*00d97012SDavid du Colombier }
814*00d97012SDavid du Colombier void
815*00d97012SDavid du Colombier dump_sym(Symbol *z, char *s)
816*00d97012SDavid du Colombier {	int i;
817*00d97012SDavid du Colombier 	char txt[64];
818*00d97012SDavid du Colombier 	depth++;
819*00d97012SDavid du Colombier 	printf(s);
820*00d97012SDavid du Colombier 	for (i = 0; i < depth; i++)
821*00d97012SDavid du Colombier 		printf("\t");
822*00d97012SDavid du Colombier 
823*00d97012SDavid du Colombier 	if (z->type == CHAN)
824*00d97012SDavid du Colombier 	{	if (z->ini && z->ini->rgt && z->ini->rgt->sym)
825*00d97012SDavid du Colombier 		{	// dump_sym(z->ini->rgt->sym, "\n:I:"); /* could also be longer list */
826*00d97012SDavid du Colombier 			if (z->ini->rgt->rgt
827*00d97012SDavid du Colombier 			|| !z->ini->rgt->sym)
828*00d97012SDavid du Colombier 			fatal("chan %s in for should have only one field (a typedef)", z->name);
829*00d97012SDavid du Colombier 			printf(" -- %s %p -- ", z->ini->rgt->sym->name, z->ini->rgt->sym);
830*00d97012SDavid du Colombier 		}
831*00d97012SDavid du Colombier 	} else if (z->type == STRUCT)
832*00d97012SDavid du Colombier 	{	if (z->Snm)
833*00d97012SDavid du Colombier 			printf(" == %s %p == ", z->Snm->name, z->Snm);
834*00d97012SDavid du Colombier 		else
835*00d97012SDavid du Colombier 		{	if (z->Slst)
836*00d97012SDavid du Colombier 				dump_lex(z->Slst, "\n:X:");
837*00d97012SDavid du Colombier 			if (z->ini)
838*00d97012SDavid du Colombier 				dump_lex(z->ini, "\n:I:");
839*00d97012SDavid du Colombier 		}
840*00d97012SDavid du Colombier 	}
841*00d97012SDavid du Colombier 	depth--;
842*00d97012SDavid du Colombier 
843*00d97012SDavid du Colombier }
844*00d97012SDavid du Colombier #endif
845*00d97012SDavid du Colombier 
846*00d97012SDavid du Colombier int
match_struct(Symbol * s,Symbol * t)847*00d97012SDavid du Colombier match_struct(Symbol *s, Symbol *t)
848*00d97012SDavid du Colombier {
849*00d97012SDavid du Colombier 	if (!t
850*00d97012SDavid du Colombier 	||  !t->ini
851*00d97012SDavid du Colombier 	||  !t->ini->rgt
852*00d97012SDavid du Colombier 	||  !t->ini->rgt->sym
853*00d97012SDavid du Colombier 	||   t->ini->rgt->rgt)
854*00d97012SDavid du Colombier 	{	fatal("chan %s in for should have only one field (a typedef)", t->name);
855*00d97012SDavid du Colombier 	}
856*00d97012SDavid du Colombier 	/* we already know that s is a STRUCT */
857*00d97012SDavid du Colombier 	if (0)
858*00d97012SDavid du Colombier 	{	printf("index type %s %p ==\n", s->Snm->name, s->Snm);
859*00d97012SDavid du Colombier 		printf("chan type  %s %p --\n\n", t->ini->rgt->sym->name, t->ini->rgt->sym);
860*00d97012SDavid du Colombier 	}
861*00d97012SDavid du Colombier 
862*00d97012SDavid du Colombier 	return (s->Snm == t->ini->rgt->sym);
863*00d97012SDavid du Colombier }
864*00d97012SDavid du Colombier 
865*00d97012SDavid du Colombier void
valid_name(Lextok * a3,Lextok * a5,Lextok * a8,char * tp)866*00d97012SDavid du Colombier valid_name(Lextok *a3, Lextok *a5, Lextok *a8, char *tp)
867*00d97012SDavid du Colombier {
868*00d97012SDavid du Colombier 	if (a3->ntyp != NAME)
869*00d97012SDavid du Colombier 	{	fatal("%s ( .name : from .. to ) { ... }", tp);
870*00d97012SDavid du Colombier 	}
871*00d97012SDavid du Colombier 	if (a3->sym->type == CHAN
872*00d97012SDavid du Colombier 	||  a3->sym->type == STRUCT
873*00d97012SDavid du Colombier 	||  a3->sym->isarray != 0)
874*00d97012SDavid du Colombier 	{	fatal("bad index in for-construct %s", a3->sym->name);
875*00d97012SDavid du Colombier 	}
876*00d97012SDavid du Colombier 	if (a5->ntyp == CONST && a8->ntyp == CONST && a5->val > a8->val)
877*00d97012SDavid du Colombier 	{	non_fatal("start value for %s exceeds end-value", a3->sym->name);
878*00d97012SDavid du Colombier 	}
879*00d97012SDavid du Colombier }
880*00d97012SDavid du Colombier 
881*00d97012SDavid du Colombier void
for_setup(Lextok * a3,Lextok * a5,Lextok * a8)882*00d97012SDavid du Colombier for_setup(Lextok *a3, Lextok *a5, Lextok *a8)
883*00d97012SDavid du Colombier {	/* for ( a3 : a5 .. a8 ) */
884*00d97012SDavid du Colombier 
885*00d97012SDavid du Colombier 	valid_name(a3, a5, a8, "for");
886*00d97012SDavid du Colombier 	/* a5->ntyp = a8->ntyp = CONST; */
887*00d97012SDavid du Colombier 	add_seq(nn(a3, ASGN, a3, a5));	/* start value */
888*00d97012SDavid du Colombier 	open_seq(0);
889*00d97012SDavid du Colombier 	add_seq(nn(ZN, 'c', nn(a3, LE, a3, a8), ZN));	/* condition */
890*00d97012SDavid du Colombier }
891*00d97012SDavid du Colombier 
892*00d97012SDavid du Colombier Lextok *
for_index(Lextok * a3,Lextok * a5)893*00d97012SDavid du Colombier for_index(Lextok *a3, Lextok *a5)
894*00d97012SDavid du Colombier {	Lextok *z0, *z1, *z2, *z3;
895*00d97012SDavid du Colombier 	Symbol *tmp_cnt;
896*00d97012SDavid du Colombier 	char tmp_nm[MAXSCOPESZ];
897*00d97012SDavid du Colombier 	/* for ( a3 in a5 ) { ... } */
898*00d97012SDavid du Colombier 
899*00d97012SDavid du Colombier 	if (a3->ntyp != NAME)
900*00d97012SDavid du Colombier 	{	fatal("for ( .name in name ) { ... }", (char *) 0);
901*00d97012SDavid du Colombier 	}
902*00d97012SDavid du Colombier 
903*00d97012SDavid du Colombier 	if (a5->ntyp != NAME)
904*00d97012SDavid du Colombier 	{	fatal("for ( %s in .name ) { ... }", a3->sym->name);
905*00d97012SDavid du Colombier 	}
906*00d97012SDavid du Colombier 
907*00d97012SDavid du Colombier 	if (a3->sym->type == STRUCT)
908*00d97012SDavid du Colombier 	{	if (a5->sym->type != CHAN)
909*00d97012SDavid du Colombier 		{	fatal("for ( %s in .channel_name ) { ... }",
910*00d97012SDavid du Colombier 				a3->sym->name);
911*00d97012SDavid du Colombier 		}
912*00d97012SDavid du Colombier 		z0 = a5->sym->ini;
913*00d97012SDavid du Colombier 		if (!z0
914*00d97012SDavid du Colombier 		|| z0->val <= 0
915*00d97012SDavid du Colombier 		|| z0->rgt->ntyp != STRUCT
916*00d97012SDavid du Colombier 		|| z0->rgt->rgt != NULL)
917*00d97012SDavid du Colombier 		{	fatal("bad channel type %s in for", a5->sym->name);
918*00d97012SDavid du Colombier 		}
919*00d97012SDavid du Colombier 
920*00d97012SDavid du Colombier 		if (!match_struct(a3->sym, a5->sym))
921*00d97012SDavid du Colombier 		{	fatal("type of %s does not match chan", a3->sym->name);
922*00d97012SDavid du Colombier 		}
923*00d97012SDavid du Colombier 
924*00d97012SDavid du Colombier 		z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0;
925*00d97012SDavid du Colombier 		z2 = nn(a5, LEN, a5, ZN);
926*00d97012SDavid du Colombier 
927*00d97012SDavid du Colombier 		sprintf(tmp_nm, "_f0r_t3mp%s", CurScope); /* make sure it's unique */
928*00d97012SDavid du Colombier 		tmp_cnt = lookup(tmp_nm);
929*00d97012SDavid du Colombier 		if (z0->val > 255)			/* check nr of slots, i.e. max length */
930*00d97012SDavid du Colombier 		{	tmp_cnt->type = SHORT;	/* should be rare */
931*00d97012SDavid du Colombier 		} else
932*00d97012SDavid du Colombier 		{	tmp_cnt->type = BYTE;
933*00d97012SDavid du Colombier 		}
934*00d97012SDavid du Colombier 		z3 = nn(ZN, NAME, ZN, ZN);
935*00d97012SDavid du Colombier 		z3->sym = tmp_cnt;
936*00d97012SDavid du Colombier 
937*00d97012SDavid du Colombier 		add_seq(nn(z3, ASGN, z3, z1));	/* start value 0 */
938*00d97012SDavid du Colombier 
939*00d97012SDavid du Colombier 		open_seq(0);
940*00d97012SDavid du Colombier 
941*00d97012SDavid du Colombier 		add_seq(nn(ZN, 'c', nn(z3, LT, z3, z2), ZN));	/* condition */
942*00d97012SDavid du Colombier 
943*00d97012SDavid du Colombier 		/* retrieve  message from the right slot -- for now: rotate contents */
944*00d97012SDavid du Colombier 		in_for = 0;
945*00d97012SDavid du Colombier 		add_seq(nn(a5, 'r', a5, expand(a3, 1)));	/* receive */
946*00d97012SDavid du Colombier 		add_seq(nn(a5, 's', a5, expand(a3, 1)));	/* put back in to rotate */
947*00d97012SDavid du Colombier 		in_for = 1;
948*00d97012SDavid du Colombier 		return z3;
949*00d97012SDavid du Colombier 	} else
950*00d97012SDavid du Colombier 	{	if (a5->sym->isarray == 0
951*00d97012SDavid du Colombier 		||  a5->sym->nel <= 0)
952*00d97012SDavid du Colombier 		{	fatal("bad arrayname %s", a5->sym->name);
953*00d97012SDavid du Colombier 		}
954*00d97012SDavid du Colombier 		z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0;
955*00d97012SDavid du Colombier 		z2 = nn(ZN, CONST, ZN, ZN); z2->val = a5->sym->nel - 1;
956*00d97012SDavid du Colombier 		for_setup(a3, z1, z2);
957*00d97012SDavid du Colombier 		return a3;
958*00d97012SDavid du Colombier 	}
959*00d97012SDavid du Colombier }
960*00d97012SDavid du Colombier 
961*00d97012SDavid du Colombier Lextok *
for_body(Lextok * a3,int with_else)962*00d97012SDavid du Colombier for_body(Lextok *a3, int with_else)
963*00d97012SDavid du Colombier {	Lextok *t1, *t2, *t0, *rv;
964*00d97012SDavid du Colombier 
965*00d97012SDavid du Colombier 	rv = nn(ZN, CONST, ZN, ZN); rv->val = 1;
966*00d97012SDavid du Colombier 	rv = nn(ZN,  '+', a3, rv);
967*00d97012SDavid du Colombier 	rv = nn(a3, ASGN, a3, rv);
968*00d97012SDavid du Colombier 	add_seq(rv);	/* initial increment */
969*00d97012SDavid du Colombier 
970*00d97012SDavid du Colombier 	pushbreak();
971*00d97012SDavid du Colombier 
972*00d97012SDavid du Colombier 	/* completed loop body, main sequence */
973*00d97012SDavid du Colombier 	t1 = nn(ZN, 0, ZN, ZN);
974*00d97012SDavid du Colombier 	t1->sq = close_seq(8);
975*00d97012SDavid du Colombier 
976*00d97012SDavid du Colombier 	open_seq(0);		/* add else -> break sequence */
977*00d97012SDavid du Colombier 	if (with_else)
978*00d97012SDavid du Colombier 	{	add_seq(nn(ZN, ELSE, ZN, ZN));
979*00d97012SDavid du Colombier 	}
980*00d97012SDavid du Colombier 	t2 = nn(ZN, GOTO, ZN, ZN);
981*00d97012SDavid du Colombier 	t2->sym = break_dest();
982*00d97012SDavid du Colombier 	add_seq(t2);
983*00d97012SDavid du Colombier 	t2 = nn(ZN, 0, ZN, ZN);
984*00d97012SDavid du Colombier 	t2->sq = close_seq(9);
985*00d97012SDavid du Colombier 
986*00d97012SDavid du Colombier 	t0 = nn(ZN, 0, ZN, ZN);
987*00d97012SDavid du Colombier 	t0->sl = seqlist(t2->sq, seqlist(t1->sq, 0));
988*00d97012SDavid du Colombier 
989*00d97012SDavid du Colombier 	rv = nn(ZN, DO, ZN, ZN);
990*00d97012SDavid du Colombier 	rv->sl = t0->sl;
991*00d97012SDavid du Colombier 	return rv;
992*00d97012SDavid du Colombier }
993*00d97012SDavid du Colombier 
994*00d97012SDavid du Colombier Lextok *
sel_index(Lextok * a3,Lextok * a5,Lextok * a7)995*00d97012SDavid du Colombier sel_index(Lextok *a3, Lextok *a5, Lextok *a7)
996*00d97012SDavid du Colombier {	/* select ( a3 : a5 .. a7 ) */
997*00d97012SDavid du Colombier 
998*00d97012SDavid du Colombier 	valid_name(a3, a5, a7, "select");
999*00d97012SDavid du Colombier 	/* a5->ntyp = a7->ntyp = CONST; */
1000*00d97012SDavid du Colombier 
1001*00d97012SDavid du Colombier 	add_seq(nn(a3, ASGN, a3, a5));	/* start value */
1002*00d97012SDavid du Colombier 	open_seq(0);
1003*00d97012SDavid du Colombier 	add_seq(nn(ZN, 'c', nn(a3, LT, a3, a7), ZN));	/* condition */
1004*00d97012SDavid du Colombier 
1005*00d97012SDavid du Colombier 	return for_body(a3, 0);	/* no else, just a non-deterministic break */
1006*00d97012SDavid du Colombier }
1007*00d97012SDavid du Colombier 
10087dd7cddfSDavid du Colombier static void
walk_atomic(Element * a,Element * b,int added)1009219b2ee8SDavid du Colombier walk_atomic(Element *a, Element *b, int added)
10107dd7cddfSDavid du Colombier {	Element *f; Symbol *ofn; int oln;
1011219b2ee8SDavid du Colombier 	SeqList *h;
1012219b2ee8SDavid du Colombier 
10137dd7cddfSDavid du Colombier 	ofn = Fname;
10147dd7cddfSDavid du Colombier 	oln = lineno;
1015219b2ee8SDavid du Colombier 	for (f = a; ; f = f->nxt)
1016219b2ee8SDavid du Colombier 	{	f->status |= (ATOM|added);
1017219b2ee8SDavid du Colombier 		switch (f->n->ntyp) {
1018219b2ee8SDavid du Colombier 		case ATOMIC:
10197dd7cddfSDavid du Colombier 			if (verbose&32)
1020*00d97012SDavid du Colombier 			  printf("spin: warning, %s:%d, atomic inside %s (ignored)\n",
1021*00d97012SDavid du Colombier 			  f->n->fn->name, f->n->ln, (added)?"d_step":"atomic");
10227dd7cddfSDavid du Colombier 			goto mknonat;
1023219b2ee8SDavid du Colombier 		case D_STEP:
10247dd7cddfSDavid du Colombier 			if (!(verbose&32))
10257dd7cddfSDavid du Colombier 			{	if (added) goto mknonat;
10267dd7cddfSDavid du Colombier 				break;
10277dd7cddfSDavid du Colombier 			}
1028*00d97012SDavid du Colombier 			printf("spin: warning, %s:%d, d_step inside ",
1029*00d97012SDavid du Colombier 			 f->n->fn->name, f->n->ln);
10307dd7cddfSDavid du Colombier 			if (added)
10317dd7cddfSDavid du Colombier 			{	printf("d_step (ignored)\n");
10327dd7cddfSDavid du Colombier 				goto mknonat;
10337dd7cddfSDavid du Colombier 			}
10347dd7cddfSDavid du Colombier 			printf("atomic\n");
1035219b2ee8SDavid du Colombier 			break;
1036219b2ee8SDavid du Colombier 		case NON_ATOMIC:
10377dd7cddfSDavid du Colombier mknonat:		f->n->ntyp = NON_ATOMIC; /* can jump here */
1038219b2ee8SDavid du Colombier 			h = f->n->sl;
1039219b2ee8SDavid du Colombier 			walk_atomic(h->this->frst, h->this->last, added);
1040219b2ee8SDavid du Colombier 			break;
1041312a1df1SDavid du Colombier 		case UNLESS:
1042312a1df1SDavid du Colombier 			if (added)
1043*00d97012SDavid du Colombier 			{ printf("spin: error, %s:%d, unless in d_step (ignored)\n",
1044*00d97012SDavid du Colombier 			 	 f->n->fn->name, f->n->ln);
1045312a1df1SDavid du Colombier 			}
1046219b2ee8SDavid du Colombier 		}
1047219b2ee8SDavid du Colombier 		for (h = f->sub; h; h = h->nxt)
1048219b2ee8SDavid du Colombier 			walk_atomic(h->this->frst, h->this->last, added);
1049219b2ee8SDavid du Colombier 		if (f == b)
1050219b2ee8SDavid du Colombier 			break;
1051219b2ee8SDavid du Colombier 	}
10527dd7cddfSDavid du Colombier 	Fname = ofn;
10537dd7cddfSDavid du Colombier 	lineno = oln;
1054219b2ee8SDavid du Colombier }
1055219b2ee8SDavid du Colombier 
1056219b2ee8SDavid du Colombier void
dumplabels(void)1057219b2ee8SDavid du Colombier dumplabels(void)
1058219b2ee8SDavid du Colombier {	Label *l;
1059219b2ee8SDavid du Colombier 
1060219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
1061219b2ee8SDavid du Colombier 		if (l->c != 0 && l->s->name[0] != ':')
1062*00d97012SDavid du Colombier 		{	printf("label	%s	%d	",
1063*00d97012SDavid du Colombier 				l->s->name, l->e->seqno);
1064*00d97012SDavid du Colombier 			if (l->uiid == 0)
1065*00d97012SDavid du Colombier 				printf("<%s>\n", l->c->name);
1066*00d97012SDavid du Colombier 			else
1067*00d97012SDavid du Colombier 				printf("<%s i%d>\n", l->c->name, l->uiid);
1068*00d97012SDavid du Colombier 		}
1069219b2ee8SDavid du Colombier }
1070