xref: /plan9/sys/src/cmd/spin/sym.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
1219b2ee8SDavid du Colombier /***** spin: sym.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"
14219b2ee8SDavid du Colombier 
15219b2ee8SDavid du Colombier extern Symbol	*Fname, *owner;
167dd7cddfSDavid du Colombier extern int	lineno, depth, verbose, NamesNotAdded, deadvar;
17*00d97012SDavid du Colombier extern int	has_hidden, m_loss, old_scope_rules;
187dd7cddfSDavid du Colombier extern short	has_xu;
19*00d97012SDavid du Colombier extern char	CurScope[MAXSCOPESZ];
20219b2ee8SDavid du Colombier 
21219b2ee8SDavid du Colombier Symbol	*context = ZS;
227dd7cddfSDavid du Colombier Ordered	*all_names = (Ordered *)0;
23219b2ee8SDavid du Colombier int	Nid = 0;
24219b2ee8SDavid du Colombier 
25*00d97012SDavid du Colombier Lextok *Mtype = (Lextok *) 0;
26*00d97012SDavid du Colombier 
277dd7cddfSDavid du Colombier static Ordered	*last_name = (Ordered *)0;
287dd7cddfSDavid du Colombier static Symbol	*symtab[Nhash+1];
29*00d97012SDavid du Colombier static Lextok *runstmnts = ZN;
307dd7cddfSDavid du Colombier 
317dd7cddfSDavid du Colombier static int
samename(Symbol * a,Symbol * b)32219b2ee8SDavid du Colombier samename(Symbol *a, Symbol *b)
33219b2ee8SDavid du Colombier {
34219b2ee8SDavid du Colombier 	if (!a && !b) return 1;
35219b2ee8SDavid du Colombier 	if (!a || !b) return 0;
36219b2ee8SDavid du Colombier 	return !strcmp(a->name, b->name);
37219b2ee8SDavid du Colombier }
38219b2ee8SDavid du Colombier 
39219b2ee8SDavid du Colombier int
hash(char * s)40219b2ee8SDavid du Colombier hash(char *s)
41219b2ee8SDavid du Colombier {	int h=0;
42219b2ee8SDavid du Colombier 
43219b2ee8SDavid du Colombier 	while (*s)
44219b2ee8SDavid du Colombier 	{	h += *s++;
45219b2ee8SDavid du Colombier 		h <<= 1;
46219b2ee8SDavid du Colombier 		if (h&(Nhash+1))
47219b2ee8SDavid du Colombier 			h |= 1;
48219b2ee8SDavid du Colombier 	}
49219b2ee8SDavid du Colombier 	return h&Nhash;
50219b2ee8SDavid du Colombier }
51219b2ee8SDavid du Colombier 
52*00d97012SDavid du Colombier void
disambiguate(void)53*00d97012SDavid du Colombier disambiguate(void)
54*00d97012SDavid du Colombier {	Ordered *walk;
55*00d97012SDavid du Colombier 	Symbol *sp;
56*00d97012SDavid du Colombier 
57*00d97012SDavid du Colombier 	if (old_scope_rules)
58*00d97012SDavid du Colombier 		return;
59*00d97012SDavid du Colombier 
60*00d97012SDavid du Colombier 	/* if the same name appears in two different scopes,
61*00d97012SDavid du Colombier 	   prepend the scope_prefix to the names */
62*00d97012SDavid du Colombier 
63*00d97012SDavid du Colombier 	for (walk = all_names; walk; walk = walk->next)
64*00d97012SDavid du Colombier 	{	sp = walk->entry;
65*00d97012SDavid du Colombier 		if (sp->type != 0
66*00d97012SDavid du Colombier 		&&  sp->type != LABEL
67*00d97012SDavid du Colombier 		&&  strlen((const char *)sp->bscp) > 1)
68*00d97012SDavid du Colombier 		{	char *n = (char *) emalloc(strlen((const char *)sp->name)
69*00d97012SDavid du Colombier 				+ strlen((const char *)sp->bscp) + 1);
70*00d97012SDavid du Colombier 			sprintf(n, "%s%s", sp->bscp, sp->name);
71*00d97012SDavid du Colombier 			sp->name = n;	/* discord the old memory */
72*00d97012SDavid du Colombier 	}	}
73*00d97012SDavid du Colombier }
74*00d97012SDavid du Colombier 
75219b2ee8SDavid du Colombier Symbol *
lookup(char * s)76219b2ee8SDavid du Colombier lookup(char *s)
777dd7cddfSDavid du Colombier {	Symbol *sp; Ordered *no;
78219b2ee8SDavid du Colombier 	int h = hash(s);
79219b2ee8SDavid du Colombier 
80*00d97012SDavid du Colombier 	if (old_scope_rules)
81*00d97012SDavid du Colombier 	{	/* same scope - global refering to global or local to local */
82219b2ee8SDavid du Colombier 		for (sp = symtab[h]; sp; sp = sp->next)
83*00d97012SDavid du Colombier 		{	if (strcmp(sp->name, s) == 0
84219b2ee8SDavid du Colombier 			&&  samename(sp->context, context)
85219b2ee8SDavid du Colombier 			&&  samename(sp->owner, owner))
86*00d97012SDavid du Colombier 			{	return sp;		/* found */
87*00d97012SDavid du Colombier 		}	}
88*00d97012SDavid du Colombier 	} else
89*00d97012SDavid du Colombier 	{	/* added 6.0.0: more traditional, scope rule */
90219b2ee8SDavid du Colombier 		for (sp = symtab[h]; sp; sp = sp->next)
91*00d97012SDavid du Colombier 		{	if (strcmp(sp->name, s) == 0
92*00d97012SDavid du Colombier 			&&  samename(sp->context, context)
93*00d97012SDavid du Colombier 			&&  (strcmp((const char *)sp->bscp, CurScope) == 0
94*00d97012SDavid du Colombier 			||   strncmp((const char *)sp->bscp, CurScope, strlen((const char *)sp->bscp)) == 0)
95*00d97012SDavid du Colombier 			&&  samename(sp->owner, owner))
96*00d97012SDavid du Colombier 			{
97*00d97012SDavid du Colombier 				if (!samename(sp->owner, owner))
98*00d97012SDavid du Colombier 				{	printf("spin: different container %s\n", sp->name);
99*00d97012SDavid du Colombier 					printf("	old: %s\n", sp->owner?sp->owner->name:"--");
100*00d97012SDavid du Colombier 					printf("	new: %s\n", owner?owner->name:"--");
101*00d97012SDavid du Colombier 				/*	alldone(1);	*/
102*00d97012SDavid du Colombier 				}
103*00d97012SDavid du Colombier 				return sp;		/* found */
104*00d97012SDavid du Colombier 	}	}	}
105*00d97012SDavid du Colombier 
106*00d97012SDavid du Colombier 	if (context)				/* in proctype, refers to global */
107*00d97012SDavid du Colombier 	for (sp = symtab[h]; sp; sp = sp->next)
108*00d97012SDavid du Colombier 	{	if (strcmp(sp->name, s) == 0
109219b2ee8SDavid du Colombier 		&& !sp->context
110219b2ee8SDavid du Colombier 		&&  samename(sp->owner, owner))
111*00d97012SDavid du Colombier 		{	return sp;		/* global */
112*00d97012SDavid du Colombier 	}	}
113219b2ee8SDavid du Colombier 
1147dd7cddfSDavid du Colombier 	sp = (Symbol *) emalloc(sizeof(Symbol));
115*00d97012SDavid du Colombier 	sp->name = (char *) emalloc(strlen(s) + 1);
116219b2ee8SDavid du Colombier 	strcpy(sp->name, s);
117219b2ee8SDavid du Colombier 	sp->nel = 1;
118219b2ee8SDavid du Colombier 	sp->setat = depth;
119219b2ee8SDavid du Colombier 	sp->context = context;
120219b2ee8SDavid du Colombier 	sp->owner = owner;			/* if fld in struct */
121*00d97012SDavid du Colombier 	sp->bscp = (unsigned char *) emalloc(strlen((const char *)CurScope)+1);
122*00d97012SDavid du Colombier 	strcpy((char *)sp->bscp, CurScope);
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier 	if (NamesNotAdded == 0)
1257dd7cddfSDavid du Colombier 	{	sp->next = symtab[h];
126219b2ee8SDavid du Colombier 		symtab[h] = sp;
1277dd7cddfSDavid du Colombier 		no = (Ordered *) emalloc(sizeof(Ordered));
1287dd7cddfSDavid du Colombier 		no->entry = sp;
1297dd7cddfSDavid du Colombier 		if (!last_name)
1307dd7cddfSDavid du Colombier 			last_name = all_names = no;
1317dd7cddfSDavid du Colombier 		else
1327dd7cddfSDavid du Colombier 		{	last_name->next = no;
1337dd7cddfSDavid du Colombier 			last_name = no;
1347dd7cddfSDavid du Colombier 	}	}
135219b2ee8SDavid du Colombier 
136219b2ee8SDavid du Colombier 	return sp;
137219b2ee8SDavid du Colombier }
138219b2ee8SDavid du Colombier 
139219b2ee8SDavid du Colombier void
trackvar(Lextok * n,Lextok * m)1407dd7cddfSDavid du Colombier trackvar(Lextok *n, Lextok *m)
1417dd7cddfSDavid du Colombier {	Symbol *sp = n->sym;
1427dd7cddfSDavid du Colombier 
1437dd7cddfSDavid du Colombier 	if (!sp) return;	/* a structure list */
1447dd7cddfSDavid du Colombier 	switch (m->ntyp) {
1457dd7cddfSDavid du Colombier 	case NAME:
1467dd7cddfSDavid du Colombier 		if (m->sym->type != BIT)
1477dd7cddfSDavid du Colombier 		{	sp->hidden |= 4;
1487dd7cddfSDavid du Colombier 			if (m->sym->type != BYTE)
1497dd7cddfSDavid du Colombier 				sp->hidden |= 8;
1507dd7cddfSDavid du Colombier 		}
1517dd7cddfSDavid du Colombier 		break;
1527dd7cddfSDavid du Colombier 	case CONST:
1537dd7cddfSDavid du Colombier 		if (m->val != 0 && m->val != 1)
1547dd7cddfSDavid du Colombier 			sp->hidden |= 4;
1557dd7cddfSDavid du Colombier 		if (m->val < 0 || m->val > 256)
1567dd7cddfSDavid du Colombier 			sp->hidden |= 8; /* ditto byte-equiv */
1577dd7cddfSDavid du Colombier 		break;
1587dd7cddfSDavid du Colombier 	default:	/* unknown */
1597dd7cddfSDavid du Colombier 		sp->hidden |= (4|8); /* not known bit-equiv */
1607dd7cddfSDavid du Colombier 	}
1617dd7cddfSDavid du Colombier }
1627dd7cddfSDavid du Colombier 
1637dd7cddfSDavid du Colombier void
trackrun(Lextok * n)1647dd7cddfSDavid du Colombier trackrun(Lextok *n)
1657dd7cddfSDavid du Colombier {
1667dd7cddfSDavid du Colombier 	runstmnts = nn(ZN, 0, n, runstmnts);
1677dd7cddfSDavid du Colombier }
1687dd7cddfSDavid du Colombier 
1697dd7cddfSDavid du Colombier void
checkrun(Symbol * parnm,int posno)1707dd7cddfSDavid du Colombier checkrun(Symbol *parnm, int posno)
1717dd7cddfSDavid du Colombier {	Lextok *n, *now, *v; int i, m;
1727dd7cddfSDavid du Colombier 	int res = 0; char buf[16], buf2[16];
1737dd7cddfSDavid du Colombier 
1747dd7cddfSDavid du Colombier 	for (n = runstmnts; n; n = n->rgt)
1757dd7cddfSDavid du Colombier 	{	now = n->lft;
1767dd7cddfSDavid du Colombier 		if (now->sym != parnm->context)
1777dd7cddfSDavid du Colombier 			continue;
1787dd7cddfSDavid du Colombier 		for (v = now->lft, i = 0; v; v = v->rgt, i++)
1797dd7cddfSDavid du Colombier 			if (i == posno)
1807dd7cddfSDavid du Colombier 			{	m = v->lft->ntyp;
1817dd7cddfSDavid du Colombier 				if (m == CONST)
1827dd7cddfSDavid du Colombier 				{	m = v->lft->val;
1837dd7cddfSDavid du Colombier 					if (m != 0 && m != 1)
1847dd7cddfSDavid du Colombier 						res |= 4;
1857dd7cddfSDavid du Colombier 					if (m < 0 || m > 256)
1867dd7cddfSDavid du Colombier 						res |= 8;
1877dd7cddfSDavid du Colombier 				} else if (m == NAME)
1887dd7cddfSDavid du Colombier 				{	m = v->lft->sym->type;
1897dd7cddfSDavid du Colombier 					if (m != BIT)
1907dd7cddfSDavid du Colombier 					{	res |= 4;
1917dd7cddfSDavid du Colombier 						if (m != BYTE)
1927dd7cddfSDavid du Colombier 							res |= 8;
1937dd7cddfSDavid du Colombier 					}
1947dd7cddfSDavid du Colombier 				} else
1957dd7cddfSDavid du Colombier 					res |= (4|8); /* unknown */
1967dd7cddfSDavid du Colombier 				break;
1977dd7cddfSDavid du Colombier 	}		}
1987dd7cddfSDavid du Colombier 	if (!(res&4) || !(res&8))
1997dd7cddfSDavid du Colombier 	{	if (!(verbose&32)) return;
2007dd7cddfSDavid du Colombier 		strcpy(buf2, (!(res&4))?"bit":"byte");
2017dd7cddfSDavid du Colombier 		sputtype(buf, parnm->type);
202312a1df1SDavid du Colombier 		i = (int) strlen(buf);
203*00d97012SDavid du Colombier 		while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
204*00d97012SDavid du Colombier 		if (i == 0 || strcmp(buf, buf2) == 0) return;
2057dd7cddfSDavid du Colombier 		prehint(parnm);
2067dd7cddfSDavid du Colombier 		printf("proctype %s, '%s %s' could be declared",
207*00d97012SDavid du Colombier 			parnm->context?parnm->context->name:"", buf, parnm->name);
2087dd7cddfSDavid du Colombier 		printf(" '%s %s'\n", buf2, parnm->name);
2097dd7cddfSDavid du Colombier 	}
2107dd7cddfSDavid du Colombier }
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier void
trackchanuse(Lextok * m,Lextok * w,int t)2137dd7cddfSDavid du Colombier trackchanuse(Lextok *m, Lextok *w, int t)
2147dd7cddfSDavid du Colombier {	Lextok *n = m; int cnt = 1;
215219b2ee8SDavid du Colombier 	while (n)
2167dd7cddfSDavid du Colombier 	{	if (n->lft
2177dd7cddfSDavid du Colombier 		&&  n->lft->sym
2187dd7cddfSDavid du Colombier 		&&  n->lft->sym->type == CHAN)
2197dd7cddfSDavid du Colombier 			setaccess(n->lft->sym, w?w->sym:ZS, cnt, t);
2207dd7cddfSDavid du Colombier 		n = n->rgt; cnt++;
2217dd7cddfSDavid du Colombier 	}
2227dd7cddfSDavid du Colombier }
2237dd7cddfSDavid du Colombier 
2247dd7cddfSDavid du Colombier void
setptype(Lextok * n,int t,Lextok * vis)2257dd7cddfSDavid du Colombier setptype(Lextok *n, int t, Lextok *vis)	/* predefined types */
2267dd7cddfSDavid du Colombier {	int oln = lineno, cnt = 1; extern int Expand_Ok;
227f3793cddSDavid du Colombier 
2287dd7cddfSDavid du Colombier 	while (n)
2297dd7cddfSDavid du Colombier 	{	if (n->sym->type && !(n->sym->hidden&32))
230219b2ee8SDavid du Colombier 		{	lineno = n->ln; Fname = n->fn;
231*00d97012SDavid du Colombier 			fatal("redeclaration of '%s'", n->sym->name);
232219b2ee8SDavid du Colombier 			lineno = oln;
233219b2ee8SDavid du Colombier 		}
2347dd7cddfSDavid du Colombier 		n->sym->type = (short) t;
2357dd7cddfSDavid du Colombier 
2367dd7cddfSDavid du Colombier 		if (Expand_Ok)
2377dd7cddfSDavid du Colombier 		{	n->sym->hidden |= (4|8|16); /* formal par */
2387dd7cddfSDavid du Colombier 			if (t == CHAN)
2397dd7cddfSDavid du Colombier 			setaccess(n->sym, ZS, cnt, 'F');
2407dd7cddfSDavid du Colombier 		}
2417dd7cddfSDavid du Colombier 		if (t == UNSIGNED)
242f3793cddSDavid du Colombier 		{	if (n->sym->nbits < 0 || n->sym->nbits >= 32)
2437dd7cddfSDavid du Colombier 			fatal("(%s) has invalid width-field", n->sym->name);
2447dd7cddfSDavid du Colombier 			if (n->sym->nbits == 0)
2457dd7cddfSDavid du Colombier 			{	n->sym->nbits = 16;
2467dd7cddfSDavid du Colombier 				non_fatal("unsigned without width-field", 0);
2477dd7cddfSDavid du Colombier 			}
2487dd7cddfSDavid du Colombier 		} else if (n->sym->nbits > 0)
2497dd7cddfSDavid du Colombier 		{	non_fatal("(%s) only an unsigned can have width-field",
2507dd7cddfSDavid du Colombier 				n->sym->name);
2517dd7cddfSDavid du Colombier 		}
252219b2ee8SDavid du Colombier 		if (vis)
253*00d97012SDavid du Colombier 		{	if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
2547dd7cddfSDavid du Colombier 			{	n->sym->hidden |= 1;
255*00d97012SDavid du Colombier 				has_hidden++;
2567dd7cddfSDavid du Colombier 				if (t == BIT)
2577dd7cddfSDavid du Colombier 				fatal("bit variable (%s) cannot be hidden",
2587dd7cddfSDavid du Colombier 					n->sym->name);
259*00d97012SDavid du Colombier 			} else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
2607dd7cddfSDavid du Colombier 			{	n->sym->hidden |= 2;
261*00d97012SDavid du Colombier 			} else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
2627dd7cddfSDavid du Colombier 			{	n->sym->hidden |= 64;
2637dd7cddfSDavid du Colombier 			}
2647dd7cddfSDavid du Colombier 		}
265219b2ee8SDavid du Colombier 		if (t == CHAN)
266219b2ee8SDavid du Colombier 			n->sym->Nid = ++Nid;
267219b2ee8SDavid du Colombier 		else
2687dd7cddfSDavid du Colombier 		{	n->sym->Nid = 0;
2697dd7cddfSDavid du Colombier 			if (n->sym->ini
2707dd7cddfSDavid du Colombier 			&&  n->sym->ini->ntyp == CHAN)
2717dd7cddfSDavid du Colombier 			{	Fname = n->fn;
2727dd7cddfSDavid du Colombier 				lineno = n->ln;
2737dd7cddfSDavid du Colombier 				fatal("chan initializer for non-channel %s",
2747dd7cddfSDavid du Colombier 				n->sym->name);
2757dd7cddfSDavid du Colombier 			}
2767dd7cddfSDavid du Colombier 		}
277219b2ee8SDavid du Colombier 		if (n->sym->nel <= 0)
278219b2ee8SDavid du Colombier 		{ lineno = n->ln; Fname = n->fn;
279219b2ee8SDavid du Colombier 		  non_fatal("bad array size for '%s'", n->sym->name);
280219b2ee8SDavid du Colombier 		  lineno = oln;
281219b2ee8SDavid du Colombier 		}
2827dd7cddfSDavid du Colombier 		n = n->rgt; cnt++;
283219b2ee8SDavid du Colombier 	}
284219b2ee8SDavid du Colombier }
285219b2ee8SDavid du Colombier 
2867dd7cddfSDavid du Colombier static void
setonexu(Symbol * sp,int t)287219b2ee8SDavid du Colombier setonexu(Symbol *sp, int t)
288219b2ee8SDavid du Colombier {
289219b2ee8SDavid du Colombier 	sp->xu |= t;
290219b2ee8SDavid du Colombier 	if (t == XR || t == XS)
291219b2ee8SDavid du Colombier 	{	if (sp->xup[t-1]
292219b2ee8SDavid du Colombier 		&&  strcmp(sp->xup[t-1]->name, context->name))
293219b2ee8SDavid du Colombier 		{	printf("error: x[rs] claims from %s and %s\n",
294219b2ee8SDavid du Colombier 				sp->xup[t-1]->name, context->name);
295219b2ee8SDavid du Colombier 			non_fatal("conflicting claims on chan '%s'",
296219b2ee8SDavid du Colombier 				sp->name);
297219b2ee8SDavid du Colombier 		}
298219b2ee8SDavid du Colombier 		sp->xup[t-1] = context;
299219b2ee8SDavid du Colombier 	}
300219b2ee8SDavid du Colombier }
301219b2ee8SDavid du Colombier 
3027dd7cddfSDavid du Colombier static void
setallxu(Lextok * n,int t)303219b2ee8SDavid du Colombier setallxu(Lextok *n, int t)
304219b2ee8SDavid du Colombier {	Lextok *fp, *tl;
305219b2ee8SDavid du Colombier 
306219b2ee8SDavid du Colombier 	for (fp = n; fp; fp = fp->rgt)
307219b2ee8SDavid du Colombier 	for (tl = fp->lft; tl; tl = tl->rgt)
308219b2ee8SDavid du Colombier 	{	if (tl->sym->type == STRUCT)
309219b2ee8SDavid du Colombier 			setallxu(tl->sym->Slst, t);
310219b2ee8SDavid du Colombier 		else if (tl->sym->type == CHAN)
311219b2ee8SDavid du Colombier 			setonexu(tl->sym, t);
312219b2ee8SDavid du Colombier 	}
313219b2ee8SDavid du Colombier }
314219b2ee8SDavid du Colombier 
315219b2ee8SDavid du Colombier Lextok *Xu_List = (Lextok *) 0;
316219b2ee8SDavid du Colombier 
317219b2ee8SDavid du Colombier void
setxus(Lextok * p,int t)318219b2ee8SDavid du Colombier setxus(Lextok *p, int t)
319219b2ee8SDavid du Colombier {	Lextok *m, *n;
320219b2ee8SDavid du Colombier 
321219b2ee8SDavid du Colombier 	has_xu = 1;
322*00d97012SDavid du Colombier 
323*00d97012SDavid du Colombier 	if (m_loss && t == XS)
324*00d97012SDavid du Colombier 	{	printf("spin: warning, %s:%d, xs tag not compatible with -m (message loss)\n",
325*00d97012SDavid du Colombier 			(p->fn != NULL) ? p->fn->name : "stdin", p->ln);
326*00d97012SDavid du Colombier 	}
327*00d97012SDavid du Colombier 
328219b2ee8SDavid du Colombier 	if (!context)
329219b2ee8SDavid du Colombier 	{	lineno = p->ln;
330219b2ee8SDavid du Colombier 		Fname = p->fn;
331f3793cddSDavid du Colombier 		fatal("non-local x[rs] assertion", (char *)0);
332219b2ee8SDavid du Colombier 	}
333219b2ee8SDavid du Colombier 	for (m = p; m; m = m->rgt)
334219b2ee8SDavid du Colombier 	{	Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok));
335*00d97012SDavid du Colombier 		Xu_new->uiid = p->uiid;
336219b2ee8SDavid du Colombier 		Xu_new->val = t;
337219b2ee8SDavid du Colombier 		Xu_new->lft = m->lft;
338219b2ee8SDavid du Colombier 		Xu_new->sym = context;
339219b2ee8SDavid du Colombier 		Xu_new->rgt = Xu_List;
340219b2ee8SDavid du Colombier 		Xu_List = Xu_new;
341219b2ee8SDavid du Colombier 
342219b2ee8SDavid du Colombier 		n = m->lft;
343219b2ee8SDavid du Colombier 		if (n->sym->type == STRUCT)
344219b2ee8SDavid du Colombier 			setallxu(n->sym->Slst, t);
345219b2ee8SDavid du Colombier 		else if (n->sym->type == CHAN)
346219b2ee8SDavid du Colombier 			setonexu(n->sym, t);
347219b2ee8SDavid du Colombier 		else
348219b2ee8SDavid du Colombier 		{	int oln = lineno;
349219b2ee8SDavid du Colombier 			lineno = n->ln; Fname = n->fn;
350219b2ee8SDavid du Colombier 			non_fatal("xr or xs of non-chan '%s'",
351219b2ee8SDavid du Colombier 				n->sym->name);
352219b2ee8SDavid du Colombier 			lineno = oln;
353219b2ee8SDavid du Colombier 		}
354219b2ee8SDavid du Colombier 	}
355219b2ee8SDavid du Colombier }
356219b2ee8SDavid du Colombier 
357219b2ee8SDavid du Colombier void
setmtype(Lextok * m)358219b2ee8SDavid du Colombier setmtype(Lextok *m)
3597dd7cddfSDavid du Colombier {	Lextok *n;
3607dd7cddfSDavid du Colombier 	int cnt, oln = lineno;
361219b2ee8SDavid du Colombier 
3627dd7cddfSDavid du Colombier 	if (m) { lineno = m->ln; Fname = m->fn; }
3637dd7cddfSDavid du Colombier 
3647dd7cddfSDavid du Colombier 	if (!Mtype)
3657dd7cddfSDavid du Colombier 		Mtype = m;
3667dd7cddfSDavid du Colombier 	else
3677dd7cddfSDavid du Colombier 	{	for (n = Mtype; n->rgt; n = n->rgt)
3687dd7cddfSDavid du Colombier 			;
3697dd7cddfSDavid du Colombier 		n->rgt = m;	/* concatenate */
370219b2ee8SDavid du Colombier 	}
371219b2ee8SDavid du Colombier 
3727dd7cddfSDavid du Colombier 	for (n = Mtype, cnt = 1; n; n = n->rgt, cnt++)	/* syntax check */
373219b2ee8SDavid du Colombier 	{	if (!n->lft || !n->lft->sym
3747dd7cddfSDavid du Colombier 		||   n->lft->ntyp != NAME
375219b2ee8SDavid du Colombier 		||   n->lft->lft)	/* indexed variable */
376219b2ee8SDavid du Colombier 			fatal("bad mtype definition", (char *)0);
377219b2ee8SDavid du Colombier 
378219b2ee8SDavid du Colombier 		/* label the name */
3797dd7cddfSDavid du Colombier 		if (n->lft->sym->type != MTYPE)
380f3793cddSDavid du Colombier 		{	n->lft->sym->hidden |= 128;	/* is used */
381219b2ee8SDavid du Colombier 			n->lft->sym->type = MTYPE;
382219b2ee8SDavid du Colombier 			n->lft->sym->ini = nn(ZN,CONST,ZN,ZN);
383219b2ee8SDavid du Colombier 			n->lft->sym->ini->val = cnt;
3847dd7cddfSDavid du Colombier 		} else if (n->lft->sym->ini->val != cnt)
385312a1df1SDavid du Colombier 			non_fatal("name %s appears twice in mtype declaration",
386312a1df1SDavid du Colombier 				n->lft->sym->name);
387219b2ee8SDavid du Colombier 	}
388219b2ee8SDavid du Colombier 	lineno = oln;
3897dd7cddfSDavid du Colombier 	if (cnt > 256)
3907dd7cddfSDavid du Colombier 		fatal("too many mtype elements (>255)", (char *)0);
391219b2ee8SDavid du Colombier }
392219b2ee8SDavid du Colombier 
393219b2ee8SDavid du Colombier int
ismtype(char * str)3947dd7cddfSDavid du Colombier ismtype(char *str)	/* name to number */
395219b2ee8SDavid du Colombier {	Lextok *n;
396219b2ee8SDavid du Colombier 	int cnt = 1;
397219b2ee8SDavid du Colombier 
398219b2ee8SDavid du Colombier 	for (n = Mtype; n; n = n->rgt)
399219b2ee8SDavid du Colombier 	{	if (strcmp(str, n->lft->sym->name) == 0)
400219b2ee8SDavid du Colombier 			return cnt;
401219b2ee8SDavid du Colombier 		cnt++;
402219b2ee8SDavid du Colombier 	}
403219b2ee8SDavid du Colombier 	return 0;
404219b2ee8SDavid du Colombier }
405219b2ee8SDavid du Colombier 
406219b2ee8SDavid du Colombier int
sputtype(char * foo,int m)407219b2ee8SDavid du Colombier sputtype(char *foo, int m)
408219b2ee8SDavid du Colombier {
409219b2ee8SDavid du Colombier 	switch (m) {
4107dd7cddfSDavid du Colombier 	case UNSIGNED:	strcpy(foo, "unsigned "); break;
411219b2ee8SDavid du Colombier 	case BIT:	strcpy(foo, "bit   "); break;
412219b2ee8SDavid du Colombier 	case BYTE:	strcpy(foo, "byte  "); break;
413219b2ee8SDavid du Colombier 	case CHAN:	strcpy(foo, "chan  "); break;
414219b2ee8SDavid du Colombier 	case SHORT:	strcpy(foo, "short "); break;
415219b2ee8SDavid du Colombier 	case INT:	strcpy(foo, "int   "); break;
416219b2ee8SDavid du Colombier 	case MTYPE:	strcpy(foo, "mtype "); break;
417219b2ee8SDavid du Colombier 	case STRUCT:	strcpy(foo, "struct"); break;
418219b2ee8SDavid du Colombier 	case PROCTYPE:	strcpy(foo, "proctype"); break;
419219b2ee8SDavid du Colombier 	case LABEL:	strcpy(foo, "label "); return 0;
420219b2ee8SDavid du Colombier 	default:	strcpy(foo, "value "); return 0;
421219b2ee8SDavid du Colombier 	}
422219b2ee8SDavid du Colombier 	return 1;
423219b2ee8SDavid du Colombier }
424219b2ee8SDavid du Colombier 
425219b2ee8SDavid du Colombier 
4267dd7cddfSDavid du Colombier static int
puttype(int m)427219b2ee8SDavid du Colombier puttype(int m)
4287dd7cddfSDavid du Colombier {	char buf[128];
429219b2ee8SDavid du Colombier 
430219b2ee8SDavid du Colombier 	if (sputtype(buf, m))
431219b2ee8SDavid du Colombier 	{	printf("%s", buf);
432219b2ee8SDavid du Colombier 		return 1;
433219b2ee8SDavid du Colombier 	}
434219b2ee8SDavid du Colombier 	return 0;
435219b2ee8SDavid du Colombier }
436219b2ee8SDavid du Colombier 
437312a1df1SDavid du Colombier void
symvar(Symbol * sp)438219b2ee8SDavid du Colombier symvar(Symbol *sp)
439219b2ee8SDavid du Colombier {	Lextok *m;
440219b2ee8SDavid du Colombier 
441219b2ee8SDavid du Colombier 	if (!puttype(sp->type))
442219b2ee8SDavid du Colombier 		return;
443219b2ee8SDavid du Colombier 
444219b2ee8SDavid du Colombier 	printf("\t");
445219b2ee8SDavid du Colombier 	if (sp->owner) printf("%s.", sp->owner->name);
446219b2ee8SDavid du Colombier 	printf("%s", sp->name);
447*00d97012SDavid du Colombier 	if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
448219b2ee8SDavid du Colombier 
449219b2ee8SDavid du Colombier 	if (sp->type == CHAN)
450219b2ee8SDavid du Colombier 		printf("\t%d", (sp->ini)?sp->ini->val:0);
451*00d97012SDavid du Colombier 	else if (sp->type == STRUCT && sp->Snm != NULL) /* Frank Weil, 2.9.8 */
4527dd7cddfSDavid du Colombier 		printf("\t%s", sp->Snm->name);
453219b2ee8SDavid du Colombier 	else
454219b2ee8SDavid du Colombier 		printf("\t%d", eval(sp->ini));
455219b2ee8SDavid du Colombier 
456219b2ee8SDavid du Colombier 	if (sp->owner)
457312a1df1SDavid du Colombier 		printf("\t<:struct-field:>");
458219b2ee8SDavid du Colombier 	else
459219b2ee8SDavid du Colombier 	if (!sp->context)
460312a1df1SDavid du Colombier 		printf("\t<:global:>");
461219b2ee8SDavid du Colombier 	else
462219b2ee8SDavid du Colombier 		printf("\t<%s>", sp->context->name);
463219b2ee8SDavid du Colombier 
464219b2ee8SDavid du Colombier 	if (sp->Nid < 0)	/* formal parameter */
465219b2ee8SDavid du Colombier 		printf("\t<parameter %d>", -(sp->Nid));
466*00d97012SDavid du Colombier 	else if (sp->type == MTYPE)
467*00d97012SDavid du Colombier 		printf("\t<constant>");
468*00d97012SDavid du Colombier 	else if (sp->isarray)
469*00d97012SDavid du Colombier 		printf("\t<array>");
470219b2ee8SDavid du Colombier 	else
471219b2ee8SDavid du Colombier 		printf("\t<variable>");
472*00d97012SDavid du Colombier 
473219b2ee8SDavid du Colombier 	if (sp->type == CHAN && sp->ini)
474219b2ee8SDavid du Colombier 	{	int i;
475219b2ee8SDavid du Colombier 		for (m = sp->ini->rgt, i = 0; m; m = m->rgt)
476219b2ee8SDavid du Colombier 			i++;
477219b2ee8SDavid du Colombier 		printf("\t%d\t", i);
478219b2ee8SDavid du Colombier 		for (m = sp->ini->rgt; m; m = m->rgt)
479312a1df1SDavid du Colombier 		{	if (m->ntyp == STRUCT)
480312a1df1SDavid du Colombier 				printf("struct %s", m->sym->name);
481312a1df1SDavid du Colombier 			else
482312a1df1SDavid du Colombier 				(void) puttype(m->ntyp);
483219b2ee8SDavid du Colombier 			if (m->rgt) printf("\t");
484219b2ee8SDavid du Colombier 		}
485219b2ee8SDavid du Colombier 	}
486*00d97012SDavid du Colombier 
487*00d97012SDavid du Colombier if (1)	printf("\t{scope %s}", sp->bscp);
488*00d97012SDavid du Colombier 
489219b2ee8SDavid du Colombier 	printf("\n");
490219b2ee8SDavid du Colombier }
491219b2ee8SDavid du Colombier 
492219b2ee8SDavid du Colombier void
symdump(void)493219b2ee8SDavid du Colombier symdump(void)
4947dd7cddfSDavid du Colombier {	Ordered *walk;
495219b2ee8SDavid du Colombier 
4967dd7cddfSDavid du Colombier 	for (walk = all_names; walk; walk = walk->next)
4977dd7cddfSDavid du Colombier 		symvar(walk->entry);
4987dd7cddfSDavid du Colombier }
4997dd7cddfSDavid du Colombier 
5007dd7cddfSDavid du Colombier void
chname(Symbol * sp)5017dd7cddfSDavid du Colombier chname(Symbol *sp)
5027dd7cddfSDavid du Colombier {	printf("chan ");
5037dd7cddfSDavid du Colombier 	if (sp->context) printf("%s-", sp->context->name);
5047dd7cddfSDavid du Colombier 	if (sp->owner) printf("%s.", sp->owner->name);
5057dd7cddfSDavid du Colombier 	printf("%s", sp->name);
506*00d97012SDavid du Colombier 	if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
5077dd7cddfSDavid du Colombier 	printf("\t");
5087dd7cddfSDavid du Colombier }
5097dd7cddfSDavid du Colombier 
5107dd7cddfSDavid du Colombier static struct X {
5117dd7cddfSDavid du Colombier 	int typ; char *nm;
5127dd7cddfSDavid du Colombier } xx[] = {
5137dd7cddfSDavid du Colombier 	{ 'A', "exported as run parameter" },
5147dd7cddfSDavid du Colombier 	{ 'F', "imported as proctype parameter" },
5157dd7cddfSDavid du Colombier 	{ 'L', "used as l-value in asgnmnt" },
5167dd7cddfSDavid du Colombier 	{ 'V', "used as r-value in asgnmnt" },
5177dd7cddfSDavid du Colombier 	{ 'P', "polled in receive stmnt" },
5187dd7cddfSDavid du Colombier 	{ 'R', "used as parameter in receive stmnt" },
5197dd7cddfSDavid du Colombier 	{ 'S', "used as parameter in send stmnt" },
5207dd7cddfSDavid du Colombier 	{ 'r', "received from" },
5217dd7cddfSDavid du Colombier 	{ 's', "sent to" },
5227dd7cddfSDavid du Colombier };
5237dd7cddfSDavid du Colombier 
5247dd7cddfSDavid du Colombier static void
chan_check(Symbol * sp)5257dd7cddfSDavid du Colombier chan_check(Symbol *sp)
5267dd7cddfSDavid du Colombier {	Access *a; int i, b=0, d;
5277dd7cddfSDavid du Colombier 
5287dd7cddfSDavid du Colombier 	if (verbose&1) goto report;	/* -C -g */
5297dd7cddfSDavid du Colombier 
5307dd7cddfSDavid du Colombier 	for (a = sp->access; a; a = a->lnk)
5317dd7cddfSDavid du Colombier 		if (a->typ == 'r')
5327dd7cddfSDavid du Colombier 			b |= 1;
5337dd7cddfSDavid du Colombier 		else if (a->typ == 's')
5347dd7cddfSDavid du Colombier 			b |= 2;
5357dd7cddfSDavid du Colombier 	if (b == 3 || (sp->hidden&16))	/* balanced or formal par */
5367dd7cddfSDavid du Colombier 		return;
5377dd7cddfSDavid du Colombier report:
5387dd7cddfSDavid du Colombier 	chname(sp);
539f3793cddSDavid du Colombier 	for (i = d = 0; i < (int) (sizeof(xx)/sizeof(struct X)); i++)
5407dd7cddfSDavid du Colombier 	{	b = 0;
5417dd7cddfSDavid du Colombier 		for (a = sp->access; a; a = a->lnk)
5427dd7cddfSDavid du Colombier 			if (a->typ == xx[i].typ) b++;
5437dd7cddfSDavid du Colombier 		if (b == 0) continue; d++;
5447dd7cddfSDavid du Colombier 		printf("\n\t%s by: ", xx[i].nm);
5457dd7cddfSDavid du Colombier 		for (a = sp->access; a; a = a->lnk)
5467dd7cddfSDavid du Colombier 		  if (a->typ == xx[i].typ)
5477dd7cddfSDavid du Colombier 		  {	printf("%s", a->who->name);
5487dd7cddfSDavid du Colombier 			if (a->what) printf(" to %s", a->what->name);
5497dd7cddfSDavid du Colombier 			if (a->cnt)  printf(" par %d", a->cnt);
5507dd7cddfSDavid du Colombier 			if (--b > 0) printf(", ");
5517dd7cddfSDavid du Colombier 		  }
5527dd7cddfSDavid du Colombier 	}
5537dd7cddfSDavid du Colombier 	printf("%s\n", (!d)?"\n\tnever used under this name":"");
5547dd7cddfSDavid du Colombier }
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier void
chanaccess(void)5577dd7cddfSDavid du Colombier chanaccess(void)
5587dd7cddfSDavid du Colombier {	Ordered *walk;
5597dd7cddfSDavid du Colombier 	char buf[128];
5607dd7cddfSDavid du Colombier 	extern int Caccess, separate;
561312a1df1SDavid du Colombier 	extern short has_code;
5627dd7cddfSDavid du Colombier 
5637dd7cddfSDavid du Colombier 	for (walk = all_names; walk; walk = walk->next)
5647dd7cddfSDavid du Colombier 	{	if (!walk->entry->owner)
5657dd7cddfSDavid du Colombier 		switch (walk->entry->type) {
5667dd7cddfSDavid du Colombier 		case CHAN:
5677dd7cddfSDavid du Colombier 			if (Caccess) chan_check(walk->entry);
5687dd7cddfSDavid du Colombier 			break;
5697dd7cddfSDavid du Colombier 		case MTYPE:
5707dd7cddfSDavid du Colombier 		case BIT:
5717dd7cddfSDavid du Colombier 		case BYTE:
5727dd7cddfSDavid du Colombier 		case SHORT:
5737dd7cddfSDavid du Colombier 		case INT:
5747dd7cddfSDavid du Colombier 		case UNSIGNED:
575f3793cddSDavid du Colombier 			if ((walk->entry->hidden&128))	/* was: 32 */
5767dd7cddfSDavid du Colombier 				continue;
5777dd7cddfSDavid du Colombier 
578312a1df1SDavid du Colombier 			if (!separate
579312a1df1SDavid du Colombier 			&&  !walk->entry->context
580312a1df1SDavid du Colombier 			&&  !has_code
581312a1df1SDavid du Colombier 			&&   deadvar)
5827dd7cddfSDavid du Colombier 				walk->entry->hidden |= 1; /* auto-hide */
5837dd7cddfSDavid du Colombier 
584312a1df1SDavid du Colombier 			if (!(verbose&32) || has_code) continue;
5857dd7cddfSDavid du Colombier 
5867dd7cddfSDavid du Colombier 			printf("spin: warning, %s, ", Fname->name);
5877dd7cddfSDavid du Colombier 			sputtype(buf, walk->entry->type);
5887dd7cddfSDavid du Colombier 			if (walk->entry->context)
5897dd7cddfSDavid du Colombier 				printf("proctype %s",
5907dd7cddfSDavid du Colombier 					walk->entry->context->name);
5917dd7cddfSDavid du Colombier 			else
5927dd7cddfSDavid du Colombier 				printf("global");
5937dd7cddfSDavid du Colombier 			printf(", '%s%s' variable is never used\n",
5947dd7cddfSDavid du Colombier 				buf, walk->entry->name);
595312a1df1SDavid du Colombier 	}	}
596219b2ee8SDavid du Colombier }
597