xref: /plan9-contrib/sys/src/cmd/spin/flow.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
1219b2ee8SDavid du Colombier /***** spin: flow.c *****/
2219b2ee8SDavid du Colombier 
3*de2caf28SDavid du Colombier /*
4*de2caf28SDavid du Colombier  * This file is part of the public release of Spin. It is subject to the
5*de2caf28SDavid du Colombier  * terms in the LICENSE file that is included in this source directory.
6*de2caf28SDavid du Colombier  * Tool documentation is available at http://spinroot.com
7*de2caf28SDavid du Colombier  */
8219b2ee8SDavid du Colombier 
9219b2ee8SDavid du Colombier #include "spin.h"
10219b2ee8SDavid du Colombier #include "y.tab.h"
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier extern Symbol	*Fname;
13*de2caf28SDavid du Colombier extern int	nr_errs, lineno, verbose, in_for, old_scope_rules, s_trail;
1400d97012SDavid du Colombier extern short	has_unless, has_badelse, has_xu;
1500d97012SDavid du Colombier extern char CurScope[MAXSCOPESZ];
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier Element *Al_El = ZE;
18219b2ee8SDavid du Colombier Label	*labtab = (Label *) 0;
197dd7cddfSDavid du Colombier int	Unique = 0, Elcnt = 0, DstepStart = -1;
2000d97012SDavid du Colombier int	initialization_ok = 1;
21*de2caf28SDavid du Colombier short	has_accept;
22219b2ee8SDavid du Colombier 
237dd7cddfSDavid du Colombier static Lbreak	*breakstack = (Lbreak *) 0;
247dd7cddfSDavid du Colombier static Lextok	*innermost;
257dd7cddfSDavid du Colombier static SeqList	*cur_s = (SeqList *) 0;
267dd7cddfSDavid du Colombier static int	break_id=0;
277dd7cddfSDavid du Colombier 
287dd7cddfSDavid du Colombier static Element	*if_seq(Lextok *);
297dd7cddfSDavid du Colombier static Element	*new_el(Lextok *);
307dd7cddfSDavid du Colombier static Element	*unless_seq(Lextok *);
317dd7cddfSDavid du Colombier static void	add_el(Element *, Sequence *);
327dd7cddfSDavid du Colombier static void	attach_escape(Sequence *, Sequence *);
337dd7cddfSDavid du Colombier static void	mov_lab(Symbol *, Element *, Element *);
347dd7cddfSDavid du Colombier static void	walk_atomic(Element *, Element *, int);
35219b2ee8SDavid du Colombier 
36219b2ee8SDavid du Colombier void
open_seq(int top)37219b2ee8SDavid du Colombier open_seq(int top)
38219b2ee8SDavid du Colombier {	SeqList *t;
39219b2ee8SDavid du Colombier 	Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
40*de2caf28SDavid du Colombier 	s->minel = -1;
41219b2ee8SDavid du Colombier 
42219b2ee8SDavid du Colombier 	t = seqlist(s, cur_s);
43219b2ee8SDavid du Colombier 	cur_s = t;
4400d97012SDavid du Colombier 	if (top)
4500d97012SDavid du Colombier 	{	Elcnt = 1;
4600d97012SDavid du Colombier 		initialization_ok = 1;
47*de2caf28SDavid du Colombier 	} else
48*de2caf28SDavid du Colombier 	{	initialization_ok = 0;
4900d97012SDavid du Colombier 	}
50219b2ee8SDavid du Colombier }
51219b2ee8SDavid du Colombier 
52219b2ee8SDavid du Colombier void
rem_Seq(void)53219b2ee8SDavid du Colombier rem_Seq(void)
54219b2ee8SDavid du Colombier {
55219b2ee8SDavid du Colombier 	DstepStart = Unique;
56219b2ee8SDavid du Colombier }
57219b2ee8SDavid du Colombier 
58219b2ee8SDavid du Colombier void
unrem_Seq(void)59219b2ee8SDavid du Colombier unrem_Seq(void)
60219b2ee8SDavid du Colombier {
61219b2ee8SDavid du Colombier 	DstepStart = -1;
62219b2ee8SDavid du Colombier }
63219b2ee8SDavid du Colombier 
647dd7cddfSDavid du Colombier static int
Rjumpslocal(Element * q,Element * stop)65219b2ee8SDavid du Colombier Rjumpslocal(Element *q, Element *stop)
66219b2ee8SDavid du Colombier {	Element *lb, *f;
67219b2ee8SDavid du Colombier 	SeqList *h;
68219b2ee8SDavid du Colombier 
69219b2ee8SDavid du Colombier 	/* allow no jumps out of a d_step sequence */
70219b2ee8SDavid du Colombier 	for (f = q; f && f != stop; f = f->nxt)
71219b2ee8SDavid du Colombier 	{	if (f && f->n && f->n->ntyp == GOTO)
72219b2ee8SDavid du Colombier 		{	lb = get_lab(f->n, 0);
73219b2ee8SDavid du Colombier 			if (!lb || lb->Seqno < DstepStart)
74219b2ee8SDavid du Colombier 			{	lineno = f->n->ln;
75219b2ee8SDavid du Colombier 				Fname = f->n->fn;
76219b2ee8SDavid du Colombier 				return 0;
77219b2ee8SDavid du Colombier 		}	}
78219b2ee8SDavid du Colombier 		for (h = f->sub; h; h = h->nxt)
79219b2ee8SDavid du Colombier 		{	if (!Rjumpslocal(h->this->frst, h->this->last))
80219b2ee8SDavid du Colombier 				return 0;
81219b2ee8SDavid du Colombier 
82219b2ee8SDavid du Colombier 	}	}
83219b2ee8SDavid du Colombier 	return 1;
84219b2ee8SDavid du Colombier }
85219b2ee8SDavid du Colombier 
86219b2ee8SDavid du Colombier void
cross_dsteps(Lextok * a,Lextok * b)87219b2ee8SDavid du Colombier cross_dsteps(Lextok *a, Lextok *b)
88219b2ee8SDavid du Colombier {
89219b2ee8SDavid du Colombier 	if (a && b
90219b2ee8SDavid du Colombier 	&&  a->indstep != b->indstep)
91219b2ee8SDavid du Colombier 	{	lineno = a->ln;
92219b2ee8SDavid du Colombier 		Fname  = a->fn;
93*de2caf28SDavid du Colombier 		if (!s_trail)
94219b2ee8SDavid du Colombier 		fatal("jump into d_step sequence", (char *) 0);
95219b2ee8SDavid du Colombier 	}
96219b2ee8SDavid du Colombier }
97219b2ee8SDavid du Colombier 
987dd7cddfSDavid du Colombier int
is_skip(Lextok * n)997dd7cddfSDavid du Colombier is_skip(Lextok *n)
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier 	return (n->ntyp == PRINT
102312a1df1SDavid du Colombier 	||	n->ntyp == PRINTM
1037dd7cddfSDavid du Colombier 	||	(n->ntyp == 'c'
1047dd7cddfSDavid du Colombier 		&& n->lft
1057dd7cddfSDavid du Colombier 		&& n->lft->ntyp == CONST
1067dd7cddfSDavid du Colombier 		&& n->lft->val  == 1));
1077dd7cddfSDavid du Colombier }
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier void
check_sequence(Sequence * s)1107dd7cddfSDavid du Colombier check_sequence(Sequence *s)
1117dd7cddfSDavid du Colombier {	Element *e, *le = ZE;
1127dd7cddfSDavid du Colombier 	Lextok *n;
1137dd7cddfSDavid du Colombier 	int cnt = 0;
1147dd7cddfSDavid du Colombier 
1157dd7cddfSDavid du Colombier 	for (e = s->frst; e; le = e, e = e->nxt)
1167dd7cddfSDavid du Colombier 	{	n = e->n;
1177dd7cddfSDavid du Colombier 		if (is_skip(n) && !has_lab(e, 0))
1187dd7cddfSDavid du Colombier 		{	cnt++;
119312a1df1SDavid du Colombier 			if (cnt > 1
120312a1df1SDavid du Colombier 			&&  n->ntyp != PRINT
121312a1df1SDavid du Colombier 			&&  n->ntyp != PRINTM)
1227dd7cddfSDavid du Colombier 			{	if (verbose&32)
12300d97012SDavid du Colombier 					printf("spin: %s:%d, redundant skip\n",
12400d97012SDavid du Colombier 						n->fn->name, n->ln);
125312a1df1SDavid du Colombier 				if (e != s->frst
126312a1df1SDavid du Colombier 				&&  e != s->last
127312a1df1SDavid du Colombier 				&&  e != s->extent)
1287dd7cddfSDavid du Colombier 				{	e->status |= DONE;	/* not unreachable */
1297dd7cddfSDavid du Colombier 					le->nxt = e->nxt;	/* remove it */
1307dd7cddfSDavid du Colombier 					e = le;
131312a1df1SDavid du Colombier 				}
1327dd7cddfSDavid du Colombier 			}
1337dd7cddfSDavid du Colombier 		} else
1347dd7cddfSDavid du Colombier 			cnt = 0;
1357dd7cddfSDavid du Colombier 	}
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier void
prune_opts(Lextok * n)1397dd7cddfSDavid du Colombier prune_opts(Lextok *n)
1407dd7cddfSDavid du Colombier {	SeqList *l;
1417dd7cddfSDavid du Colombier 	extern Symbol *context;
1427dd7cddfSDavid du Colombier 	extern char *claimproc;
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	if (!n
1457dd7cddfSDavid du Colombier 	|| (context && claimproc && strcmp(context->name, claimproc) == 0))
1467dd7cddfSDavid du Colombier 		return;
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier 	for (l = n->sl; l; l = l->nxt)	/* find sequences of unlabeled skips */
1497dd7cddfSDavid du Colombier 		check_sequence(l->this);
1507dd7cddfSDavid du Colombier }
1517dd7cddfSDavid du Colombier 
152219b2ee8SDavid du Colombier Sequence *
close_seq(int nottop)153219b2ee8SDavid du Colombier close_seq(int nottop)
154219b2ee8SDavid du Colombier {	Sequence *s = cur_s->this;
155219b2ee8SDavid du Colombier 	Symbol *z;
156219b2ee8SDavid du Colombier 
15700d97012SDavid du Colombier 	if (nottop == 0)	/* end of proctype body */
15800d97012SDavid du Colombier 	{	initialization_ok = 1;
15900d97012SDavid du Colombier 	}
16000d97012SDavid du Colombier 
161*de2caf28SDavid du Colombier 	if (nottop > 0 && s->frst && (z = has_lab(s->frst, 0)))
162219b2ee8SDavid du Colombier 	{	printf("error: (%s:%d) label %s placed incorrectly\n",
163219b2ee8SDavid du Colombier 			(s->frst->n)?s->frst->n->fn->name:"-",
164219b2ee8SDavid du Colombier 			(s->frst->n)?s->frst->n->ln:0,
165219b2ee8SDavid du Colombier 			z->name);
166219b2ee8SDavid du Colombier 		switch (nottop) {
167219b2ee8SDavid du Colombier 		case 1:
168219b2ee8SDavid du Colombier 			printf("=====> stmnt unless Label: stmnt\n");
169219b2ee8SDavid du Colombier 			printf("sorry, cannot jump to the guard of an\n");
170219b2ee8SDavid du Colombier 			printf("escape (it is not a unique state)\n");
171219b2ee8SDavid du Colombier 			break;
172219b2ee8SDavid du Colombier 		case 2:
173219b2ee8SDavid du Colombier 			printf("=====> instead of  ");
174219b2ee8SDavid du Colombier 			printf("\"Label: stmnt unless stmnt\"\n");
175219b2ee8SDavid du Colombier 			printf("=====> always use  ");
176219b2ee8SDavid du Colombier 			printf("\"Label: { stmnt unless stmnt }\"\n");
177219b2ee8SDavid du Colombier 			break;
178219b2ee8SDavid du Colombier 		case 3:
179219b2ee8SDavid du Colombier 			printf("=====> instead of  ");
180219b2ee8SDavid du Colombier 			printf("\"atomic { Label: statement ... }\"\n");
181219b2ee8SDavid du Colombier 			printf("=====> always use  ");
182219b2ee8SDavid du Colombier 			printf("\"Label: atomic { statement ... }\"\n");
183219b2ee8SDavid du Colombier 			break;
184219b2ee8SDavid du Colombier 		case 4:
185219b2ee8SDavid du Colombier 			printf("=====> instead of  ");
186219b2ee8SDavid du Colombier 			printf("\"d_step { Label: statement ... }\"\n");
187219b2ee8SDavid du Colombier 			printf("=====> always use  ");
188219b2ee8SDavid du Colombier 			printf("\"Label: d_step { statement ... }\"\n");
189219b2ee8SDavid du Colombier 			break;
190219b2ee8SDavid du Colombier 		case 5:
191219b2ee8SDavid du Colombier 			printf("=====> instead of  ");
192219b2ee8SDavid du Colombier 			printf("\"{ Label: statement ... }\"\n");
193219b2ee8SDavid du Colombier 			printf("=====> always use  ");
194219b2ee8SDavid du Colombier 			printf("\"Label: { statement ... }\"\n");
195219b2ee8SDavid du Colombier 			break;
196219b2ee8SDavid du Colombier 		case 6:
197219b2ee8SDavid du Colombier 			printf("=====> instead of\n");
198219b2ee8SDavid du Colombier 			printf("	do (or if)\n");
199219b2ee8SDavid du Colombier 			printf("	:: ...\n");
200219b2ee8SDavid du Colombier 			printf("	:: Label: statement\n");
201219b2ee8SDavid du Colombier 			printf("	od (of fi)\n");
202*de2caf28SDavid du Colombier 			printf("=====> use\n");
203219b2ee8SDavid du Colombier 			printf("Label:	do (or if)\n");
204219b2ee8SDavid du Colombier 			printf("	:: ...\n");
205219b2ee8SDavid du Colombier 			printf("	:: statement\n");
206219b2ee8SDavid du Colombier 			printf("	od (or fi)\n");
207219b2ee8SDavid du Colombier 			break;
208219b2ee8SDavid du Colombier 		case 7:
209219b2ee8SDavid du Colombier 			printf("cannot happen - labels\n");
210219b2ee8SDavid du Colombier 			break;
211219b2ee8SDavid du Colombier 		}
212*de2caf28SDavid du Colombier 		if (nottop != 6)
213*de2caf28SDavid du Colombier 		{	alldone(1);
214*de2caf28SDavid du Colombier 	}	}
215219b2ee8SDavid du Colombier 
216219b2ee8SDavid du Colombier 	if (nottop == 4
217219b2ee8SDavid du Colombier 	&& !Rjumpslocal(s->frst, s->last))
218219b2ee8SDavid du Colombier 		fatal("non_local jump in d_step sequence", (char *) 0);
219219b2ee8SDavid du Colombier 
220219b2ee8SDavid du Colombier 	cur_s = cur_s->nxt;
221219b2ee8SDavid du Colombier 	s->maxel = Elcnt;
222219b2ee8SDavid du Colombier 	s->extent = s->last;
2237dd7cddfSDavid du Colombier 	if (!s->last)
2247dd7cddfSDavid du Colombier 		fatal("sequence must have at least one statement", (char *) 0);
225219b2ee8SDavid du Colombier 	return s;
226219b2ee8SDavid du Colombier }
227219b2ee8SDavid du Colombier 
228219b2ee8SDavid du Colombier Lextok *
do_unless(Lextok * No,Lextok * Es)229219b2ee8SDavid du Colombier do_unless(Lextok *No, Lextok *Es)
230219b2ee8SDavid du Colombier {	SeqList *Sl;
231219b2ee8SDavid du Colombier 	Lextok *Re = nn(ZN, UNLESS, ZN, ZN);
232*de2caf28SDavid du Colombier 
233219b2ee8SDavid du Colombier 	Re->ln = No->ln;
234219b2ee8SDavid du Colombier 	Re->fn = No->fn;
235219b2ee8SDavid du Colombier 	has_unless++;
236*de2caf28SDavid du Colombier 
237219b2ee8SDavid du Colombier 	if (Es->ntyp == NON_ATOMIC)
238*de2caf28SDavid du Colombier 	{	Sl = Es->sl;
239*de2caf28SDavid du Colombier 	} else
240219b2ee8SDavid du Colombier 	{	open_seq(0); add_seq(Es);
241219b2ee8SDavid du Colombier 		Sl = seqlist(close_seq(1), 0);
242219b2ee8SDavid du Colombier 	}
243219b2ee8SDavid du Colombier 
244219b2ee8SDavid du Colombier 	if (No->ntyp == NON_ATOMIC)
245219b2ee8SDavid du Colombier 	{	No->sl->nxt = Sl;
246219b2ee8SDavid du Colombier 		Sl = No->sl;
247219b2ee8SDavid du Colombier 	} else	if (No->ntyp == ':'
248219b2ee8SDavid du Colombier 		&& (No->lft->ntyp == NON_ATOMIC
249219b2ee8SDavid du Colombier 		||  No->lft->ntyp == ATOMIC
250219b2ee8SDavid du Colombier 		||  No->lft->ntyp == D_STEP))
251219b2ee8SDavid du Colombier 	{
252219b2ee8SDavid du Colombier 		int tok = No->lft->ntyp;
253219b2ee8SDavid du Colombier 
254219b2ee8SDavid du Colombier 		No->lft->sl->nxt = Sl;
255219b2ee8SDavid du Colombier 		Re->sl = No->lft->sl;
256219b2ee8SDavid du Colombier 
257219b2ee8SDavid du Colombier 		open_seq(0); add_seq(Re);
258219b2ee8SDavid du Colombier 		Re = nn(ZN, tok, ZN, ZN);
259219b2ee8SDavid du Colombier 		Re->sl = seqlist(close_seq(7), 0);
260219b2ee8SDavid du Colombier 		Re->ln = No->ln;
261219b2ee8SDavid du Colombier 		Re->fn = No->fn;
262219b2ee8SDavid du Colombier 
263219b2ee8SDavid du Colombier 		Re = nn(No, ':', Re, ZN);	/* lift label */
264219b2ee8SDavid du Colombier 		Re->ln = No->ln;
265219b2ee8SDavid du Colombier 		Re->fn = No->fn;
266219b2ee8SDavid du Colombier 		return Re;
267219b2ee8SDavid du Colombier 	} else
268219b2ee8SDavid du Colombier 	{	open_seq(0); add_seq(No);
269219b2ee8SDavid du Colombier 		Sl = seqlist(close_seq(2), Sl);
270219b2ee8SDavid du Colombier 	}
271219b2ee8SDavid du Colombier 
272219b2ee8SDavid du Colombier 	Re->sl = Sl;
273219b2ee8SDavid du Colombier 	return Re;
274219b2ee8SDavid du Colombier }
275219b2ee8SDavid du Colombier 
276219b2ee8SDavid du Colombier SeqList *
seqlist(Sequence * s,SeqList * r)277219b2ee8SDavid du Colombier seqlist(Sequence *s, SeqList *r)
278219b2ee8SDavid du Colombier {	SeqList *t = (SeqList *) emalloc(sizeof(SeqList));
279219b2ee8SDavid du Colombier 
280219b2ee8SDavid du Colombier 	t->this = s;
281219b2ee8SDavid du Colombier 	t->nxt = r;
282219b2ee8SDavid du Colombier 	return t;
283219b2ee8SDavid du Colombier }
284219b2ee8SDavid du Colombier 
2857dd7cddfSDavid du Colombier static Element *
new_el(Lextok * n)286219b2ee8SDavid du Colombier new_el(Lextok *n)
287219b2ee8SDavid du Colombier {	Element *m;
288219b2ee8SDavid du Colombier 
289219b2ee8SDavid du Colombier 	if (n)
290219b2ee8SDavid du Colombier 	{	if (n->ntyp == IF || n->ntyp == DO)
291219b2ee8SDavid du Colombier 			return if_seq(n);
292219b2ee8SDavid du Colombier 		if (n->ntyp == UNLESS)
293219b2ee8SDavid du Colombier 			return unless_seq(n);
294219b2ee8SDavid du Colombier 	}
295219b2ee8SDavid du Colombier 	m = (Element *) emalloc(sizeof(Element));
296219b2ee8SDavid du Colombier 	m->n = n;
297219b2ee8SDavid du Colombier 	m->seqno = Elcnt++;
298219b2ee8SDavid du Colombier 	m->Seqno = Unique++;
299219b2ee8SDavid du Colombier 	m->Nxt = Al_El; Al_El = m;
300219b2ee8SDavid du Colombier 	return m;
301219b2ee8SDavid du Colombier }
302219b2ee8SDavid du Colombier 
3037dd7cddfSDavid du Colombier static int
has_chanref(Lextok * n)3047dd7cddfSDavid du Colombier has_chanref(Lextok *n)
3057dd7cddfSDavid du Colombier {
3067dd7cddfSDavid du Colombier 	if (!n) return 0;
3077dd7cddfSDavid du Colombier 
3087dd7cddfSDavid du Colombier 	switch (n->ntyp) {
3097dd7cddfSDavid du Colombier 	case 's':	case 'r':
3107dd7cddfSDavid du Colombier #if 0
3117dd7cddfSDavid du Colombier 	case 'R':	case LEN:
3127dd7cddfSDavid du Colombier #endif
3137dd7cddfSDavid du Colombier 	case FULL:	case NFULL:
3147dd7cddfSDavid du Colombier 	case EMPTY:	case NEMPTY:
3157dd7cddfSDavid du Colombier 		return 1;
3167dd7cddfSDavid du Colombier 	default:
3177dd7cddfSDavid du Colombier 		break;
3187dd7cddfSDavid du Colombier 	}
3197dd7cddfSDavid du Colombier 	if (has_chanref(n->lft))
3207dd7cddfSDavid du Colombier 		return 1;
3217dd7cddfSDavid du Colombier 
3227dd7cddfSDavid du Colombier 	return has_chanref(n->rgt);
3237dd7cddfSDavid du Colombier }
3247dd7cddfSDavid du Colombier 
325312a1df1SDavid du Colombier void
loose_ends(void)326312a1df1SDavid du Colombier loose_ends(void)	/* properly tie-up ends of sub-sequences */
327312a1df1SDavid du Colombier {	Element *e, *f;
328312a1df1SDavid du Colombier 
329312a1df1SDavid du Colombier 	for (e = Al_El; e; e = e->Nxt)
330312a1df1SDavid du Colombier 	{	if (!e->n
331312a1df1SDavid du Colombier 		||  !e->nxt)
332312a1df1SDavid du Colombier 			continue;
333312a1df1SDavid du Colombier 		switch (e->n->ntyp) {
334312a1df1SDavid du Colombier 		case ATOMIC:
335312a1df1SDavid du Colombier 		case NON_ATOMIC:
336312a1df1SDavid du Colombier 		case D_STEP:
337312a1df1SDavid du Colombier 			f = e->nxt;
338312a1df1SDavid du Colombier 			while (f && f->n->ntyp == '.')
339312a1df1SDavid du Colombier 				f = f->nxt;
340312a1df1SDavid du Colombier 			if (0) printf("link %d, {%d .. %d} -> %d (ntyp=%d) was %d\n",
341312a1df1SDavid du Colombier 				e->seqno,
342312a1df1SDavid du Colombier 				e->n->sl->this->frst->seqno,
343312a1df1SDavid du Colombier 				e->n->sl->this->last->seqno,
344312a1df1SDavid du Colombier 				f?f->seqno:-1, f?f->n->ntyp:-1,
345312a1df1SDavid du Colombier 				e->n->sl->this->last->nxt?e->n->sl->this->last->nxt->seqno:-1);
346312a1df1SDavid du Colombier 			if (!e->n->sl->this->last->nxt)
347312a1df1SDavid du Colombier 				e->n->sl->this->last->nxt = f;
348312a1df1SDavid du Colombier 			else
349312a1df1SDavid du Colombier 			{	if (e->n->sl->this->last->nxt->n->ntyp != GOTO)
350312a1df1SDavid du Colombier 				{	if (!f || e->n->sl->this->last->nxt->seqno != f->seqno)
351312a1df1SDavid du Colombier 					non_fatal("unexpected: loose ends", (char *)0);
352312a1df1SDavid du Colombier 				} else
353312a1df1SDavid du Colombier 					e->n->sl->this->last = e->n->sl->this->last->nxt;
354312a1df1SDavid du Colombier 				/*
355312a1df1SDavid du Colombier 				 * fix_dest can push a goto into the nxt position
356312a1df1SDavid du Colombier 				 * in that case the goto wins and f is not needed
357312a1df1SDavid du Colombier 				 * but the last fields needs adjusting
358312a1df1SDavid du Colombier 				 */
359312a1df1SDavid du Colombier 			}
360312a1df1SDavid du Colombier 			break;
361312a1df1SDavid du Colombier 	}	}
362312a1df1SDavid du Colombier }
363312a1df1SDavid du Colombier 
364*de2caf28SDavid du Colombier void
popbreak(void)365*de2caf28SDavid du Colombier popbreak(void)
366*de2caf28SDavid du Colombier {
367*de2caf28SDavid du Colombier 	if (!breakstack)
368*de2caf28SDavid du Colombier 		fatal("cannot happen, breakstack", (char *) 0);
369*de2caf28SDavid du Colombier 
370*de2caf28SDavid du Colombier 	breakstack = breakstack->nxt;	/* pop stack */
371*de2caf28SDavid du Colombier }
372*de2caf28SDavid du Colombier 
373*de2caf28SDavid du Colombier static Lbreak *ob = (Lbreak *) 0;
374*de2caf28SDavid du Colombier 
375*de2caf28SDavid du Colombier void
safe_break(void)376*de2caf28SDavid du Colombier safe_break(void)
377*de2caf28SDavid du Colombier {
378*de2caf28SDavid du Colombier 	ob = breakstack;
379*de2caf28SDavid du Colombier 	popbreak();
380*de2caf28SDavid du Colombier }
381*de2caf28SDavid du Colombier 
382*de2caf28SDavid du Colombier void
restore_break(void)383*de2caf28SDavid du Colombier restore_break(void)
384*de2caf28SDavid du Colombier {
385*de2caf28SDavid du Colombier 	breakstack = ob;
386*de2caf28SDavid du Colombier 	ob = (Lbreak *) 0;
387*de2caf28SDavid du Colombier }
388*de2caf28SDavid du Colombier 
3897dd7cddfSDavid du Colombier static Element *
if_seq(Lextok * n)390219b2ee8SDavid du Colombier if_seq(Lextok *n)
391219b2ee8SDavid du Colombier {	int	tok = n->ntyp;
392219b2ee8SDavid du Colombier 	SeqList	*s  = n->sl;
393219b2ee8SDavid du Colombier 	Element	*e  = new_el(ZN);
394219b2ee8SDavid du Colombier 	Element	*t  = new_el(nn(ZN,'.',ZN,ZN)); /* target */
395219b2ee8SDavid du Colombier 	SeqList	*z, *prev_z = (SeqList *) 0;
396219b2ee8SDavid du Colombier 	SeqList *move_else  = (SeqList *) 0;	/* to end of optionlist */
3977dd7cddfSDavid du Colombier 	int	ref_chans = 0;
398219b2ee8SDavid du Colombier 
399219b2ee8SDavid du Colombier 	for (z = s; z; z = z->nxt)
4007dd7cddfSDavid du Colombier 	{	if (!z->this->frst)
4017dd7cddfSDavid du Colombier 			continue;
4027dd7cddfSDavid du Colombier 		if (z->this->frst->n->ntyp == ELSE)
403219b2ee8SDavid du Colombier 		{	if (move_else)
404219b2ee8SDavid du Colombier 				fatal("duplicate `else'", (char *) 0);
405219b2ee8SDavid du Colombier 			if (z->nxt)	/* is not already at the end */
406219b2ee8SDavid du Colombier 			{	move_else = z;
407219b2ee8SDavid du Colombier 				if (prev_z)
408219b2ee8SDavid du Colombier 					prev_z->nxt = z->nxt;
409219b2ee8SDavid du Colombier 				else
410219b2ee8SDavid du Colombier 					s = n->sl = z->nxt;
411219b2ee8SDavid du Colombier 				continue;
412219b2ee8SDavid du Colombier 			}
413219b2ee8SDavid du Colombier 		} else
4147dd7cddfSDavid du Colombier 			ref_chans |= has_chanref(z->this->frst->n);
415219b2ee8SDavid du Colombier 		prev_z = z;
416219b2ee8SDavid du Colombier 	}
417219b2ee8SDavid du Colombier 	if (move_else)
418219b2ee8SDavid du Colombier 	{	move_else->nxt = (SeqList *) 0;
419219b2ee8SDavid du Colombier 		/* if there is no prev, then else was at the end */
420219b2ee8SDavid du Colombier 		if (!prev_z) fatal("cannot happen - if_seq", (char *) 0);
421219b2ee8SDavid du Colombier 		prev_z->nxt = move_else;
422219b2ee8SDavid du Colombier 		prev_z = move_else;
423219b2ee8SDavid du Colombier 	}
424219b2ee8SDavid du Colombier 	if (prev_z
4257dd7cddfSDavid du Colombier 	&&  ref_chans
426219b2ee8SDavid du Colombier 	&&  prev_z->this->frst->n->ntyp == ELSE)
4277dd7cddfSDavid du Colombier 	{	prev_z->this->frst->n->val = 1;
4287dd7cddfSDavid du Colombier 		has_badelse++;
42900d97012SDavid du Colombier 		if (has_xu)
43000d97012SDavid du Colombier 		{	fatal("invalid use of 'else' combined with i/o and xr/xs assertions,",
4317dd7cddfSDavid du Colombier 				(char *)0);
43200d97012SDavid du Colombier 		} else
43300d97012SDavid du Colombier 		{	non_fatal("dubious use of 'else' combined with i/o,",
43400d97012SDavid du Colombier 				(char *)0);
43500d97012SDavid du Colombier 		}
4367dd7cddfSDavid du Colombier 		nr_errs--;
4377dd7cddfSDavid du Colombier 	}
438219b2ee8SDavid du Colombier 
439219b2ee8SDavid du Colombier 	e->n = nn(n, tok, ZN, ZN);
440219b2ee8SDavid du Colombier 	e->n->sl = s;			/* preserve as info only */
441219b2ee8SDavid du Colombier 	e->sub = s;
442*de2caf28SDavid du Colombier 	for (z = s; z; z = z->nxt)
443219b2ee8SDavid du Colombier 		add_el(t, z->this);	/* append target */
444219b2ee8SDavid du Colombier 	if (tok == DO)
445219b2ee8SDavid du Colombier 	{	add_el(t, cur_s->this); /* target upfront */
446219b2ee8SDavid du Colombier 		t = new_el(nn(n, BREAK, ZN, ZN)); /* break target */
447219b2ee8SDavid du Colombier 		set_lab(break_dest(), t);	/* new exit  */
448*de2caf28SDavid du Colombier 		popbreak();
449219b2ee8SDavid du Colombier 	}
450219b2ee8SDavid du Colombier 	add_el(e, cur_s->this);
451219b2ee8SDavid du Colombier 	add_el(t, cur_s->this);
452219b2ee8SDavid du Colombier 	return e;			/* destination node for label */
453219b2ee8SDavid du Colombier }
454219b2ee8SDavid du Colombier 
4557dd7cddfSDavid du Colombier static void
escape_el(Element * f,Sequence * e)4567dd7cddfSDavid du Colombier escape_el(Element *f, Sequence *e)
4577dd7cddfSDavid du Colombier {	SeqList *z;
458219b2ee8SDavid du Colombier 
4597dd7cddfSDavid du Colombier 	for (z = f->esc; z; z = z->nxt)
4607dd7cddfSDavid du Colombier 		if (z->this == e)
4617dd7cddfSDavid du Colombier 			return;	/* already there */
4627dd7cddfSDavid du Colombier 
4637dd7cddfSDavid du Colombier 	/* cover the lower-level escapes of this state */
4647dd7cddfSDavid du Colombier 	for (z = f->esc; z; z = z->nxt)
4657dd7cddfSDavid du Colombier 		attach_escape(z->this, e);
4667dd7cddfSDavid du Colombier 
4677dd7cddfSDavid du Colombier 	/* now attach escape to the state itself */
4687dd7cddfSDavid du Colombier 
4697dd7cddfSDavid du Colombier 	f->esc = seqlist(e, f->esc);	/* in lifo order... */
470219b2ee8SDavid du Colombier #ifdef DEBUG
471219b2ee8SDavid du Colombier 	printf("attach %d (", e->frst->Seqno);
472219b2ee8SDavid du Colombier 	comment(stdout, e->frst->n, 0);
473219b2ee8SDavid du Colombier 	printf(")	to %d (", f->Seqno);
474219b2ee8SDavid du Colombier 	comment(stdout, f->n, 0);
475219b2ee8SDavid du Colombier 	printf(")\n");
476219b2ee8SDavid du Colombier #endif
4777dd7cddfSDavid du Colombier 	switch (f->n->ntyp) {
4787dd7cddfSDavid du Colombier 	case UNLESS:
4797dd7cddfSDavid du Colombier 		attach_escape(f->sub->this, e);
4807dd7cddfSDavid du Colombier 		break;
4817dd7cddfSDavid du Colombier 	case IF:
4827dd7cddfSDavid du Colombier 	case DO:
4837dd7cddfSDavid du Colombier 		for (z = f->sub; z; z = z->nxt)
484219b2ee8SDavid du Colombier 			attach_escape(z->this, e);
4857dd7cddfSDavid du Colombier 		break;
4867dd7cddfSDavid du Colombier 	case D_STEP:
4877dd7cddfSDavid du Colombier 		/* attach only to the guard stmnt */
4887dd7cddfSDavid du Colombier 		escape_el(f->n->sl->this->frst, e);
4897dd7cddfSDavid du Colombier 		break;
4907dd7cddfSDavid du Colombier 	case ATOMIC:
4917dd7cddfSDavid du Colombier 	case NON_ATOMIC:
4927dd7cddfSDavid du Colombier 		/* attach to all stmnts */
4937dd7cddfSDavid du Colombier 		attach_escape(f->n->sl->this, e);
4947dd7cddfSDavid du Colombier 		break;
495219b2ee8SDavid du Colombier 	}
496219b2ee8SDavid du Colombier }
497219b2ee8SDavid du Colombier 
4987dd7cddfSDavid du Colombier static void
attach_escape(Sequence * n,Sequence * e)4997dd7cddfSDavid du Colombier attach_escape(Sequence *n, Sequence *e)
5007dd7cddfSDavid du Colombier {	Element *f;
5017dd7cddfSDavid du Colombier 
5027dd7cddfSDavid du Colombier 	for (f = n->frst; f; f = f->nxt)
5037dd7cddfSDavid du Colombier 	{	escape_el(f, e);
5047dd7cddfSDavid du Colombier 		if (f == n->extent)
5057dd7cddfSDavid du Colombier 			break;
5067dd7cddfSDavid du Colombier 	}
5077dd7cddfSDavid du Colombier }
5087dd7cddfSDavid du Colombier 
5097dd7cddfSDavid du Colombier static Element *
unless_seq(Lextok * n)510219b2ee8SDavid du Colombier unless_seq(Lextok *n)
511219b2ee8SDavid du Colombier {	SeqList	*s  = n->sl;
512219b2ee8SDavid du Colombier 	Element	*e  = new_el(ZN);
513219b2ee8SDavid du Colombier 	Element	*t  = new_el(nn(ZN,'.',ZN,ZN)); /* target */
514219b2ee8SDavid du Colombier 	SeqList	*z;
515219b2ee8SDavid du Colombier 
516219b2ee8SDavid du Colombier 	e->n = nn(n, UNLESS, ZN, ZN);
517219b2ee8SDavid du Colombier 	e->n->sl = s;			/* info only */
518219b2ee8SDavid du Colombier 	e->sub = s;
519219b2ee8SDavid du Colombier 
5207dd7cddfSDavid du Colombier 	/* need 2 sequences: normal execution and escape */
521219b2ee8SDavid du Colombier 	if (!s || !s->nxt || s->nxt->nxt)
522219b2ee8SDavid du Colombier 		fatal("unexpected unless structure", (char *)0);
5237dd7cddfSDavid du Colombier 
5247dd7cddfSDavid du Colombier 	/* append the target state to both */
525219b2ee8SDavid du Colombier 	for (z = s; z; z = z->nxt)
526219b2ee8SDavid du Colombier 		add_el(t, z->this);
5277dd7cddfSDavid du Colombier 
5287dd7cddfSDavid du Colombier 	/* attach escapes to all states in normal sequence */
529219b2ee8SDavid du Colombier 	attach_escape(s->this, s->nxt->this);
530219b2ee8SDavid du Colombier 
531219b2ee8SDavid du Colombier 	add_el(e, cur_s->this);
532219b2ee8SDavid du Colombier 	add_el(t, cur_s->this);
533219b2ee8SDavid du Colombier #ifdef DEBUG
534219b2ee8SDavid du Colombier 	printf("unless element (%d,%d):\n", e->Seqno, t->Seqno);
535219b2ee8SDavid du Colombier 	for (z = s; z; z = z->nxt)
536219b2ee8SDavid du Colombier 	{	Element *x; printf("\t%d,%d,%d :: ",
537219b2ee8SDavid du Colombier 		z->this->frst->Seqno,
538219b2ee8SDavid du Colombier 		z->this->extent->Seqno,
539219b2ee8SDavid du Colombier 		z->this->last->Seqno);
540219b2ee8SDavid du Colombier 		for (x = z->this->frst; x; x = x->nxt)
541219b2ee8SDavid du Colombier 			printf("(%d)", x->Seqno);
542219b2ee8SDavid du Colombier 		printf("\n");
543219b2ee8SDavid du Colombier 	}
544219b2ee8SDavid du Colombier #endif
545219b2ee8SDavid du Colombier 	return e;
546219b2ee8SDavid du Colombier }
547219b2ee8SDavid du Colombier 
548219b2ee8SDavid du Colombier Element *
mk_skip(void)549219b2ee8SDavid du Colombier mk_skip(void)
550219b2ee8SDavid du Colombier {	Lextok  *t = nn(ZN, CONST, ZN, ZN);
551219b2ee8SDavid du Colombier 	t->val = 1;
552219b2ee8SDavid du Colombier 	return new_el(nn(ZN, 'c', t, ZN));
553219b2ee8SDavid du Colombier }
554219b2ee8SDavid du Colombier 
5557dd7cddfSDavid du Colombier static void
add_el(Element * e,Sequence * s)556219b2ee8SDavid du Colombier add_el(Element *e, Sequence *s)
557219b2ee8SDavid du Colombier {
558219b2ee8SDavid du Colombier 	if (e->n->ntyp == GOTO)
5597dd7cddfSDavid du Colombier 	{	Symbol *z = has_lab(e, (1|2|4));
5607dd7cddfSDavid du Colombier 		if (z)
561219b2ee8SDavid du Colombier 		{	Element *y; /* insert a skip */
562219b2ee8SDavid du Colombier 			y = mk_skip();
563219b2ee8SDavid du Colombier 			mov_lab(z, e, y); /* inherit label */
564219b2ee8SDavid du Colombier 			add_el(y, s);
565219b2ee8SDavid du Colombier 	}	}
566219b2ee8SDavid du Colombier #ifdef DEBUG
567219b2ee8SDavid du Colombier 	printf("add_el %d after %d -- ",
568219b2ee8SDavid du Colombier 	e->Seqno, (s->last)?s->last->Seqno:-1);
569219b2ee8SDavid du Colombier 	comment(stdout, e->n, 0);
570219b2ee8SDavid du Colombier 	printf("\n");
571219b2ee8SDavid du Colombier #endif
572219b2ee8SDavid du Colombier 	if (!s->frst)
573219b2ee8SDavid du Colombier 		s->frst = e;
574219b2ee8SDavid du Colombier 	else
575219b2ee8SDavid du Colombier 		s->last->nxt = e;
576219b2ee8SDavid du Colombier 	s->last = e;
577219b2ee8SDavid du Colombier }
578219b2ee8SDavid du Colombier 
5797dd7cddfSDavid du Colombier static Element *
colons(Lextok * n)580219b2ee8SDavid du Colombier colons(Lextok *n)
581219b2ee8SDavid du Colombier {
582219b2ee8SDavid du Colombier 	if (!n)
583219b2ee8SDavid du Colombier 		return ZE;
584219b2ee8SDavid du Colombier 	if (n->ntyp == ':')
585219b2ee8SDavid du Colombier 	{	Element *e = colons(n->lft);
586219b2ee8SDavid du Colombier 		set_lab(n->sym, e);
587219b2ee8SDavid du Colombier 		return e;
588219b2ee8SDavid du Colombier 	}
589219b2ee8SDavid du Colombier 	innermost = n;
590219b2ee8SDavid du Colombier 	return new_el(n);
591219b2ee8SDavid du Colombier }
592219b2ee8SDavid du Colombier 
593219b2ee8SDavid du Colombier void
add_seq(Lextok * n)594219b2ee8SDavid du Colombier add_seq(Lextok *n)
595219b2ee8SDavid du Colombier {	Element *e;
596219b2ee8SDavid du Colombier 
597219b2ee8SDavid du Colombier 	if (!n) return;
598219b2ee8SDavid du Colombier 	innermost = n;
599219b2ee8SDavid du Colombier 	e = colons(n);
600219b2ee8SDavid du Colombier 	if (innermost->ntyp != IF
601219b2ee8SDavid du Colombier 	&&  innermost->ntyp != DO
602219b2ee8SDavid du Colombier 	&&  innermost->ntyp != UNLESS)
603219b2ee8SDavid du Colombier 		add_el(e, cur_s->this);
604219b2ee8SDavid du Colombier }
605219b2ee8SDavid du Colombier 
606219b2ee8SDavid du Colombier void
set_lab(Symbol * s,Element * e)607219b2ee8SDavid du Colombier set_lab(Symbol *s, Element *e)
608219b2ee8SDavid du Colombier {	Label *l; extern Symbol *context;
60900d97012SDavid du Colombier 	int cur_uiid = is_inline();
610219b2ee8SDavid du Colombier 
611219b2ee8SDavid du Colombier 	if (!s) return;
61200d97012SDavid du Colombier 
6137dd7cddfSDavid du Colombier 	for (l = labtab; l; l = l->nxt)
61400d97012SDavid du Colombier 	{	if (strcmp(l->s->name, s->name) == 0
61500d97012SDavid du Colombier 		&&  l->c == context
616*de2caf28SDavid du Colombier 		&&  (old_scope_rules || strcmp((const char *) s->bscp, (const char *) l->s->bscp) == 0)
61700d97012SDavid du Colombier 		&&  l->uiid == cur_uiid)
6187dd7cddfSDavid du Colombier 		{	non_fatal("label %s redeclared", s->name);
6197dd7cddfSDavid du Colombier 			break;
62000d97012SDavid du Colombier 	}	}
62100d97012SDavid du Colombier 
622*de2caf28SDavid du Colombier 	if (strncmp(s->name, "accept", 6) == 0
623*de2caf28SDavid du Colombier 	&&  strncmp(s->name, "accept_all", 10) != 0)
624*de2caf28SDavid du Colombier 	{	has_accept = 1;
625*de2caf28SDavid du Colombier 	}
626*de2caf28SDavid du Colombier 
627219b2ee8SDavid du Colombier 	l = (Label *) emalloc(sizeof(Label));
628219b2ee8SDavid du Colombier 	l->s = s;
629219b2ee8SDavid du Colombier 	l->c = context;
630219b2ee8SDavid du Colombier 	l->e = e;
63100d97012SDavid du Colombier 	l->uiid = cur_uiid;
632219b2ee8SDavid du Colombier 	l->nxt = labtab;
633219b2ee8SDavid du Colombier 	labtab = l;
634219b2ee8SDavid du Colombier }
635219b2ee8SDavid du Colombier 
63600d97012SDavid du Colombier static Label *
get_labspec(Lextok * n)63700d97012SDavid du Colombier get_labspec(Lextok *n)
63800d97012SDavid du Colombier {	Symbol *s = n->sym;
63900d97012SDavid du Colombier 	Label  *l, *anymatch = (Label *) 0;
640*de2caf28SDavid du Colombier 	int ln;
64100d97012SDavid du Colombier 	/*
642*de2caf28SDavid du Colombier 	 * try to find a label with the same inline id (uiid)
643*de2caf28SDavid du Colombier 	 * but if it doesn't exist, return any other match
644*de2caf28SDavid du Colombier 	 * within the same scope
64500d97012SDavid du Colombier 	 */
64600d97012SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
647*de2caf28SDavid du Colombier 	{	if (strcmp(l->s->name, s->name) == 0	/* labelname matches */
648*de2caf28SDavid du Colombier 		&&  s->context == l->s->context)	/* same scope */
649*de2caf28SDavid du Colombier 		{
650*de2caf28SDavid du Colombier #if 0
651*de2caf28SDavid du Colombier 			if (anymatch && n->uiid == anymatch->uiid)
652*de2caf28SDavid du Colombier 			{	if (0) non_fatal("label %s re-declared", s->name);
653*de2caf28SDavid du Colombier 			}
654*de2caf28SDavid du Colombier 			if (0)
655*de2caf28SDavid du Colombier 			{	printf("Label %s uiid now::then %d :: %d bcsp %s :: %s\n",
656*de2caf28SDavid du Colombier 					s->name, n->uiid, l->uiid, s->bscp, l->s->bscp);
657*de2caf28SDavid du Colombier 				printf("get_labspec match on %s %s (bscp goto %s - label %s)\n",
658*de2caf28SDavid du Colombier 					s->name, s->context->name,  s->bscp, l->s->bscp);
659*de2caf28SDavid du Colombier 			}
660*de2caf28SDavid du Colombier #endif
661*de2caf28SDavid du Colombier 			/* same block scope */
662*de2caf28SDavid du Colombier 			if (strcmp((const char *) s->bscp, (const char *) l->s->bscp) == 0)
663*de2caf28SDavid du Colombier 			{	return l;	/* definite match */
664*de2caf28SDavid du Colombier 			}
665*de2caf28SDavid du Colombier 			/* higher block scope */
666*de2caf28SDavid du Colombier 			ln = strlen((const char *) l->s->bscp);
667*de2caf28SDavid du Colombier 			if (strncmp((const char *) s->bscp, (const char *) l->s->bscp, ln) == 0)
668*de2caf28SDavid du Colombier 			{	anymatch = l;	/* possible match */
669*de2caf28SDavid du Colombier 			} else if (!anymatch)
670*de2caf28SDavid du Colombier 			{	anymatch = l;	/* somewhere else in same context */
67100d97012SDavid du Colombier 	}	}	}
67200d97012SDavid du Colombier 
673*de2caf28SDavid du Colombier 	return anymatch; /* return best match */
67400d97012SDavid du Colombier }
67500d97012SDavid du Colombier 
676219b2ee8SDavid du Colombier Element *
get_lab(Lextok * n,int md)677219b2ee8SDavid du Colombier get_lab(Lextok *n, int md)
67800d97012SDavid du Colombier {	Label *l = get_labspec(n);
679219b2ee8SDavid du Colombier 
68000d97012SDavid du Colombier 	if (l != (Label *) 0)
68100d97012SDavid du Colombier 	{	return (l->e);
68200d97012SDavid du Colombier 	}
683312a1df1SDavid du Colombier 
68400d97012SDavid du Colombier 	if (md)
68500d97012SDavid du Colombier 	{	lineno = n->ln;
686219b2ee8SDavid du Colombier 		Fname  = n->fn;
68700d97012SDavid du Colombier 		fatal("undefined label %s", n->sym->name);
68800d97012SDavid du Colombier 	}
689219b2ee8SDavid du Colombier 	return ZE;
690219b2ee8SDavid du Colombier }
691219b2ee8SDavid du Colombier 
692219b2ee8SDavid du Colombier Symbol *
has_lab(Element * e,int special)6937dd7cddfSDavid du Colombier has_lab(Element *e, int special)
694219b2ee8SDavid du Colombier {	Label *l;
695219b2ee8SDavid du Colombier 
696219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
6977dd7cddfSDavid du Colombier 	{	if (e != l->e)
6987dd7cddfSDavid du Colombier 			continue;
6997dd7cddfSDavid du Colombier 		if (special == 0
7007dd7cddfSDavid du Colombier 		||  ((special&1) && !strncmp(l->s->name, "accept", 6))
7017dd7cddfSDavid du Colombier 		||  ((special&2) && !strncmp(l->s->name, "end", 3))
7027dd7cddfSDavid du Colombier 		||  ((special&4) && !strncmp(l->s->name, "progress", 8)))
703219b2ee8SDavid du Colombier 			return (l->s);
7047dd7cddfSDavid du Colombier 	}
705219b2ee8SDavid du Colombier 	return ZS;
706219b2ee8SDavid du Colombier }
707219b2ee8SDavid du Colombier 
7087dd7cddfSDavid du Colombier static void
mov_lab(Symbol * z,Element * e,Element * y)709219b2ee8SDavid du Colombier mov_lab(Symbol *z, Element *e, Element *y)
710219b2ee8SDavid du Colombier {	Label *l;
711219b2ee8SDavid du Colombier 
712219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
713219b2ee8SDavid du Colombier 		if (e == l->e)
714219b2ee8SDavid du Colombier 		{	l->e = y;
715219b2ee8SDavid du Colombier 			return;
716219b2ee8SDavid du Colombier 		}
717219b2ee8SDavid du Colombier 	if (e->n)
718219b2ee8SDavid du Colombier 	{	lineno = e->n->ln;
719219b2ee8SDavid du Colombier 		Fname  = e->n->fn;
720219b2ee8SDavid du Colombier 	}
721219b2ee8SDavid du Colombier 	fatal("cannot happen - mov_lab %s", z->name);
722219b2ee8SDavid du Colombier }
723219b2ee8SDavid du Colombier 
724219b2ee8SDavid du Colombier void
fix_dest(Symbol * c,Symbol * a)725312a1df1SDavid du Colombier fix_dest(Symbol *c, Symbol *a)		/* c:label name, a:proctype name */
7267dd7cddfSDavid du Colombier {	Label *l; extern Symbol *context;
727219b2ee8SDavid du Colombier 
728312a1df1SDavid du Colombier #if 0
729312a1df1SDavid du Colombier 	printf("ref to label '%s' in proctype '%s', search:\n",
730312a1df1SDavid du Colombier 		c->name, a->name);
731312a1df1SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
732312a1df1SDavid du Colombier 		printf("	%s in	%s\n", l->s->name, l->c->name);
733312a1df1SDavid du Colombier #endif
734312a1df1SDavid du Colombier 
735219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
736219b2ee8SDavid du Colombier 	{	if (strcmp(c->name, l->s->name) == 0
737312a1df1SDavid du Colombier 		&&  strcmp(a->name, l->c->name) == 0)	/* ? */
738219b2ee8SDavid du Colombier 			break;
739219b2ee8SDavid du Colombier 	}
740219b2ee8SDavid du Colombier 	if (!l)
7417dd7cddfSDavid du Colombier 	{	printf("spin: label '%s' (proctype %s)\n", c->name, a->name);
7427dd7cddfSDavid du Colombier 		non_fatal("unknown label '%s'", c->name);
7437dd7cddfSDavid du Colombier 		if (context == a)
7447dd7cddfSDavid du Colombier 		printf("spin: cannot remote ref a label inside the same proctype\n");
745219b2ee8SDavid du Colombier 		return;
746219b2ee8SDavid du Colombier 	}
747219b2ee8SDavid du Colombier 	if (!l->e || !l->e->n)
748219b2ee8SDavid du Colombier 		fatal("fix_dest error (%s)", c->name);
749219b2ee8SDavid du Colombier 	if (l->e->n->ntyp == GOTO)
750219b2ee8SDavid du Colombier 	{	Element	*y = (Element *) emalloc(sizeof(Element));
751219b2ee8SDavid du Colombier 		int	keep_ln = l->e->n->ln;
752219b2ee8SDavid du Colombier 		Symbol	*keep_fn = l->e->n->fn;
753219b2ee8SDavid du Colombier 
754219b2ee8SDavid du Colombier 		/* insert skip - or target is optimized away */
755219b2ee8SDavid du Colombier 		y->n = l->e->n;		  /* copy of the goto   */
756219b2ee8SDavid du Colombier 		y->seqno = find_maxel(a); /* unique seqno within proc */
757219b2ee8SDavid du Colombier 		y->nxt = l->e->nxt;
758219b2ee8SDavid du Colombier 		y->Seqno = Unique++; y->Nxt = Al_El; Al_El = y;
759219b2ee8SDavid du Colombier 
760219b2ee8SDavid du Colombier 		/* turn the original element+seqno into a skip */
761219b2ee8SDavid du Colombier 		l->e->n = nn(ZN, 'c', nn(ZN, CONST, ZN, ZN), ZN);
762219b2ee8SDavid du Colombier 		l->e->n->ln = l->e->n->lft->ln = keep_ln;
763219b2ee8SDavid du Colombier 		l->e->n->fn = l->e->n->lft->fn = keep_fn;
764219b2ee8SDavid du Colombier 		l->e->n->lft->val = 1;
765219b2ee8SDavid du Colombier 		l->e->nxt = y;		/* append the goto  */
766219b2ee8SDavid du Colombier 	}
7677dd7cddfSDavid du Colombier 	l->e->status |= CHECK2;	/* treat as if global */
768312a1df1SDavid du Colombier 	if (l->e->status & (ATOM | L_ATOM | D_ATOM))
769*de2caf28SDavid du Colombier 	{	printf("spin: %s:%d, warning, reference to label ",
770*de2caf28SDavid du Colombier 			Fname->name, lineno);
771*de2caf28SDavid du Colombier 		printf("from inside atomic or d_step (%s)\n", c->name);
772312a1df1SDavid du Colombier 	}
773219b2ee8SDavid du Colombier }
774219b2ee8SDavid du Colombier 
775219b2ee8SDavid du Colombier int
find_lab(Symbol * s,Symbol * c,int markit)7767dd7cddfSDavid du Colombier find_lab(Symbol *s, Symbol *c, int markit)
777*de2caf28SDavid du Colombier {	Label *l, *pm = (Label *) 0, *apm = (Label *) 0;
778*de2caf28SDavid du Colombier 	int ln;
779219b2ee8SDavid du Colombier 
780*de2caf28SDavid du Colombier 	/* generally called for remote references in never claims */
781219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
782*de2caf28SDavid du Colombier 	{
783*de2caf28SDavid du Colombier 		if (strcmp(s->name, l->s->name) == 0
784219b2ee8SDavid du Colombier 		&&  strcmp(c->name, l->c->name) == 0)
785*de2caf28SDavid du Colombier 		{	ln = strlen((const char *) l->s->bscp);
786*de2caf28SDavid du Colombier 			if (0)
787*de2caf28SDavid du Colombier 			{	printf("want '%s' in context '%s', scope ref '%s' - label '%s'\n",
788*de2caf28SDavid du Colombier 					s->name, c->name, s->bscp, l->s->bscp);
789*de2caf28SDavid du Colombier 			}
790*de2caf28SDavid du Colombier 			/* same or higher block scope */
791*de2caf28SDavid du Colombier 			if (strcmp((const char *)  s->bscp, (const char *) l->s->bscp) == 0)
792*de2caf28SDavid du Colombier 			{	pm = l;	/* definite match */
793*de2caf28SDavid du Colombier 				break;
794*de2caf28SDavid du Colombier 			}
795*de2caf28SDavid du Colombier 			if (strncmp((const char *) s->bscp, (const char *) l->s->bscp, ln) == 0)
796*de2caf28SDavid du Colombier 			{	pm = l;	/* possible match */
797*de2caf28SDavid du Colombier 			} else
798*de2caf28SDavid du Colombier 			{	apm = l;	/* remote */
799*de2caf28SDavid du Colombier 	}	}	}
800*de2caf28SDavid du Colombier 
801*de2caf28SDavid du Colombier 	if (pm)
802*de2caf28SDavid du Colombier 	{	pm->visible |= markit;
803*de2caf28SDavid du Colombier 		return pm->e->seqno;
804*de2caf28SDavid du Colombier 	}
805*de2caf28SDavid du Colombier 	if (apm)
806*de2caf28SDavid du Colombier 	{	apm->visible |= markit;
807*de2caf28SDavid du Colombier 		return apm->e->seqno;
808*de2caf28SDavid du Colombier 	} /* else printf("Not Found\n"); */
809219b2ee8SDavid du Colombier 	return 0;
810219b2ee8SDavid du Colombier }
811219b2ee8SDavid du Colombier 
812219b2ee8SDavid du Colombier void
pushbreak(void)813219b2ee8SDavid du Colombier pushbreak(void)
814219b2ee8SDavid du Colombier {	Lbreak *r = (Lbreak *) emalloc(sizeof(Lbreak));
815219b2ee8SDavid du Colombier 	Symbol *l;
8167dd7cddfSDavid du Colombier 	char buf[64];
817219b2ee8SDavid du Colombier 
818219b2ee8SDavid du Colombier 	sprintf(buf, ":b%d", break_id++);
819219b2ee8SDavid du Colombier 	l = lookup(buf);
820219b2ee8SDavid du Colombier 	r->l = l;
821219b2ee8SDavid du Colombier 	r->nxt = breakstack;
822219b2ee8SDavid du Colombier 	breakstack = r;
823219b2ee8SDavid du Colombier }
824219b2ee8SDavid du Colombier 
825219b2ee8SDavid du Colombier Symbol *
break_dest(void)826219b2ee8SDavid du Colombier break_dest(void)
827219b2ee8SDavid du Colombier {
828219b2ee8SDavid du Colombier 	if (!breakstack)
829219b2ee8SDavid du Colombier 		fatal("misplaced break statement", (char *)0);
830219b2ee8SDavid du Colombier 	return breakstack->l;
831219b2ee8SDavid du Colombier }
832219b2ee8SDavid du Colombier 
833219b2ee8SDavid du Colombier void
make_atomic(Sequence * s,int added)834219b2ee8SDavid du Colombier make_atomic(Sequence *s, int added)
835312a1df1SDavid du Colombier {	Element *f;
836312a1df1SDavid du Colombier 
837219b2ee8SDavid du Colombier 	walk_atomic(s->frst, s->last, added);
838312a1df1SDavid du Colombier 
839312a1df1SDavid du Colombier 	f = s->last;
840312a1df1SDavid du Colombier 	switch (f->n->ntyp) {	/* is last step basic stmnt or sequence ? */
841312a1df1SDavid du Colombier 	case NON_ATOMIC:
842312a1df1SDavid du Colombier 	case ATOMIC:
843312a1df1SDavid du Colombier 		/* redo and search for the last step of that sequence */
844312a1df1SDavid du Colombier 		make_atomic(f->n->sl->this, added);
845312a1df1SDavid du Colombier 		break;
846312a1df1SDavid du Colombier 
847312a1df1SDavid du Colombier 	case UNLESS:
848312a1df1SDavid du Colombier 		/* escapes are folded into main sequence */
849312a1df1SDavid du Colombier 		make_atomic(f->sub->this, added);
850312a1df1SDavid du Colombier 		break;
851312a1df1SDavid du Colombier 
852312a1df1SDavid du Colombier 	default:
853312a1df1SDavid du Colombier 		f->status &= ~ATOM;
854312a1df1SDavid du Colombier 		f->status |= L_ATOM;
855312a1df1SDavid du Colombier 		break;
856312a1df1SDavid du Colombier 	}
857219b2ee8SDavid du Colombier }
858219b2ee8SDavid du Colombier 
85900d97012SDavid du Colombier #if 0
86000d97012SDavid du Colombier static int depth = 0;
86100d97012SDavid du Colombier void dump_sym(Symbol *, char *);
86200d97012SDavid du Colombier 
86300d97012SDavid du Colombier void
86400d97012SDavid du Colombier dump_lex(Lextok *t, char *s)
86500d97012SDavid du Colombier {	int i;
86600d97012SDavid du Colombier 
86700d97012SDavid du Colombier 	depth++;
86800d97012SDavid du Colombier 	printf(s);
86900d97012SDavid du Colombier 	for (i = 0; i < depth; i++)
87000d97012SDavid du Colombier 		printf("\t");
87100d97012SDavid du Colombier 	explain(t->ntyp);
87200d97012SDavid du Colombier 	if (t->ntyp == NAME) printf(" %s ", t->sym->name);
87300d97012SDavid du Colombier 	if (t->ntyp == CONST) printf(" %d ", t->val);
87400d97012SDavid du Colombier 	if (t->ntyp == STRUCT)
87500d97012SDavid du Colombier 	{	dump_sym(t->sym, "\n:Z:");
87600d97012SDavid du Colombier 	}
87700d97012SDavid du Colombier 	if (t->lft)
87800d97012SDavid du Colombier 	{	dump_lex(t->lft, "\nL");
87900d97012SDavid du Colombier 	}
88000d97012SDavid du Colombier 	if (t->rgt)
88100d97012SDavid du Colombier 	{	dump_lex(t->rgt, "\nR");
88200d97012SDavid du Colombier 	}
88300d97012SDavid du Colombier 	depth--;
88400d97012SDavid du Colombier }
88500d97012SDavid du Colombier void
88600d97012SDavid du Colombier dump_sym(Symbol *z, char *s)
88700d97012SDavid du Colombier {	int i;
88800d97012SDavid du Colombier 	char txt[64];
88900d97012SDavid du Colombier 	depth++;
89000d97012SDavid du Colombier 	printf(s);
89100d97012SDavid du Colombier 	for (i = 0; i < depth; i++)
89200d97012SDavid du Colombier 		printf("\t");
89300d97012SDavid du Colombier 
89400d97012SDavid du Colombier 	if (z->type == CHAN)
89500d97012SDavid du Colombier 	{	if (z->ini && z->ini->rgt && z->ini->rgt->sym)
896*de2caf28SDavid du Colombier 		{	/* dump_sym(z->ini->rgt->sym, "\n:I:"); -- could also be longer list */
89700d97012SDavid du Colombier 			if (z->ini->rgt->rgt
89800d97012SDavid du Colombier 			|| !z->ini->rgt->sym)
89900d97012SDavid du Colombier 			fatal("chan %s in for should have only one field (a typedef)", z->name);
90000d97012SDavid du Colombier 			printf(" -- %s %p -- ", z->ini->rgt->sym->name, z->ini->rgt->sym);
90100d97012SDavid du Colombier 		}
90200d97012SDavid du Colombier 	} else if (z->type == STRUCT)
90300d97012SDavid du Colombier 	{	if (z->Snm)
90400d97012SDavid du Colombier 			printf(" == %s %p == ", z->Snm->name, z->Snm);
90500d97012SDavid du Colombier 		else
90600d97012SDavid du Colombier 		{	if (z->Slst)
90700d97012SDavid du Colombier 				dump_lex(z->Slst, "\n:X:");
90800d97012SDavid du Colombier 			if (z->ini)
90900d97012SDavid du Colombier 				dump_lex(z->ini, "\n:I:");
91000d97012SDavid du Colombier 		}
91100d97012SDavid du Colombier 	}
91200d97012SDavid du Colombier 	depth--;
91300d97012SDavid du Colombier 
91400d97012SDavid du Colombier }
91500d97012SDavid du Colombier #endif
91600d97012SDavid du Colombier 
91700d97012SDavid du Colombier int
match_struct(Symbol * s,Symbol * t)91800d97012SDavid du Colombier match_struct(Symbol *s, Symbol *t)
91900d97012SDavid du Colombier {
92000d97012SDavid du Colombier 	if (!t
92100d97012SDavid du Colombier 	||  !t->ini
92200d97012SDavid du Colombier 	||  !t->ini->rgt
92300d97012SDavid du Colombier 	||  !t->ini->rgt->sym
92400d97012SDavid du Colombier 	||   t->ini->rgt->rgt)
925*de2caf28SDavid du Colombier 	{	fatal("chan %s in for should have only one field (a typedef)", t?t->name:"--");
92600d97012SDavid du Colombier 	}
92700d97012SDavid du Colombier 	/* we already know that s is a STRUCT */
92800d97012SDavid du Colombier 	if (0)
929*de2caf28SDavid du Colombier 	{	printf("index type %s %p ==\n", s->Snm->name, (void *) s->Snm);
930*de2caf28SDavid du Colombier 		printf("chan type  %s %p --\n\n", t->ini->rgt->sym->name, (void *) t->ini->rgt->sym);
93100d97012SDavid du Colombier 	}
93200d97012SDavid du Colombier 
93300d97012SDavid du Colombier 	return (s->Snm == t->ini->rgt->sym);
93400d97012SDavid du Colombier }
93500d97012SDavid du Colombier 
93600d97012SDavid du Colombier void
valid_name(Lextok * a3,Lextok * a5,Lextok * a8,char * tp)93700d97012SDavid du Colombier valid_name(Lextok *a3, Lextok *a5, Lextok *a8, char *tp)
93800d97012SDavid du Colombier {
93900d97012SDavid du Colombier 	if (a3->ntyp != NAME)
94000d97012SDavid du Colombier 	{	fatal("%s ( .name : from .. to ) { ... }", tp);
94100d97012SDavid du Colombier 	}
94200d97012SDavid du Colombier 	if (a3->sym->type == CHAN
94300d97012SDavid du Colombier 	||  a3->sym->type == STRUCT
94400d97012SDavid du Colombier 	||  a3->sym->isarray != 0)
94500d97012SDavid du Colombier 	{	fatal("bad index in for-construct %s", a3->sym->name);
94600d97012SDavid du Colombier 	}
94700d97012SDavid du Colombier 	if (a5->ntyp == CONST && a8->ntyp == CONST && a5->val > a8->val)
94800d97012SDavid du Colombier 	{	non_fatal("start value for %s exceeds end-value", a3->sym->name);
94900d97012SDavid du Colombier 	}
95000d97012SDavid du Colombier }
95100d97012SDavid du Colombier 
95200d97012SDavid du Colombier void
for_setup(Lextok * a3,Lextok * a5,Lextok * a8)95300d97012SDavid du Colombier for_setup(Lextok *a3, Lextok *a5, Lextok *a8)
95400d97012SDavid du Colombier {	/* for ( a3 : a5 .. a8 ) */
95500d97012SDavid du Colombier 
95600d97012SDavid du Colombier 	valid_name(a3, a5, a8, "for");
95700d97012SDavid du Colombier 	/* a5->ntyp = a8->ntyp = CONST; */
95800d97012SDavid du Colombier 	add_seq(nn(a3, ASGN, a3, a5));	/* start value */
95900d97012SDavid du Colombier 	open_seq(0);
96000d97012SDavid du Colombier 	add_seq(nn(ZN, 'c', nn(a3, LE, a3, a8), ZN));	/* condition */
96100d97012SDavid du Colombier }
96200d97012SDavid du Colombier 
96300d97012SDavid du Colombier Lextok *
for_index(Lextok * a3,Lextok * a5)96400d97012SDavid du Colombier for_index(Lextok *a3, Lextok *a5)
96500d97012SDavid du Colombier {	Lextok *z0, *z1, *z2, *z3;
96600d97012SDavid du Colombier 	Symbol *tmp_cnt;
967*de2caf28SDavid du Colombier 	char tmp_nm[MAXSCOPESZ+16];
96800d97012SDavid du Colombier 	/* for ( a3 in a5 ) { ... } */
96900d97012SDavid du Colombier 
97000d97012SDavid du Colombier 	if (a3->ntyp != NAME)
97100d97012SDavid du Colombier 	{	fatal("for ( .name in name ) { ... }", (char *) 0);
97200d97012SDavid du Colombier 	}
97300d97012SDavid du Colombier 
97400d97012SDavid du Colombier 	if (a5->ntyp != NAME)
97500d97012SDavid du Colombier 	{	fatal("for ( %s in .name ) { ... }", a3->sym->name);
97600d97012SDavid du Colombier 	}
97700d97012SDavid du Colombier 
97800d97012SDavid du Colombier 	if (a3->sym->type == STRUCT)
97900d97012SDavid du Colombier 	{	if (a5->sym->type != CHAN)
98000d97012SDavid du Colombier 		{	fatal("for ( %s in .channel_name ) { ... }",
98100d97012SDavid du Colombier 				a3->sym->name);
98200d97012SDavid du Colombier 		}
98300d97012SDavid du Colombier 		z0 = a5->sym->ini;
98400d97012SDavid du Colombier 		if (!z0
98500d97012SDavid du Colombier 		|| z0->val <= 0
98600d97012SDavid du Colombier 		|| z0->rgt->ntyp != STRUCT
98700d97012SDavid du Colombier 		|| z0->rgt->rgt != NULL)
98800d97012SDavid du Colombier 		{	fatal("bad channel type %s in for", a5->sym->name);
98900d97012SDavid du Colombier 		}
99000d97012SDavid du Colombier 
99100d97012SDavid du Colombier 		if (!match_struct(a3->sym, a5->sym))
99200d97012SDavid du Colombier 		{	fatal("type of %s does not match chan", a3->sym->name);
99300d97012SDavid du Colombier 		}
99400d97012SDavid du Colombier 
99500d97012SDavid du Colombier 		z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0;
99600d97012SDavid du Colombier 		z2 = nn(a5, LEN, a5, ZN);
99700d97012SDavid du Colombier 
99800d97012SDavid du Colombier 		sprintf(tmp_nm, "_f0r_t3mp%s", CurScope); /* make sure it's unique */
99900d97012SDavid du Colombier 		tmp_cnt = lookup(tmp_nm);
100000d97012SDavid du Colombier 		if (z0->val > 255)			/* check nr of slots, i.e. max length */
100100d97012SDavid du Colombier 		{	tmp_cnt->type = SHORT;	/* should be rare */
100200d97012SDavid du Colombier 		} else
100300d97012SDavid du Colombier 		{	tmp_cnt->type = BYTE;
100400d97012SDavid du Colombier 		}
100500d97012SDavid du Colombier 		z3 = nn(ZN, NAME, ZN, ZN);
100600d97012SDavid du Colombier 		z3->sym = tmp_cnt;
100700d97012SDavid du Colombier 
100800d97012SDavid du Colombier 		add_seq(nn(z3, ASGN, z3, z1));	/* start value 0 */
100900d97012SDavid du Colombier 
101000d97012SDavid du Colombier 		open_seq(0);
101100d97012SDavid du Colombier 
101200d97012SDavid du Colombier 		add_seq(nn(ZN, 'c', nn(z3, LT, z3, z2), ZN));	/* condition */
101300d97012SDavid du Colombier 
101400d97012SDavid du Colombier 		/* retrieve  message from the right slot -- for now: rotate contents */
101500d97012SDavid du Colombier 		in_for = 0;
101600d97012SDavid du Colombier 		add_seq(nn(a5, 'r', a5, expand(a3, 1)));	/* receive */
101700d97012SDavid du Colombier 		add_seq(nn(a5, 's', a5, expand(a3, 1)));	/* put back in to rotate */
101800d97012SDavid du Colombier 		in_for = 1;
101900d97012SDavid du Colombier 		return z3;
102000d97012SDavid du Colombier 	} else
1021*de2caf28SDavid du Colombier 	{	Lextok *leaf = a5;
1022*de2caf28SDavid du Colombier 		if (leaf->sym->type == STRUCT)	// find leaf node, which should be an array
1023*de2caf28SDavid du Colombier 		{	while (leaf->rgt
1024*de2caf28SDavid du Colombier 			&&     leaf->rgt->ntyp == '.')
1025*de2caf28SDavid du Colombier 			{	leaf = leaf->rgt;
1026*de2caf28SDavid du Colombier 			}
1027*de2caf28SDavid du Colombier 			leaf = leaf->lft;
1028*de2caf28SDavid du Colombier 			// printf("%s %d\n", leaf->sym->name, leaf->sym->isarray);
1029*de2caf28SDavid du Colombier 		}
1030*de2caf28SDavid du Colombier 
1031*de2caf28SDavid du Colombier 		if (leaf->sym->isarray == 0
1032*de2caf28SDavid du Colombier 		||  leaf->sym->nel <= 0)
1033*de2caf28SDavid du Colombier 		{	fatal("bad arrayname %s", leaf->sym->name);
103400d97012SDavid du Colombier 		}
103500d97012SDavid du Colombier 		z1 = nn(ZN, CONST, ZN, ZN); z1->val = 0;
1036*de2caf28SDavid du Colombier 		z2 = nn(ZN, CONST, ZN, ZN); z2->val = leaf->sym->nel - 1;
103700d97012SDavid du Colombier 		for_setup(a3, z1, z2);
103800d97012SDavid du Colombier 		return a3;
103900d97012SDavid du Colombier 	}
104000d97012SDavid du Colombier }
104100d97012SDavid du Colombier 
104200d97012SDavid du Colombier Lextok *
for_body(Lextok * a3,int with_else)104300d97012SDavid du Colombier for_body(Lextok *a3, int with_else)
104400d97012SDavid du Colombier {	Lextok *t1, *t2, *t0, *rv;
104500d97012SDavid du Colombier 
104600d97012SDavid du Colombier 	rv = nn(ZN, CONST, ZN, ZN); rv->val = 1;
104700d97012SDavid du Colombier 	rv = nn(ZN,  '+', a3, rv);
104800d97012SDavid du Colombier 	rv = nn(a3, ASGN, a3, rv);
104900d97012SDavid du Colombier 	add_seq(rv);	/* initial increment */
105000d97012SDavid du Colombier 
105100d97012SDavid du Colombier 	/* completed loop body, main sequence */
105200d97012SDavid du Colombier 	t1 = nn(ZN, 0, ZN, ZN);
105300d97012SDavid du Colombier 	t1->sq = close_seq(8);
105400d97012SDavid du Colombier 
105500d97012SDavid du Colombier 	open_seq(0);		/* add else -> break sequence */
105600d97012SDavid du Colombier 	if (with_else)
105700d97012SDavid du Colombier 	{	add_seq(nn(ZN, ELSE, ZN, ZN));
105800d97012SDavid du Colombier 	}
105900d97012SDavid du Colombier 	t2 = nn(ZN, GOTO, ZN, ZN);
106000d97012SDavid du Colombier 	t2->sym = break_dest();
106100d97012SDavid du Colombier 	add_seq(t2);
106200d97012SDavid du Colombier 	t2 = nn(ZN, 0, ZN, ZN);
106300d97012SDavid du Colombier 	t2->sq = close_seq(9);
106400d97012SDavid du Colombier 
106500d97012SDavid du Colombier 	t0 = nn(ZN, 0, ZN, ZN);
106600d97012SDavid du Colombier 	t0->sl = seqlist(t2->sq, seqlist(t1->sq, 0));
106700d97012SDavid du Colombier 
106800d97012SDavid du Colombier 	rv = nn(ZN, DO, ZN, ZN);
106900d97012SDavid du Colombier 	rv->sl = t0->sl;
1070*de2caf28SDavid du Colombier 
107100d97012SDavid du Colombier 	return rv;
107200d97012SDavid du Colombier }
107300d97012SDavid du Colombier 
107400d97012SDavid du Colombier Lextok *
sel_index(Lextok * a3,Lextok * a5,Lextok * a7)107500d97012SDavid du Colombier sel_index(Lextok *a3, Lextok *a5, Lextok *a7)
107600d97012SDavid du Colombier {	/* select ( a3 : a5 .. a7 ) */
107700d97012SDavid du Colombier 
107800d97012SDavid du Colombier 	valid_name(a3, a5, a7, "select");
107900d97012SDavid du Colombier 	/* a5->ntyp = a7->ntyp = CONST; */
108000d97012SDavid du Colombier 
108100d97012SDavid du Colombier 	add_seq(nn(a3, ASGN, a3, a5));	/* start value */
108200d97012SDavid du Colombier 	open_seq(0);
108300d97012SDavid du Colombier 	add_seq(nn(ZN, 'c', nn(a3, LT, a3, a7), ZN));	/* condition */
108400d97012SDavid du Colombier 
1085*de2caf28SDavid du Colombier 	pushbreak(); /* new 6.2.1 */
108600d97012SDavid du Colombier 	return for_body(a3, 0);	/* no else, just a non-deterministic break */
108700d97012SDavid du Colombier }
108800d97012SDavid du Colombier 
10897dd7cddfSDavid du Colombier static void
walk_atomic(Element * a,Element * b,int added)1090219b2ee8SDavid du Colombier walk_atomic(Element *a, Element *b, int added)
10917dd7cddfSDavid du Colombier {	Element *f; Symbol *ofn; int oln;
1092219b2ee8SDavid du Colombier 	SeqList *h;
1093219b2ee8SDavid du Colombier 
10947dd7cddfSDavid du Colombier 	ofn = Fname;
10957dd7cddfSDavid du Colombier 	oln = lineno;
1096219b2ee8SDavid du Colombier 	for (f = a; ; f = f->nxt)
1097219b2ee8SDavid du Colombier 	{	f->status |= (ATOM|added);
1098219b2ee8SDavid du Colombier 		switch (f->n->ntyp) {
1099219b2ee8SDavid du Colombier 		case ATOMIC:
11007dd7cddfSDavid du Colombier 			if (verbose&32)
1101*de2caf28SDavid du Colombier 			  printf("spin: %s:%d, warning, atomic inside %s (ignored)\n",
110200d97012SDavid du Colombier 			  f->n->fn->name, f->n->ln, (added)?"d_step":"atomic");
11037dd7cddfSDavid du Colombier 			goto mknonat;
1104219b2ee8SDavid du Colombier 		case D_STEP:
11057dd7cddfSDavid du Colombier 			if (!(verbose&32))
11067dd7cddfSDavid du Colombier 			{	if (added) goto mknonat;
11077dd7cddfSDavid du Colombier 				break;
11087dd7cddfSDavid du Colombier 			}
1109*de2caf28SDavid du Colombier 			printf("spin: %s:%d, warning, d_step inside ",
111000d97012SDavid du Colombier 			 f->n->fn->name, f->n->ln);
11117dd7cddfSDavid du Colombier 			if (added)
11127dd7cddfSDavid du Colombier 			{	printf("d_step (ignored)\n");
11137dd7cddfSDavid du Colombier 				goto mknonat;
11147dd7cddfSDavid du Colombier 			}
11157dd7cddfSDavid du Colombier 			printf("atomic\n");
1116219b2ee8SDavid du Colombier 			break;
1117219b2ee8SDavid du Colombier 		case NON_ATOMIC:
11187dd7cddfSDavid du Colombier mknonat:		f->n->ntyp = NON_ATOMIC; /* can jump here */
1119219b2ee8SDavid du Colombier 			h = f->n->sl;
1120219b2ee8SDavid du Colombier 			walk_atomic(h->this->frst, h->this->last, added);
1121219b2ee8SDavid du Colombier 			break;
1122312a1df1SDavid du Colombier 		case UNLESS:
1123312a1df1SDavid du Colombier 			if (added)
112400d97012SDavid du Colombier 			{ printf("spin: error, %s:%d, unless in d_step (ignored)\n",
112500d97012SDavid du Colombier 			 	 f->n->fn->name, f->n->ln);
1126312a1df1SDavid du Colombier 			}
1127219b2ee8SDavid du Colombier 		}
1128219b2ee8SDavid du Colombier 		for (h = f->sub; h; h = h->nxt)
1129219b2ee8SDavid du Colombier 			walk_atomic(h->this->frst, h->this->last, added);
1130219b2ee8SDavid du Colombier 		if (f == b)
1131219b2ee8SDavid du Colombier 			break;
1132219b2ee8SDavid du Colombier 	}
11337dd7cddfSDavid du Colombier 	Fname = ofn;
11347dd7cddfSDavid du Colombier 	lineno = oln;
1135219b2ee8SDavid du Colombier }
1136219b2ee8SDavid du Colombier 
1137219b2ee8SDavid du Colombier void
dumplabels(void)1138219b2ee8SDavid du Colombier dumplabels(void)
1139219b2ee8SDavid du Colombier {	Label *l;
1140219b2ee8SDavid du Colombier 
1141219b2ee8SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
1142219b2ee8SDavid du Colombier 		if (l->c != 0 && l->s->name[0] != ':')
114300d97012SDavid du Colombier 		{	printf("label	%s	%d	",
114400d97012SDavid du Colombier 				l->s->name, l->e->seqno);
114500d97012SDavid du Colombier 			if (l->uiid == 0)
1146*de2caf28SDavid du Colombier 				printf("<%s>", l->c->name);
114700d97012SDavid du Colombier 			else
1148*de2caf28SDavid du Colombier 				printf("<%s i%d>", l->c->name, l->uiid);
1149*de2caf28SDavid du Colombier 			if (!old_scope_rules)
1150*de2caf28SDavid du Colombier 			{	printf("\t{scope %s}", l->s->bscp);
1151*de2caf28SDavid du Colombier 			}
1152*de2caf28SDavid du Colombier 			printf("\n");
115300d97012SDavid du Colombier 		}
1154219b2ee8SDavid du Colombier }
1155