1 /***** spin: sym.c *****/
4 * This file is part of the public release of Spin. It is subject to the
5 * terms in the LICENSE file that is included in this source directory.
6 * Tool documentation is available at http://spinroot.com
12 extern Symbol *Fname, *owner;
13 extern int lineno, depth, verbose, NamesNotAdded, deadvar;
14 extern int has_hidden, m_loss, old_scope_rules;
16 extern char CurScope[MAXSCOPESZ];
19 Ordered *all_names = (Ordered *)0;
22 Lextok *Mtype = (Lextok *) 0;
23 Lextok *runstmnts = ZN;
25 static Ordered *last_name = (Ordered *)0;
26 static Symbol *symtab[Nhash+1];
29 samename(Symbol *a, Symbol *b)
31 if (!a && !b) return 1;
32 if (!a || !b) return 0;
33 return !strcmp(a->name, b->name);
41 { h += (unsigned int) *s++;
58 /* prepend the scope_prefix to the names */
60 for (walk = all_names; walk; walk = walk->next)
64 && strlen((const char *)sp->bscp) > 1)
66 { m = (char *) emalloc(strlen((const char *)sp->bscp) + 1);
67 sprintf(m, "_%d_", sp->context->sc);
68 if (strcmp((const char *) m, (const char *) sp->bscp) == 0)
70 /* 6.2.0: only prepend scope for inner-blocks,
71 not for top-level locals within a proctype
72 this means that you can no longer use the same name
73 for a global and a (top-level) local variable
77 n = (char *) emalloc(strlen((const char *)sp->name)
78 + strlen((const char *)sp->bscp) + 1);
79 sprintf(n, "%s%s", sp->bscp, sp->name);
80 sp->name = n; /* discard the old memory */
86 { Symbol *sp; Ordered *no;
87 unsigned int h = hash(s);
90 { /* same scope - global refering to global or local to local */
91 for (sp = symtab[h]; sp; sp = sp->next)
92 { if (strcmp(sp->name, s) == 0
93 && samename(sp->context, context)
94 && samename(sp->owner, owner))
95 { return sp; /* found */
98 { /* added 6.0.0: more traditional, scope rule */
99 for (sp = symtab[h]; sp; sp = sp->next)
100 { if (strcmp(sp->name, s) == 0
101 && samename(sp->context, context)
102 && (strcmp((const char *)sp->bscp, CurScope) == 0
103 || strncmp((const char *)sp->bscp, CurScope, strlen((const char *)sp->bscp)) == 0)
104 && samename(sp->owner, owner))
106 if (!samename(sp->owner, owner))
107 { printf("spin: different container %s\n", sp->name);
108 printf(" old: %s\n", sp->owner?sp->owner->name:"--");
109 printf(" new: %s\n", owner?owner->name:"--");
112 return sp; /* found */
115 if (context) /* in proctype, refers to global */
116 for (sp = symtab[h]; sp; sp = sp->next)
117 { if (strcmp(sp->name, s) == 0
119 && samename(sp->owner, owner))
120 { return sp; /* global */
123 sp = (Symbol *) emalloc(sizeof(Symbol));
124 sp->name = (char *) emalloc(strlen(s) + 1);
128 sp->context = context;
129 sp->owner = owner; /* if fld in struct */
130 sp->bscp = (unsigned char *) emalloc(strlen((const char *)CurScope)+1);
131 strcpy((char *)sp->bscp, CurScope);
133 if (NamesNotAdded == 0)
134 { sp->next = symtab[h];
136 no = (Ordered *) emalloc(sizeof(Ordered));
139 last_name = all_names = no;
141 { last_name->next = no;
149 trackvar(Lextok *n, Lextok *m)
150 { Symbol *sp = n->sym;
152 if (!sp) return; /* a structure list */
155 if (m->sym->type != BIT)
157 if (m->sym->type != BYTE)
162 if (m->val != 0 && m->val != 1)
164 if (m->val < 0 || m->val > 256)
165 sp->hidden |= 8; /* ditto byte-equiv */
167 default: /* unknown */
168 sp->hidden |= (4|8); /* not known bit-equiv */
175 runstmnts = nn(ZN, 0, n, runstmnts);
179 checkrun(Symbol *parnm, int posno)
180 { Lextok *n, *now, *v; int i, m;
181 int res = 0; char buf[16], buf2[16];
183 for (n = runstmnts; n; n = n->rgt)
185 if (now->sym != parnm->context)
187 for (v = now->lft, i = 0; v; v = v->rgt, i++)
192 if (m != 0 && m != 1)
194 if (m < 0 || m > 256)
196 } else if (m == NAME)
197 { m = v->lft->sym->type;
204 res |= (4|8); /* unknown */
207 if (!(res&4) || !(res&8))
208 { if (!(verbose&32)) return;
209 strcpy(buf2, (!(res&4))?"bit":"byte");
210 sputtype(buf, parnm->type);
211 i = (int) strlen(buf);
212 while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
213 if (i == 0 || strcmp(buf, buf2) == 0) return;
215 printf("proctype %s, '%s %s' could be declared",
216 parnm->context?parnm->context->name:"", buf, parnm->name);
217 printf(" '%s %s'\n", buf2, parnm->name);
222 trackchanuse(Lextok *m, Lextok *w, int t)
223 { Lextok *n = m; int cnt = 1;
227 && n->lft->sym->type == CHAN)
228 setaccess(n->lft->sym, w?w->sym:ZS, cnt, t);
234 setptype(Lextok *n, int t, Lextok *vis) /* predefined types */
235 { int oln = lineno, cnt = 1; extern int Expand_Ok;
238 { if (n->sym->type && !(n->sym->hidden&32))
239 { lineno = n->ln; Fname = n->fn;
240 fatal("redeclaration of '%s'", n->sym->name);
243 n->sym->type = (short) t;
246 { n->sym->hidden |= (4|8|16); /* formal par */
248 setaccess(n->sym, ZS, cnt, 'F');
251 { if (n->sym->nbits < 0 || n->sym->nbits >= 32)
252 fatal("(%s) has invalid width-field", n->sym->name);
253 if (n->sym->nbits == 0)
254 { n->sym->nbits = 16;
255 non_fatal("unsigned without width-field", 0);
257 } else if (n->sym->nbits > 0)
258 { non_fatal("(%s) only an unsigned can have width-field",
262 { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
263 { n->sym->hidden |= 1;
266 fatal("bit variable (%s) cannot be hidden",
268 } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
269 { n->sym->hidden |= 2;
270 } else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
271 { n->sym->hidden |= 64;
279 && n->sym->ini->ntyp == CHAN)
282 fatal("chan initializer for non-channel %s",
286 if (n->sym->nel <= 0)
287 { lineno = n->ln; Fname = n->fn;
288 non_fatal("bad array size for '%s'", n->sym->name);
296 setonexu(Symbol *sp, int t)
299 if (t == XR || t == XS)
301 && strcmp(sp->xup[t-1]->name, context->name))
302 { printf("error: x[rs] claims from %s and %s\n",
303 sp->xup[t-1]->name, context->name);
304 non_fatal("conflicting claims on chan '%s'",
307 sp->xup[t-1] = context;
312 setallxu(Lextok *n, int t)
315 for (fp = n; fp; fp = fp->rgt)
316 for (tl = fp->lft; tl; tl = tl->rgt)
317 { if (tl->sym->type == STRUCT)
318 setallxu(tl->sym->Slst, t);
319 else if (tl->sym->type == CHAN)
320 setonexu(tl->sym, t);
324 Lextok *Xu_List = (Lextok *) 0;
327 setxus(Lextok *p, int t)
332 if (m_loss && t == XS)
333 { printf("spin: %s:%d, warning, xs tag not compatible with -m (message loss)\n",
334 (p->fn != NULL) ? p->fn->name : "stdin", p->ln);
340 fatal("non-local x[rs] assertion", (char *)0);
342 for (m = p; m; m = m->rgt)
343 { Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok));
344 Xu_new->uiid = p->uiid;
346 Xu_new->lft = m->lft;
347 Xu_new->sym = context;
348 Xu_new->rgt = Xu_List;
352 if (n->sym->type == STRUCT)
353 setallxu(n->sym->Slst, t);
354 else if (n->sym->type == CHAN)
358 lineno = n->ln; Fname = n->fn;
359 non_fatal("xr or xs of non-chan '%s'",
369 int cnt, oln = lineno;
371 if (m) { lineno = m->ln; Fname = m->fn; }
376 { for (n = Mtype; n->rgt; n = n->rgt)
378 n->rgt = m; /* concatenate */
381 for (n = Mtype, cnt = 1; n; n = n->rgt, cnt++) /* syntax check */
382 { if (!n->lft || !n->lft->sym
383 || n->lft->ntyp != NAME
384 || n->lft->lft) /* indexed variable */
385 fatal("bad mtype definition", (char *)0);
388 if (n->lft->sym->type != MTYPE)
389 { n->lft->sym->hidden |= 128; /* is used */
390 n->lft->sym->type = MTYPE;
391 n->lft->sym->ini = nn(ZN,CONST,ZN,ZN);
392 n->lft->sym->ini->val = cnt;
393 } else if (n->lft->sym->ini->val != cnt)
394 non_fatal("name %s appears twice in mtype declaration",
399 fatal("too many mtype elements (>255)", (char *)0);
403 ismtype(char *str) /* name to number */
407 for (n = Mtype; n; n = n->rgt)
408 { if (strcmp(str, n->lft->sym->name) == 0)
416 sputtype(char *foo, int m)
419 case UNSIGNED: strcpy(foo, "unsigned "); break;
420 case BIT: strcpy(foo, "bit "); break;
421 case BYTE: strcpy(foo, "byte "); break;
422 case CHAN: strcpy(foo, "chan "); break;
423 case SHORT: strcpy(foo, "short "); break;
424 case INT: strcpy(foo, "int "); break;
425 case MTYPE: strcpy(foo, "mtype "); break;
426 case STRUCT: strcpy(foo, "struct"); break;
427 case PROCTYPE: strcpy(foo, "proctype"); break;
428 case LABEL: strcpy(foo, "label "); return 0;
429 default: strcpy(foo, "value "); return 0;
439 if (sputtype(buf, m))
450 if (!puttype(sp->type))
454 if (sp->owner) printf("%s.", sp->owner->name);
455 printf("%s", sp->name);
456 if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
458 if (sp->type == CHAN)
459 printf("\t%d", (sp->ini)?sp->ini->val:0);
460 else if (sp->type == STRUCT && sp->Snm != NULL) /* Frank Weil, 2.9.8 */
461 printf("\t%s", sp->Snm->name);
463 printf("\t%d", eval(sp->ini));
466 printf("\t<:struct-field:>");
469 printf("\t<:global:>");
471 printf("\t<%s>", sp->context->name);
473 if (sp->Nid < 0) /* formal parameter */
474 printf("\t<parameter %d>", -(sp->Nid));
475 else if (sp->type == MTYPE)
476 printf("\t<constant>");
477 else if (sp->isarray)
480 printf("\t<variable>");
482 if (sp->type == CHAN && sp->ini)
484 for (m = sp->ini->rgt, i = 0; m; m = m->rgt)
487 for (m = sp->ini->rgt; m; m = m->rgt)
488 { if (m->ntyp == STRUCT)
489 printf("struct %s", m->sym->name);
491 (void) puttype(m->ntyp);
492 if (m->rgt) printf("\t");
496 if (!old_scope_rules)
497 { printf("\t{scope %s}", sp->bscp);
507 for (walk = all_names; walk; walk = walk->next)
514 if (sp->context) printf("%s-", sp->context->name);
515 if (sp->owner) printf("%s.", sp->owner->name);
516 printf("%s", sp->name);
517 if (sp->nel > 1 || sp->isarray == 1) printf("[%d]", sp->nel);
524 { 'A', "exported as run parameter" },
525 { 'F', "imported as proctype parameter" },
526 { 'L', "used as l-value in asgnmnt" },
527 { 'V', "used as r-value in asgnmnt" },
528 { 'P', "polled in receive stmnt" },
529 { 'R', "used as parameter in receive stmnt" },
530 { 'S', "used as parameter in send stmnt" },
531 { 'r', "received from" },
536 chan_check(Symbol *sp)
537 { Access *a; int i, b=0, d;
539 if (verbose&1) goto report; /* -C -g */
541 for (a = sp->access; a; a = a->lnk)
544 else if (a->typ == 's')
546 if (b == 3 || (sp->hidden&16)) /* balanced or formal par */
550 for (i = d = 0; i < (int) (sizeof(xx)/sizeof(struct X)); i++)
552 for (a = sp->access; a; a = a->lnk)
553 if (a->typ == xx[i].typ) b++;
554 if (b == 0) continue; d++;
555 printf("\n\t%s by: ", xx[i].nm);
556 for (a = sp->access; a; a = a->lnk)
557 if (a->typ == xx[i].typ)
558 { printf("%s", a->who->name);
559 if (a->what) printf(" to %s", a->what->name);
560 if (a->cnt) printf(" par %d", a->cnt);
561 if (--b > 0) printf(", ");
564 printf("%s\n", (!d)?"\n\tnever used under this name":"");
571 extern int Caccess, separate;
572 extern short has_code;
574 for (walk = all_names; walk; walk = walk->next)
575 { if (!walk->entry->owner)
576 switch (walk->entry->type) {
578 if (Caccess) chan_check(walk->entry);
586 if ((walk->entry->hidden&128)) /* was: 32 */
590 && !walk->entry->context
593 walk->entry->hidden |= 1; /* auto-hide */
595 if (!(verbose&32) || has_code) continue;
597 printf("spin: %s:0, warning, ", Fname->name);
598 sputtype(buf, walk->entry->type);
599 if (walk->entry->context)
600 printf("proctype %s",
601 walk->entry->context->name);
604 printf(", '%s%s' variable is never used (other than in print stmnts)\n",
605 buf, walk->entry->name);