1219b2ee8SDavid du Colombier /***** spin: sym.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"
11219b2ee8SDavid du Colombier
12219b2ee8SDavid du Colombier extern Symbol *Fname, *owner;
137dd7cddfSDavid du Colombier extern int lineno, depth, verbose, NamesNotAdded, deadvar;
1400d97012SDavid du Colombier extern int has_hidden, m_loss, old_scope_rules;
157dd7cddfSDavid du Colombier extern short has_xu;
1600d97012SDavid du Colombier extern char CurScope[MAXSCOPESZ];
17219b2ee8SDavid du Colombier
18219b2ee8SDavid du Colombier Symbol *context = ZS;
197dd7cddfSDavid du Colombier Ordered *all_names = (Ordered *)0;
20*de2caf28SDavid du Colombier int Nid_nr = 0;
21219b2ee8SDavid du Colombier
22*de2caf28SDavid du Colombier Mtypes_t *Mtypes;
23*de2caf28SDavid du Colombier Lextok *runstmnts = ZN;
2400d97012SDavid du Colombier
257dd7cddfSDavid du Colombier static Ordered *last_name = (Ordered *)0;
267dd7cddfSDavid du Colombier static Symbol *symtab[Nhash+1];
277dd7cddfSDavid du Colombier
287dd7cddfSDavid du Colombier static int
samename(Symbol * a,Symbol * b)29219b2ee8SDavid du Colombier samename(Symbol *a, Symbol *b)
30219b2ee8SDavid du Colombier {
31219b2ee8SDavid du Colombier if (!a && !b) return 1;
32219b2ee8SDavid du Colombier if (!a || !b) return 0;
33219b2ee8SDavid du Colombier return !strcmp(a->name, b->name);
34219b2ee8SDavid du Colombier }
35219b2ee8SDavid du Colombier
36*de2caf28SDavid du Colombier unsigned int
hash(const char * s)37*de2caf28SDavid du Colombier hash(const char *s)
38*de2caf28SDavid du Colombier { unsigned int h = 0;
39219b2ee8SDavid du Colombier
40219b2ee8SDavid du Colombier while (*s)
41*de2caf28SDavid du Colombier { h += (unsigned int) *s++;
42219b2ee8SDavid du Colombier h <<= 1;
43219b2ee8SDavid du Colombier if (h&(Nhash+1))
44219b2ee8SDavid du Colombier h |= 1;
45219b2ee8SDavid du Colombier }
46219b2ee8SDavid du Colombier return h&Nhash;
47219b2ee8SDavid du Colombier }
48219b2ee8SDavid du Colombier
4900d97012SDavid du Colombier void
disambiguate(void)5000d97012SDavid du Colombier disambiguate(void)
5100d97012SDavid du Colombier { Ordered *walk;
5200d97012SDavid du Colombier Symbol *sp;
53*de2caf28SDavid du Colombier char *n, *m;
5400d97012SDavid du Colombier
5500d97012SDavid du Colombier if (old_scope_rules)
5600d97012SDavid du Colombier return;
5700d97012SDavid du Colombier
58*de2caf28SDavid du Colombier /* prepend the scope_prefix to the names */
5900d97012SDavid du Colombier
6000d97012SDavid du Colombier for (walk = all_names; walk; walk = walk->next)
6100d97012SDavid du Colombier { sp = walk->entry;
6200d97012SDavid du Colombier if (sp->type != 0
6300d97012SDavid du Colombier && sp->type != LABEL
6400d97012SDavid du Colombier && strlen((const char *)sp->bscp) > 1)
65*de2caf28SDavid du Colombier { if (sp->context)
66*de2caf28SDavid du Colombier { m = (char *) emalloc(strlen((const char *)sp->bscp) + 1);
67*de2caf28SDavid du Colombier sprintf(m, "_%d_", sp->context->sc);
68*de2caf28SDavid du Colombier if (strcmp((const char *) m, (const char *) sp->bscp) == 0)
69*de2caf28SDavid du Colombier { continue;
70*de2caf28SDavid du Colombier /* 6.2.0: only prepend scope for inner-blocks,
71*de2caf28SDavid du Colombier not for top-level locals within a proctype
72*de2caf28SDavid du Colombier this means that you can no longer use the same name
73*de2caf28SDavid du Colombier for a global and a (top-level) local variable
74*de2caf28SDavid du Colombier */
75*de2caf28SDavid du Colombier } }
76*de2caf28SDavid du Colombier
77*de2caf28SDavid du Colombier n = (char *) emalloc(strlen((const char *)sp->name)
7800d97012SDavid du Colombier + strlen((const char *)sp->bscp) + 1);
7900d97012SDavid du Colombier sprintf(n, "%s%s", sp->bscp, sp->name);
80*de2caf28SDavid du Colombier sp->name = n; /* discard the old memory */
8100d97012SDavid du Colombier } }
8200d97012SDavid du Colombier }
8300d97012SDavid du Colombier
84219b2ee8SDavid du Colombier Symbol *
lookup(char * s)85219b2ee8SDavid du Colombier lookup(char *s)
867dd7cddfSDavid du Colombier { Symbol *sp; Ordered *no;
87*de2caf28SDavid du Colombier unsigned int h = hash(s);
88219b2ee8SDavid du Colombier
8900d97012SDavid du Colombier if (old_scope_rules)
9000d97012SDavid du Colombier { /* same scope - global refering to global or local to local */
91219b2ee8SDavid du Colombier for (sp = symtab[h]; sp; sp = sp->next)
9200d97012SDavid du Colombier { if (strcmp(sp->name, s) == 0
93219b2ee8SDavid du Colombier && samename(sp->context, context)
94219b2ee8SDavid du Colombier && samename(sp->owner, owner))
9500d97012SDavid du Colombier { return sp; /* found */
9600d97012SDavid du Colombier } }
9700d97012SDavid du Colombier } else
9800d97012SDavid du Colombier { /* added 6.0.0: more traditional, scope rule */
99219b2ee8SDavid du Colombier for (sp = symtab[h]; sp; sp = sp->next)
10000d97012SDavid du Colombier { if (strcmp(sp->name, s) == 0
10100d97012SDavid du Colombier && samename(sp->context, context)
10200d97012SDavid du Colombier && (strcmp((const char *)sp->bscp, CurScope) == 0
10300d97012SDavid du Colombier || strncmp((const char *)sp->bscp, CurScope, strlen((const char *)sp->bscp)) == 0)
10400d97012SDavid du Colombier && samename(sp->owner, owner))
10500d97012SDavid du Colombier {
10600d97012SDavid du Colombier if (!samename(sp->owner, owner))
10700d97012SDavid du Colombier { printf("spin: different container %s\n", sp->name);
10800d97012SDavid du Colombier printf(" old: %s\n", sp->owner?sp->owner->name:"--");
10900d97012SDavid du Colombier printf(" new: %s\n", owner?owner->name:"--");
11000d97012SDavid du Colombier /* alldone(1); */
11100d97012SDavid du Colombier }
11200d97012SDavid du Colombier return sp; /* found */
11300d97012SDavid du Colombier } } }
11400d97012SDavid du Colombier
11500d97012SDavid du Colombier if (context) /* in proctype, refers to global */
11600d97012SDavid du Colombier for (sp = symtab[h]; sp; sp = sp->next)
11700d97012SDavid du Colombier { if (strcmp(sp->name, s) == 0
118219b2ee8SDavid du Colombier && !sp->context
119219b2ee8SDavid du Colombier && samename(sp->owner, owner))
12000d97012SDavid du Colombier { return sp; /* global */
12100d97012SDavid du Colombier } }
122219b2ee8SDavid du Colombier
1237dd7cddfSDavid du Colombier sp = (Symbol *) emalloc(sizeof(Symbol));
12400d97012SDavid du Colombier sp->name = (char *) emalloc(strlen(s) + 1);
125219b2ee8SDavid du Colombier strcpy(sp->name, s);
126219b2ee8SDavid du Colombier sp->nel = 1;
127219b2ee8SDavid du Colombier sp->setat = depth;
128219b2ee8SDavid du Colombier sp->context = context;
129219b2ee8SDavid du Colombier sp->owner = owner; /* if fld in struct */
13000d97012SDavid du Colombier sp->bscp = (unsigned char *) emalloc(strlen((const char *)CurScope)+1);
13100d97012SDavid du Colombier strcpy((char *)sp->bscp, CurScope);
1327dd7cddfSDavid du Colombier
1337dd7cddfSDavid du Colombier if (NamesNotAdded == 0)
1347dd7cddfSDavid du Colombier { sp->next = symtab[h];
135219b2ee8SDavid du Colombier symtab[h] = sp;
1367dd7cddfSDavid du Colombier no = (Ordered *) emalloc(sizeof(Ordered));
1377dd7cddfSDavid du Colombier no->entry = sp;
1387dd7cddfSDavid du Colombier if (!last_name)
1397dd7cddfSDavid du Colombier last_name = all_names = no;
1407dd7cddfSDavid du Colombier else
1417dd7cddfSDavid du Colombier { last_name->next = no;
1427dd7cddfSDavid du Colombier last_name = no;
1437dd7cddfSDavid du Colombier } }
144219b2ee8SDavid du Colombier
145219b2ee8SDavid du Colombier return sp;
146219b2ee8SDavid du Colombier }
147219b2ee8SDavid du Colombier
148219b2ee8SDavid du Colombier void
trackvar(Lextok * n,Lextok * m)1497dd7cddfSDavid du Colombier trackvar(Lextok *n, Lextok *m)
1507dd7cddfSDavid du Colombier { Symbol *sp = n->sym;
1517dd7cddfSDavid du Colombier
1527dd7cddfSDavid du Colombier if (!sp) return; /* a structure list */
1537dd7cddfSDavid du Colombier switch (m->ntyp) {
1547dd7cddfSDavid du Colombier case NAME:
1557dd7cddfSDavid du Colombier if (m->sym->type != BIT)
1567dd7cddfSDavid du Colombier { sp->hidden |= 4;
1577dd7cddfSDavid du Colombier if (m->sym->type != BYTE)
1587dd7cddfSDavid du Colombier sp->hidden |= 8;
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier break;
1617dd7cddfSDavid du Colombier case CONST:
1627dd7cddfSDavid du Colombier if (m->val != 0 && m->val != 1)
1637dd7cddfSDavid du Colombier sp->hidden |= 4;
1647dd7cddfSDavid du Colombier if (m->val < 0 || m->val > 256)
1657dd7cddfSDavid du Colombier sp->hidden |= 8; /* ditto byte-equiv */
1667dd7cddfSDavid du Colombier break;
1677dd7cddfSDavid du Colombier default: /* unknown */
1687dd7cddfSDavid du Colombier sp->hidden |= (4|8); /* not known bit-equiv */
1697dd7cddfSDavid du Colombier }
1707dd7cddfSDavid du Colombier }
1717dd7cddfSDavid du Colombier
1727dd7cddfSDavid du Colombier void
trackrun(Lextok * n)1737dd7cddfSDavid du Colombier trackrun(Lextok *n)
1747dd7cddfSDavid du Colombier {
1757dd7cddfSDavid du Colombier runstmnts = nn(ZN, 0, n, runstmnts);
1767dd7cddfSDavid du Colombier }
1777dd7cddfSDavid du Colombier
1787dd7cddfSDavid du Colombier void
checkrun(Symbol * parnm,int posno)1797dd7cddfSDavid du Colombier checkrun(Symbol *parnm, int posno)
1807dd7cddfSDavid du Colombier { Lextok *n, *now, *v; int i, m;
1817dd7cddfSDavid du Colombier int res = 0; char buf[16], buf2[16];
1827dd7cddfSDavid du Colombier
1837dd7cddfSDavid du Colombier for (n = runstmnts; n; n = n->rgt)
1847dd7cddfSDavid du Colombier { now = n->lft;
1857dd7cddfSDavid du Colombier if (now->sym != parnm->context)
1867dd7cddfSDavid du Colombier continue;
1877dd7cddfSDavid du Colombier for (v = now->lft, i = 0; v; v = v->rgt, i++)
1887dd7cddfSDavid du Colombier if (i == posno)
1897dd7cddfSDavid du Colombier { m = v->lft->ntyp;
1907dd7cddfSDavid du Colombier if (m == CONST)
1917dd7cddfSDavid du Colombier { m = v->lft->val;
1927dd7cddfSDavid du Colombier if (m != 0 && m != 1)
1937dd7cddfSDavid du Colombier res |= 4;
1947dd7cddfSDavid du Colombier if (m < 0 || m > 256)
1957dd7cddfSDavid du Colombier res |= 8;
1967dd7cddfSDavid du Colombier } else if (m == NAME)
1977dd7cddfSDavid du Colombier { m = v->lft->sym->type;
1987dd7cddfSDavid du Colombier if (m != BIT)
1997dd7cddfSDavid du Colombier { res |= 4;
2007dd7cddfSDavid du Colombier if (m != BYTE)
2017dd7cddfSDavid du Colombier res |= 8;
2027dd7cddfSDavid du Colombier }
2037dd7cddfSDavid du Colombier } else
2047dd7cddfSDavid du Colombier res |= (4|8); /* unknown */
2057dd7cddfSDavid du Colombier break;
2067dd7cddfSDavid du Colombier } }
2077dd7cddfSDavid du Colombier if (!(res&4) || !(res&8))
2087dd7cddfSDavid du Colombier { if (!(verbose&32)) return;
2097dd7cddfSDavid du Colombier strcpy(buf2, (!(res&4))?"bit":"byte");
2107dd7cddfSDavid du Colombier sputtype(buf, parnm->type);
211312a1df1SDavid du Colombier i = (int) strlen(buf);
21200d97012SDavid du Colombier while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
21300d97012SDavid du Colombier if (i == 0 || strcmp(buf, buf2) == 0) return;
2147dd7cddfSDavid du Colombier prehint(parnm);
2157dd7cddfSDavid du Colombier printf("proctype %s, '%s %s' could be declared",
21600d97012SDavid du Colombier parnm->context?parnm->context->name:"", buf, parnm->name);
2177dd7cddfSDavid du Colombier printf(" '%s %s'\n", buf2, parnm->name);
2187dd7cddfSDavid du Colombier }
2197dd7cddfSDavid du Colombier }
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier void
trackchanuse(Lextok * m,Lextok * w,int t)2227dd7cddfSDavid du Colombier trackchanuse(Lextok *m, Lextok *w, int t)
2237dd7cddfSDavid du Colombier { Lextok *n = m; int cnt = 1;
224219b2ee8SDavid du Colombier while (n)
2257dd7cddfSDavid du Colombier { if (n->lft
2267dd7cddfSDavid du Colombier && n->lft->sym
2277dd7cddfSDavid du Colombier && n->lft->sym->type == CHAN)
2287dd7cddfSDavid du Colombier setaccess(n->lft->sym, w?w->sym:ZS, cnt, t);
2297dd7cddfSDavid du Colombier n = n->rgt; cnt++;
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier
2337dd7cddfSDavid du Colombier void
setptype(Lextok * mtype_name,Lextok * n,int t,Lextok * vis)234*de2caf28SDavid du Colombier setptype(Lextok *mtype_name, Lextok *n, int t, Lextok *vis) /* predefined types */
2357dd7cddfSDavid du Colombier { int oln = lineno, cnt = 1; extern int Expand_Ok;
236f3793cddSDavid du Colombier
2377dd7cddfSDavid du Colombier while (n)
2387dd7cddfSDavid du Colombier { if (n->sym->type && !(n->sym->hidden&32))
239219b2ee8SDavid du Colombier { lineno = n->ln; Fname = n->fn;
24000d97012SDavid du Colombier fatal("redeclaration of '%s'", n->sym->name);
241219b2ee8SDavid du Colombier lineno = oln;
242219b2ee8SDavid du Colombier }
2437dd7cddfSDavid du Colombier n->sym->type = (short) t;
2447dd7cddfSDavid du Colombier
245*de2caf28SDavid du Colombier if (mtype_name && t != MTYPE)
246*de2caf28SDavid du Colombier { lineno = n->ln; Fname = n->fn;
247*de2caf28SDavid du Colombier fatal("missing semi-colon after '%s'?",
248*de2caf28SDavid du Colombier mtype_name->sym->name);
249*de2caf28SDavid du Colombier lineno = oln;
250*de2caf28SDavid du Colombier }
251*de2caf28SDavid du Colombier
252*de2caf28SDavid du Colombier if (mtype_name && n->sym->mtype_name
253*de2caf28SDavid du Colombier && strcmp(mtype_name->sym->name, n->sym->mtype_name->name) != 0)
254*de2caf28SDavid du Colombier { fprintf(stderr, "spin: %s:%d, Error: '%s' is type '%s' but assigned type '%s'\n",
255*de2caf28SDavid du Colombier n->fn->name, n->ln,
256*de2caf28SDavid du Colombier n->sym->name,
257*de2caf28SDavid du Colombier mtype_name->sym->name,
258*de2caf28SDavid du Colombier n->sym->mtype_name->name);
259*de2caf28SDavid du Colombier non_fatal("type error", (char *) 0);
260*de2caf28SDavid du Colombier }
261*de2caf28SDavid du Colombier
262*de2caf28SDavid du Colombier n->sym->mtype_name = mtype_name?mtype_name->sym:0; /* if mtype, else 0 */
263*de2caf28SDavid du Colombier
2647dd7cddfSDavid du Colombier if (Expand_Ok)
2657dd7cddfSDavid du Colombier { n->sym->hidden |= (4|8|16); /* formal par */
2667dd7cddfSDavid du Colombier if (t == CHAN)
2677dd7cddfSDavid du Colombier setaccess(n->sym, ZS, cnt, 'F');
2687dd7cddfSDavid du Colombier }
269*de2caf28SDavid du Colombier
2707dd7cddfSDavid du Colombier if (t == UNSIGNED)
271f3793cddSDavid du Colombier { if (n->sym->nbits < 0 || n->sym->nbits >= 32)
2727dd7cddfSDavid du Colombier fatal("(%s) has invalid width-field", n->sym->name);
2737dd7cddfSDavid du Colombier if (n->sym->nbits == 0)
2747dd7cddfSDavid du Colombier { n->sym->nbits = 16;
2757dd7cddfSDavid du Colombier non_fatal("unsigned without width-field", 0);
2767dd7cddfSDavid du Colombier }
2777dd7cddfSDavid du Colombier } else if (n->sym->nbits > 0)
2787dd7cddfSDavid du Colombier { non_fatal("(%s) only an unsigned can have width-field",
2797dd7cddfSDavid du Colombier n->sym->name);
2807dd7cddfSDavid du Colombier }
281*de2caf28SDavid du Colombier
282219b2ee8SDavid du Colombier if (vis)
28300d97012SDavid du Colombier { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
2847dd7cddfSDavid du Colombier { n->sym->hidden |= 1;
28500d97012SDavid du Colombier has_hidden++;
2867dd7cddfSDavid du Colombier if (t == BIT)
2877dd7cddfSDavid du Colombier fatal("bit variable (%s) cannot be hidden",
2887dd7cddfSDavid du Colombier n->sym->name);
28900d97012SDavid du Colombier } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
2907dd7cddfSDavid du Colombier { n->sym->hidden |= 2;
29100d97012SDavid du Colombier } else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
2927dd7cddfSDavid du Colombier { n->sym->hidden |= 64;
2937dd7cddfSDavid du Colombier }
2947dd7cddfSDavid du Colombier }
295*de2caf28SDavid du Colombier
296219b2ee8SDavid du Colombier if (t == CHAN)
297*de2caf28SDavid du Colombier { n->sym->Nid = ++Nid_nr;
298*de2caf28SDavid du Colombier } else
2997dd7cddfSDavid du Colombier { n->sym->Nid = 0;
3007dd7cddfSDavid du Colombier if (n->sym->ini
3017dd7cddfSDavid du Colombier && n->sym->ini->ntyp == CHAN)
3027dd7cddfSDavid du Colombier { Fname = n->fn;
3037dd7cddfSDavid du Colombier lineno = n->ln;
3047dd7cddfSDavid du Colombier fatal("chan initializer for non-channel %s",
3057dd7cddfSDavid du Colombier n->sym->name);
306*de2caf28SDavid du Colombier } }
307*de2caf28SDavid du Colombier
308219b2ee8SDavid du Colombier if (n->sym->nel <= 0)
309219b2ee8SDavid du Colombier { lineno = n->ln; Fname = n->fn;
310219b2ee8SDavid du Colombier non_fatal("bad array size for '%s'", n->sym->name);
311219b2ee8SDavid du Colombier lineno = oln;
312219b2ee8SDavid du Colombier }
313*de2caf28SDavid du Colombier
3147dd7cddfSDavid du Colombier n = n->rgt; cnt++;
315219b2ee8SDavid du Colombier }
316219b2ee8SDavid du Colombier }
317219b2ee8SDavid du Colombier
3187dd7cddfSDavid du Colombier static void
setonexu(Symbol * sp,int t)319219b2ee8SDavid du Colombier setonexu(Symbol *sp, int t)
320219b2ee8SDavid du Colombier {
321219b2ee8SDavid du Colombier sp->xu |= t;
322219b2ee8SDavid du Colombier if (t == XR || t == XS)
323219b2ee8SDavid du Colombier { if (sp->xup[t-1]
324219b2ee8SDavid du Colombier && strcmp(sp->xup[t-1]->name, context->name))
325219b2ee8SDavid du Colombier { printf("error: x[rs] claims from %s and %s\n",
326219b2ee8SDavid du Colombier sp->xup[t-1]->name, context->name);
327219b2ee8SDavid du Colombier non_fatal("conflicting claims on chan '%s'",
328219b2ee8SDavid du Colombier sp->name);
329219b2ee8SDavid du Colombier }
330219b2ee8SDavid du Colombier sp->xup[t-1] = context;
331219b2ee8SDavid du Colombier }
332219b2ee8SDavid du Colombier }
333219b2ee8SDavid du Colombier
3347dd7cddfSDavid du Colombier static void
setallxu(Lextok * n,int t)335219b2ee8SDavid du Colombier setallxu(Lextok *n, int t)
336219b2ee8SDavid du Colombier { Lextok *fp, *tl;
337219b2ee8SDavid du Colombier
338219b2ee8SDavid du Colombier for (fp = n; fp; fp = fp->rgt)
339219b2ee8SDavid du Colombier for (tl = fp->lft; tl; tl = tl->rgt)
340219b2ee8SDavid du Colombier { if (tl->sym->type == STRUCT)
341219b2ee8SDavid du Colombier setallxu(tl->sym->Slst, t);
342219b2ee8SDavid du Colombier else if (tl->sym->type == CHAN)
343219b2ee8SDavid du Colombier setonexu(tl->sym, t);
344219b2ee8SDavid du Colombier }
345219b2ee8SDavid du Colombier }
346219b2ee8SDavid du Colombier
347219b2ee8SDavid du Colombier Lextok *Xu_List = (Lextok *) 0;
348219b2ee8SDavid du Colombier
349219b2ee8SDavid du Colombier void
setxus(Lextok * p,int t)350219b2ee8SDavid du Colombier setxus(Lextok *p, int t)
351219b2ee8SDavid du Colombier { Lextok *m, *n;
352219b2ee8SDavid du Colombier
353219b2ee8SDavid du Colombier has_xu = 1;
35400d97012SDavid du Colombier
35500d97012SDavid du Colombier if (m_loss && t == XS)
356*de2caf28SDavid du Colombier { printf("spin: %s:%d, warning, xs tag not compatible with -m (message loss)\n",
35700d97012SDavid du Colombier (p->fn != NULL) ? p->fn->name : "stdin", p->ln);
35800d97012SDavid du Colombier }
35900d97012SDavid du Colombier
360219b2ee8SDavid du Colombier if (!context)
361219b2ee8SDavid du Colombier { lineno = p->ln;
362219b2ee8SDavid du Colombier Fname = p->fn;
363f3793cddSDavid du Colombier fatal("non-local x[rs] assertion", (char *)0);
364219b2ee8SDavid du Colombier }
365219b2ee8SDavid du Colombier for (m = p; m; m = m->rgt)
366219b2ee8SDavid du Colombier { Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok));
36700d97012SDavid du Colombier Xu_new->uiid = p->uiid;
368219b2ee8SDavid du Colombier Xu_new->val = t;
369219b2ee8SDavid du Colombier Xu_new->lft = m->lft;
370219b2ee8SDavid du Colombier Xu_new->sym = context;
371219b2ee8SDavid du Colombier Xu_new->rgt = Xu_List;
372219b2ee8SDavid du Colombier Xu_List = Xu_new;
373219b2ee8SDavid du Colombier
374219b2ee8SDavid du Colombier n = m->lft;
375219b2ee8SDavid du Colombier if (n->sym->type == STRUCT)
376219b2ee8SDavid du Colombier setallxu(n->sym->Slst, t);
377219b2ee8SDavid du Colombier else if (n->sym->type == CHAN)
378219b2ee8SDavid du Colombier setonexu(n->sym, t);
379219b2ee8SDavid du Colombier else
380219b2ee8SDavid du Colombier { int oln = lineno;
381219b2ee8SDavid du Colombier lineno = n->ln; Fname = n->fn;
382219b2ee8SDavid du Colombier non_fatal("xr or xs of non-chan '%s'",
383219b2ee8SDavid du Colombier n->sym->name);
384219b2ee8SDavid du Colombier lineno = oln;
385219b2ee8SDavid du Colombier }
386219b2ee8SDavid du Colombier }
387219b2ee8SDavid du Colombier }
388219b2ee8SDavid du Colombier
389*de2caf28SDavid du Colombier Lextok **
find_mtype_list(const char * s)390*de2caf28SDavid du Colombier find_mtype_list(const char *s)
391*de2caf28SDavid du Colombier { Mtypes_t *lst;
392*de2caf28SDavid du Colombier
393*de2caf28SDavid du Colombier for (lst = Mtypes; lst; lst = lst->nxt)
394*de2caf28SDavid du Colombier { if (strcmp(lst->nm, s) == 0)
395*de2caf28SDavid du Colombier { return &(lst->mt);
396*de2caf28SDavid du Colombier } }
397*de2caf28SDavid du Colombier
398*de2caf28SDavid du Colombier /* not found, create it */
399*de2caf28SDavid du Colombier lst = (Mtypes_t *) emalloc(sizeof(Mtypes_t));
400*de2caf28SDavid du Colombier lst->nm = (char *) emalloc(strlen(s)+1);
401*de2caf28SDavid du Colombier strcpy(lst->nm, s);
402*de2caf28SDavid du Colombier lst->nxt = Mtypes;
403*de2caf28SDavid du Colombier Mtypes = lst;
404*de2caf28SDavid du Colombier return &(lst->mt);
405*de2caf28SDavid du Colombier }
406*de2caf28SDavid du Colombier
407219b2ee8SDavid du Colombier void
setmtype(Lextok * mtype_name,Lextok * m)408*de2caf28SDavid du Colombier setmtype(Lextok *mtype_name, Lextok *m)
409*de2caf28SDavid du Colombier { Lextok **mtl; /* mtype list */
410*de2caf28SDavid du Colombier Lextok *n, *Mtype;
4117dd7cddfSDavid du Colombier int cnt, oln = lineno;
412*de2caf28SDavid du Colombier char *s = "_unnamed_";
413219b2ee8SDavid du Colombier
4147dd7cddfSDavid du Colombier if (m) { lineno = m->ln; Fname = m->fn; }
4157dd7cddfSDavid du Colombier
416*de2caf28SDavid du Colombier if (mtype_name && mtype_name->sym)
417*de2caf28SDavid du Colombier { s = mtype_name->sym->name;
418*de2caf28SDavid du Colombier }
419*de2caf28SDavid du Colombier
420*de2caf28SDavid du Colombier mtl = find_mtype_list(s);
421*de2caf28SDavid du Colombier Mtype = *mtl;
422*de2caf28SDavid du Colombier
4237dd7cddfSDavid du Colombier if (!Mtype)
424*de2caf28SDavid du Colombier { *mtl = Mtype = m;
425*de2caf28SDavid du Colombier } else
4267dd7cddfSDavid du Colombier { for (n = Mtype; n->rgt; n = n->rgt)
427*de2caf28SDavid du Colombier { ;
428*de2caf28SDavid du Colombier }
4297dd7cddfSDavid du Colombier n->rgt = m; /* concatenate */
430219b2ee8SDavid du Colombier }
431219b2ee8SDavid du Colombier
4327dd7cddfSDavid du Colombier for (n = Mtype, cnt = 1; n; n = n->rgt, cnt++) /* syntax check */
433219b2ee8SDavid du Colombier { if (!n->lft || !n->lft->sym
4347dd7cddfSDavid du Colombier || n->lft->ntyp != NAME
435219b2ee8SDavid du Colombier || n->lft->lft) /* indexed variable */
436219b2ee8SDavid du Colombier fatal("bad mtype definition", (char *)0);
437219b2ee8SDavid du Colombier
438219b2ee8SDavid du Colombier /* label the name */
4397dd7cddfSDavid du Colombier if (n->lft->sym->type != MTYPE)
440f3793cddSDavid du Colombier { n->lft->sym->hidden |= 128; /* is used */
441219b2ee8SDavid du Colombier n->lft->sym->type = MTYPE;
442219b2ee8SDavid du Colombier n->lft->sym->ini = nn(ZN,CONST,ZN,ZN);
443219b2ee8SDavid du Colombier n->lft->sym->ini->val = cnt;
4447dd7cddfSDavid du Colombier } else if (n->lft->sym->ini->val != cnt)
445*de2caf28SDavid du Colombier { non_fatal("name %s appears twice in mtype declaration",
446312a1df1SDavid du Colombier n->lft->sym->name);
447*de2caf28SDavid du Colombier } }
448*de2caf28SDavid du Colombier
449219b2ee8SDavid du Colombier lineno = oln;
4507dd7cddfSDavid du Colombier if (cnt > 256)
451*de2caf28SDavid du Colombier { fatal("too many mtype elements (>255)", (char *) 0);
452*de2caf28SDavid du Colombier }
453*de2caf28SDavid du Colombier }
454*de2caf28SDavid du Colombier
455*de2caf28SDavid du Colombier char *
which_mtype(const char * str)456*de2caf28SDavid du Colombier which_mtype(const char *str) /* which mtype is str, 0 if not an mtype at all */
457*de2caf28SDavid du Colombier { Mtypes_t *lst;
458*de2caf28SDavid du Colombier Lextok *n;
459*de2caf28SDavid du Colombier
460*de2caf28SDavid du Colombier for (lst = Mtypes; lst; lst = lst->nxt)
461*de2caf28SDavid du Colombier for (n = lst->mt; n; n = n->rgt)
462*de2caf28SDavid du Colombier { if (strcmp(str, n->lft->sym->name) == 0)
463*de2caf28SDavid du Colombier { return lst->nm;
464*de2caf28SDavid du Colombier } }
465*de2caf28SDavid du Colombier
466*de2caf28SDavid du Colombier return (char *) 0;
467219b2ee8SDavid du Colombier }
468219b2ee8SDavid du Colombier
469219b2ee8SDavid du Colombier int
ismtype(char * str)4707dd7cddfSDavid du Colombier ismtype(char *str) /* name to number */
471*de2caf28SDavid du Colombier { Mtypes_t *lst;
472*de2caf28SDavid du Colombier Lextok *n;
473*de2caf28SDavid du Colombier int cnt;
474219b2ee8SDavid du Colombier
475*de2caf28SDavid du Colombier for (lst = Mtypes; lst; lst = lst->nxt)
476*de2caf28SDavid du Colombier { cnt = 1;
477*de2caf28SDavid du Colombier for (n = lst->mt; n; n = n->rgt)
478219b2ee8SDavid du Colombier { if (strcmp(str, n->lft->sym->name) == 0)
479*de2caf28SDavid du Colombier { return cnt;
480219b2ee8SDavid du Colombier }
481*de2caf28SDavid du Colombier cnt++;
482*de2caf28SDavid du Colombier } }
483*de2caf28SDavid du Colombier
484219b2ee8SDavid du Colombier return 0;
485219b2ee8SDavid du Colombier }
486219b2ee8SDavid du Colombier
487219b2ee8SDavid du Colombier int
sputtype(char * foo,int m)488219b2ee8SDavid du Colombier sputtype(char *foo, int m)
489219b2ee8SDavid du Colombier {
490219b2ee8SDavid du Colombier switch (m) {
4917dd7cddfSDavid du Colombier case UNSIGNED: strcpy(foo, "unsigned "); break;
492219b2ee8SDavid du Colombier case BIT: strcpy(foo, "bit "); break;
493219b2ee8SDavid du Colombier case BYTE: strcpy(foo, "byte "); break;
494219b2ee8SDavid du Colombier case CHAN: strcpy(foo, "chan "); break;
495219b2ee8SDavid du Colombier case SHORT: strcpy(foo, "short "); break;
496219b2ee8SDavid du Colombier case INT: strcpy(foo, "int "); break;
497219b2ee8SDavid du Colombier case MTYPE: strcpy(foo, "mtype "); break;
498219b2ee8SDavid du Colombier case STRUCT: strcpy(foo, "struct"); break;
499219b2ee8SDavid du Colombier case PROCTYPE: strcpy(foo, "proctype"); break;
500219b2ee8SDavid du Colombier case LABEL: strcpy(foo, "label "); return 0;
501219b2ee8SDavid du Colombier default: strcpy(foo, "value "); return 0;
502219b2ee8SDavid du Colombier }
503219b2ee8SDavid du Colombier return 1;
504219b2ee8SDavid du Colombier }
505219b2ee8SDavid du Colombier
506219b2ee8SDavid du Colombier
5077dd7cddfSDavid du Colombier static int
puttype(int m)508219b2ee8SDavid du Colombier puttype(int m)
5097dd7cddfSDavid du Colombier { char buf[128];
510219b2ee8SDavid du Colombier
511219b2ee8SDavid du Colombier if (sputtype(buf, m))
512219b2ee8SDavid du Colombier { printf("%s", buf);
513219b2ee8SDavid du Colombier return 1;
514219b2ee8SDavid du Colombier }
515219b2ee8SDavid du Colombier return 0;
516219b2ee8SDavid du Colombier }
517219b2ee8SDavid du Colombier
518312a1df1SDavid du Colombier void
symvar(Symbol * sp)519219b2ee8SDavid du Colombier symvar(Symbol *sp)
520219b2ee8SDavid du Colombier { Lextok *m;
521219b2ee8SDavid du Colombier
522219b2ee8SDavid du Colombier if (!puttype(sp->type))
523219b2ee8SDavid du Colombier return;
524219b2ee8SDavid du Colombier
525219b2ee8SDavid du Colombier printf("\t");
526219b2ee8SDavid du Colombier if (sp->owner) printf("%s.", sp->owner->name);
527219b2ee8SDavid du Colombier printf("%s", sp->name);
52800d97012SDavid du Colombier if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
529219b2ee8SDavid du Colombier
530219b2ee8SDavid du Colombier if (sp->type == CHAN)
531219b2ee8SDavid du Colombier printf("\t%d", (sp->ini)?sp->ini->val:0);
53200d97012SDavid du Colombier else if (sp->type == STRUCT && sp->Snm != NULL) /* Frank Weil, 2.9.8 */
5337dd7cddfSDavid du Colombier printf("\t%s", sp->Snm->name);
534219b2ee8SDavid du Colombier else
535219b2ee8SDavid du Colombier printf("\t%d", eval(sp->ini));
536219b2ee8SDavid du Colombier
537219b2ee8SDavid du Colombier if (sp->owner)
538312a1df1SDavid du Colombier printf("\t<:struct-field:>");
539219b2ee8SDavid du Colombier else
540219b2ee8SDavid du Colombier if (!sp->context)
541312a1df1SDavid du Colombier printf("\t<:global:>");
542219b2ee8SDavid du Colombier else
543219b2ee8SDavid du Colombier printf("\t<%s>", sp->context->name);
544219b2ee8SDavid du Colombier
545219b2ee8SDavid du Colombier if (sp->Nid < 0) /* formal parameter */
546219b2ee8SDavid du Colombier printf("\t<parameter %d>", -(sp->Nid));
54700d97012SDavid du Colombier else if (sp->type == MTYPE)
54800d97012SDavid du Colombier printf("\t<constant>");
54900d97012SDavid du Colombier else if (sp->isarray)
55000d97012SDavid du Colombier printf("\t<array>");
551219b2ee8SDavid du Colombier else
552219b2ee8SDavid du Colombier printf("\t<variable>");
55300d97012SDavid du Colombier
554219b2ee8SDavid du Colombier if (sp->type == CHAN && sp->ini)
555219b2ee8SDavid du Colombier { int i;
556219b2ee8SDavid du Colombier for (m = sp->ini->rgt, i = 0; m; m = m->rgt)
557219b2ee8SDavid du Colombier i++;
558219b2ee8SDavid du Colombier printf("\t%d\t", i);
559219b2ee8SDavid du Colombier for (m = sp->ini->rgt; m; m = m->rgt)
560312a1df1SDavid du Colombier { if (m->ntyp == STRUCT)
561312a1df1SDavid du Colombier printf("struct %s", m->sym->name);
562312a1df1SDavid du Colombier else
563312a1df1SDavid du Colombier (void) puttype(m->ntyp);
564219b2ee8SDavid du Colombier if (m->rgt) printf("\t");
565219b2ee8SDavid du Colombier }
566219b2ee8SDavid du Colombier }
56700d97012SDavid du Colombier
568*de2caf28SDavid du Colombier if (!old_scope_rules)
569*de2caf28SDavid du Colombier { printf("\t{scope %s}", sp->bscp);
570*de2caf28SDavid du Colombier }
57100d97012SDavid du Colombier
572219b2ee8SDavid du Colombier printf("\n");
573219b2ee8SDavid du Colombier }
574219b2ee8SDavid du Colombier
575219b2ee8SDavid du Colombier void
symdump(void)576219b2ee8SDavid du Colombier symdump(void)
5777dd7cddfSDavid du Colombier { Ordered *walk;
578219b2ee8SDavid du Colombier
5797dd7cddfSDavid du Colombier for (walk = all_names; walk; walk = walk->next)
5807dd7cddfSDavid du Colombier symvar(walk->entry);
5817dd7cddfSDavid du Colombier }
5827dd7cddfSDavid du Colombier
5837dd7cddfSDavid du Colombier void
chname(Symbol * sp)5847dd7cddfSDavid du Colombier chname(Symbol *sp)
5857dd7cddfSDavid du Colombier { printf("chan ");
5867dd7cddfSDavid du Colombier if (sp->context) printf("%s-", sp->context->name);
5877dd7cddfSDavid du Colombier if (sp->owner) printf("%s.", sp->owner->name);
5887dd7cddfSDavid du Colombier printf("%s", sp->name);
58900d97012SDavid du Colombier if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
5907dd7cddfSDavid du Colombier printf("\t");
5917dd7cddfSDavid du Colombier }
5927dd7cddfSDavid du Colombier
593*de2caf28SDavid du Colombier static struct X_lkp {
5947dd7cddfSDavid du Colombier int typ; char *nm;
5957dd7cddfSDavid du Colombier } xx[] = {
5967dd7cddfSDavid du Colombier { 'A', "exported as run parameter" },
5977dd7cddfSDavid du Colombier { 'F', "imported as proctype parameter" },
5987dd7cddfSDavid du Colombier { 'L', "used as l-value in asgnmnt" },
5997dd7cddfSDavid du Colombier { 'V', "used as r-value in asgnmnt" },
6007dd7cddfSDavid du Colombier { 'P', "polled in receive stmnt" },
6017dd7cddfSDavid du Colombier { 'R', "used as parameter in receive stmnt" },
6027dd7cddfSDavid du Colombier { 'S', "used as parameter in send stmnt" },
6037dd7cddfSDavid du Colombier { 'r', "received from" },
6047dd7cddfSDavid du Colombier { 's', "sent to" },
6057dd7cddfSDavid du Colombier };
6067dd7cddfSDavid du Colombier
6077dd7cddfSDavid du Colombier static void
chan_check(Symbol * sp)6087dd7cddfSDavid du Colombier chan_check(Symbol *sp)
6097dd7cddfSDavid du Colombier { Access *a; int i, b=0, d;
6107dd7cddfSDavid du Colombier
6117dd7cddfSDavid du Colombier if (verbose&1) goto report; /* -C -g */
6127dd7cddfSDavid du Colombier
6137dd7cddfSDavid du Colombier for (a = sp->access; a; a = a->lnk)
6147dd7cddfSDavid du Colombier if (a->typ == 'r')
6157dd7cddfSDavid du Colombier b |= 1;
6167dd7cddfSDavid du Colombier else if (a->typ == 's')
6177dd7cddfSDavid du Colombier b |= 2;
6187dd7cddfSDavid du Colombier if (b == 3 || (sp->hidden&16)) /* balanced or formal par */
6197dd7cddfSDavid du Colombier return;
6207dd7cddfSDavid du Colombier report:
6217dd7cddfSDavid du Colombier chname(sp);
622*de2caf28SDavid du Colombier for (i = d = 0; i < (int) (sizeof(xx)/sizeof(struct X_lkp)); i++)
6237dd7cddfSDavid du Colombier { b = 0;
6247dd7cddfSDavid du Colombier for (a = sp->access; a; a = a->lnk)
625*de2caf28SDavid du Colombier { if (a->typ == xx[i].typ)
626*de2caf28SDavid du Colombier { b++;
627*de2caf28SDavid du Colombier } }
628*de2caf28SDavid du Colombier if (b == 0)
629*de2caf28SDavid du Colombier { continue;
630*de2caf28SDavid du Colombier }
631*de2caf28SDavid du Colombier d++;
6327dd7cddfSDavid du Colombier printf("\n\t%s by: ", xx[i].nm);
6337dd7cddfSDavid du Colombier for (a = sp->access; a; a = a->lnk)
6347dd7cddfSDavid du Colombier if (a->typ == xx[i].typ)
6357dd7cddfSDavid du Colombier { printf("%s", a->who->name);
6367dd7cddfSDavid du Colombier if (a->what) printf(" to %s", a->what->name);
6377dd7cddfSDavid du Colombier if (a->cnt) printf(" par %d", a->cnt);
6387dd7cddfSDavid du Colombier if (--b > 0) printf(", ");
6397dd7cddfSDavid du Colombier }
6407dd7cddfSDavid du Colombier }
6417dd7cddfSDavid du Colombier printf("%s\n", (!d)?"\n\tnever used under this name":"");
6427dd7cddfSDavid du Colombier }
6437dd7cddfSDavid du Colombier
6447dd7cddfSDavid du Colombier void
chanaccess(void)6457dd7cddfSDavid du Colombier chanaccess(void)
6467dd7cddfSDavid du Colombier { Ordered *walk;
6477dd7cddfSDavid du Colombier char buf[128];
6487dd7cddfSDavid du Colombier extern int Caccess, separate;
649312a1df1SDavid du Colombier extern short has_code;
6507dd7cddfSDavid du Colombier
6517dd7cddfSDavid du Colombier for (walk = all_names; walk; walk = walk->next)
6527dd7cddfSDavid du Colombier { if (!walk->entry->owner)
6537dd7cddfSDavid du Colombier switch (walk->entry->type) {
6547dd7cddfSDavid du Colombier case CHAN:
6557dd7cddfSDavid du Colombier if (Caccess) chan_check(walk->entry);
6567dd7cddfSDavid du Colombier break;
6577dd7cddfSDavid du Colombier case MTYPE:
6587dd7cddfSDavid du Colombier case BIT:
6597dd7cddfSDavid du Colombier case BYTE:
6607dd7cddfSDavid du Colombier case SHORT:
6617dd7cddfSDavid du Colombier case INT:
6627dd7cddfSDavid du Colombier case UNSIGNED:
663f3793cddSDavid du Colombier if ((walk->entry->hidden&128)) /* was: 32 */
6647dd7cddfSDavid du Colombier continue;
6657dd7cddfSDavid du Colombier
666312a1df1SDavid du Colombier if (!separate
667312a1df1SDavid du Colombier && !walk->entry->context
668312a1df1SDavid du Colombier && !has_code
669312a1df1SDavid du Colombier && deadvar)
6707dd7cddfSDavid du Colombier walk->entry->hidden |= 1; /* auto-hide */
6717dd7cddfSDavid du Colombier
672312a1df1SDavid du Colombier if (!(verbose&32) || has_code) continue;
6737dd7cddfSDavid du Colombier
674*de2caf28SDavid du Colombier printf("spin: %s:0, warning, ", Fname->name);
6757dd7cddfSDavid du Colombier sputtype(buf, walk->entry->type);
6767dd7cddfSDavid du Colombier if (walk->entry->context)
6777dd7cddfSDavid du Colombier printf("proctype %s",
6787dd7cddfSDavid du Colombier walk->entry->context->name);
6797dd7cddfSDavid du Colombier else
6807dd7cddfSDavid du Colombier printf("global");
681*de2caf28SDavid du Colombier printf(", '%s%s' variable is never used (other than in print stmnts)\n",
6827dd7cddfSDavid du Colombier buf, walk->entry->name);
683312a1df1SDavid du Colombier } }
684219b2ee8SDavid du Colombier }
685