1 /***** spin: sym.c *****/
3 /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
4 /* All Rights Reserved. This software is for educational purposes only. */
5 /* No guarantee whatsoever is expressed or implied by the distribution of */
6 /* this code. Permission is given to distribute this code provided that */
7 /* this introductory message is not removed and no monies are exchanged. */
8 /* Software written by Gerard J. Holzmann. For tool documentation see: */
9 /* http://spinroot.com/ */
10 /* Send all bug-reports and/or questions to: bugs@spinroot.com */
15 extern Symbol *Fname, *owner;
16 extern int lineno, depth, verbose, NamesNotAdded, deadvar;
20 Ordered *all_names = (Ordered *)0;
23 static Ordered *last_name = (Ordered *)0;
24 static Symbol *symtab[Nhash+1];
27 samename(Symbol *a, Symbol *b)
29 if (!a && !b) return 1;
30 if (!a || !b) return 0;
31 return !strcmp(a->name, b->name);
49 { Symbol *sp; Ordered *no;
52 for (sp = symtab[h]; sp; sp = sp->next)
53 if (strcmp(sp->name, s) == 0
54 && samename(sp->context, context)
55 && samename(sp->owner, owner))
56 return sp; /* found */
58 if (context) /* in proctype */
59 for (sp = symtab[h]; sp; sp = sp->next)
60 if (strcmp(sp->name, s) == 0
62 && samename(sp->owner, owner))
63 return sp; /* global */
65 sp = (Symbol *) emalloc(sizeof(Symbol));
66 sp->name = (char *) emalloc((int) strlen(s) + 1);
70 sp->context = context;
71 sp->owner = owner; /* if fld in struct */
73 if (NamesNotAdded == 0)
74 { sp->next = symtab[h];
76 no = (Ordered *) emalloc(sizeof(Ordered));
79 last_name = all_names = no;
81 { last_name->next = no;
89 trackvar(Lextok *n, Lextok *m)
90 { Symbol *sp = n->sym;
92 if (!sp) return; /* a structure list */
95 if (m->sym->type != BIT)
97 if (m->sym->type != BYTE)
102 if (m->val != 0 && m->val != 1)
104 if (m->val < 0 || m->val > 256)
105 sp->hidden |= 8; /* ditto byte-equiv */
107 default: /* unknown */
108 sp->hidden |= (4|8); /* not known bit-equiv */
112 Lextok *runstmnts = ZN;
117 runstmnts = nn(ZN, 0, n, runstmnts);
121 checkrun(Symbol *parnm, int posno)
122 { Lextok *n, *now, *v; int i, m;
123 int res = 0; char buf[16], buf2[16];
125 for (n = runstmnts; n; n = n->rgt)
127 if (now->sym != parnm->context)
129 for (v = now->lft, i = 0; v; v = v->rgt, i++)
134 if (m != 0 && m != 1)
136 if (m < 0 || m > 256)
138 } else if (m == NAME)
139 { m = v->lft->sym->type;
146 res |= (4|8); /* unknown */
149 if (!(res&4) || !(res&8))
150 { if (!(verbose&32)) return;
151 strcpy(buf2, (!(res&4))?"bit":"byte");
152 sputtype(buf, parnm->type);
153 i = (int) strlen(buf);
154 while (buf[--i] == ' ') buf[i] = '\0';
155 if (strcmp(buf, buf2) == 0) return;
157 printf("proctype %s, '%s %s' could be declared",
158 parnm->context->name, buf, parnm->name);
159 printf(" '%s %s'\n", buf2, parnm->name);
164 trackchanuse(Lextok *m, Lextok *w, int t)
165 { Lextok *n = m; int cnt = 1;
169 && n->lft->sym->type == CHAN)
170 setaccess(n->lft->sym, w?w->sym:ZS, cnt, t);
176 setptype(Lextok *n, int t, Lextok *vis) /* predefined types */
177 { int oln = lineno, cnt = 1; extern int Expand_Ok;
180 { if (n->sym->type && !(n->sym->hidden&32))
181 { lineno = n->ln; Fname = n->fn;
182 non_fatal("redeclaration of '%s'", n->sym->name);
185 n->sym->type = (short) t;
188 { n->sym->hidden |= (4|8|16); /* formal par */
190 setaccess(n->sym, ZS, cnt, 'F');
193 { if (n->sym->nbits < 0 || n->sym->nbits >= 32)
194 fatal("(%s) has invalid width-field", n->sym->name);
195 if (n->sym->nbits == 0)
196 { n->sym->nbits = 16;
197 non_fatal("unsigned without width-field", 0);
199 } else if (n->sym->nbits > 0)
200 { non_fatal("(%s) only an unsigned can have width-field",
204 { if (strncmp(vis->sym->name, ":hide:", 6) == 0)
205 { n->sym->hidden |= 1;
207 fatal("bit variable (%s) cannot be hidden",
209 } else if (strncmp(vis->sym->name, ":show:", 6) == 0)
210 { n->sym->hidden |= 2;
211 } else if (strncmp(vis->sym->name, ":local:", 7) == 0)
212 { n->sym->hidden |= 64;
220 && n->sym->ini->ntyp == CHAN)
223 fatal("chan initializer for non-channel %s",
227 if (n->sym->nel <= 0)
228 { lineno = n->ln; Fname = n->fn;
229 non_fatal("bad array size for '%s'", n->sym->name);
237 setonexu(Symbol *sp, int t)
240 if (t == XR || t == XS)
242 && strcmp(sp->xup[t-1]->name, context->name))
243 { printf("error: x[rs] claims from %s and %s\n",
244 sp->xup[t-1]->name, context->name);
245 non_fatal("conflicting claims on chan '%s'",
248 sp->xup[t-1] = context;
253 setallxu(Lextok *n, int t)
256 for (fp = n; fp; fp = fp->rgt)
257 for (tl = fp->lft; tl; tl = tl->rgt)
258 { if (tl->sym->type == STRUCT)
259 setallxu(tl->sym->Slst, t);
260 else if (tl->sym->type == CHAN)
261 setonexu(tl->sym, t);
265 Lextok *Xu_List = (Lextok *) 0;
268 setxus(Lextok *p, int t)
275 fatal("non-local x[rs] assertion", (char *)0);
277 for (m = p; m; m = m->rgt)
278 { Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok));
280 Xu_new->lft = m->lft;
281 Xu_new->sym = context;
282 Xu_new->rgt = Xu_List;
286 if (n->sym->type == STRUCT)
287 setallxu(n->sym->Slst, t);
288 else if (n->sym->type == CHAN)
292 lineno = n->ln; Fname = n->fn;
293 non_fatal("xr or xs of non-chan '%s'",
300 Lextok *Mtype = (Lextok *) 0;
305 int cnt, oln = lineno;
307 if (m) { lineno = m->ln; Fname = m->fn; }
312 { for (n = Mtype; n->rgt; n = n->rgt)
314 n->rgt = m; /* concatenate */
317 for (n = Mtype, cnt = 1; n; n = n->rgt, cnt++) /* syntax check */
318 { if (!n->lft || !n->lft->sym
319 || n->lft->ntyp != NAME
320 || n->lft->lft) /* indexed variable */
321 fatal("bad mtype definition", (char *)0);
324 if (n->lft->sym->type != MTYPE)
325 { n->lft->sym->hidden |= 128; /* is used */
326 n->lft->sym->type = MTYPE;
327 n->lft->sym->ini = nn(ZN,CONST,ZN,ZN);
328 n->lft->sym->ini->val = cnt;
329 } else if (n->lft->sym->ini->val != cnt)
330 non_fatal("name %s appears twice in mtype declaration",
335 fatal("too many mtype elements (>255)", (char *)0);
339 ismtype(char *str) /* name to number */
343 for (n = Mtype; n; n = n->rgt)
344 { if (strcmp(str, n->lft->sym->name) == 0)
352 sputtype(char *foo, int m)
355 case UNSIGNED: strcpy(foo, "unsigned "); break;
356 case BIT: strcpy(foo, "bit "); break;
357 case BYTE: strcpy(foo, "byte "); break;
358 case CHAN: strcpy(foo, "chan "); break;
359 case SHORT: strcpy(foo, "short "); break;
360 case INT: strcpy(foo, "int "); break;
361 case MTYPE: strcpy(foo, "mtype "); break;
362 case STRUCT: strcpy(foo, "struct"); break;
363 case PROCTYPE: strcpy(foo, "proctype"); break;
364 case LABEL: strcpy(foo, "label "); return 0;
365 default: strcpy(foo, "value "); return 0;
375 if (sputtype(buf, m))
386 if (!puttype(sp->type))
390 if (sp->owner) printf("%s.", sp->owner->name);
391 printf("%s", sp->name);
392 if (sp->nel > 1) printf("[%d]", sp->nel);
394 if (sp->type == CHAN)
395 printf("\t%d", (sp->ini)?sp->ini->val:0);
396 else if (sp->type == STRUCT) /* Frank Weil, 2.9.8 */
397 printf("\t%s", sp->Snm->name);
399 printf("\t%d", eval(sp->ini));
402 printf("\t<:struct-field:>");
405 printf("\t<:global:>");
407 printf("\t<%s>", sp->context->name);
409 if (sp->Nid < 0) /* formal parameter */
410 printf("\t<parameter %d>", -(sp->Nid));
412 printf("\t<variable>");
413 if (sp->type == CHAN && sp->ini)
415 for (m = sp->ini->rgt, i = 0; m; m = m->rgt)
418 for (m = sp->ini->rgt; m; m = m->rgt)
419 { if (m->ntyp == STRUCT)
420 printf("struct %s", m->sym->name);
422 (void) puttype(m->ntyp);
423 if (m->rgt) printf("\t");
433 for (walk = all_names; walk; walk = walk->next)
440 if (sp->context) printf("%s-", sp->context->name);
441 if (sp->owner) printf("%s.", sp->owner->name);
442 printf("%s", sp->name);
443 if (sp->nel > 1) printf("[%d]", sp->nel);
451 { 'A', "exported as run parameter" },
452 { 'F', "imported as proctype parameter" },
453 { 'L', "used as l-value in asgnmnt" },
454 { 'V', "used as r-value in asgnmnt" },
455 { 'P', "polled in receive stmnt" },
456 { 'R', "used as parameter in receive stmnt" },
457 { 'S', "used as parameter in send stmnt" },
458 { 'r', "received from" },
463 chan_check(Symbol *sp)
464 { Access *a; int i, b=0, d;
466 if (verbose&1) goto report; /* -C -g */
468 for (a = sp->access; a; a = a->lnk)
471 else if (a->typ == 's')
473 if (b == 3 || (sp->hidden&16)) /* balanced or formal par */
477 for (i = d = 0; i < (int) (sizeof(xx)/sizeof(struct X)); i++)
479 for (a = sp->access; a; a = a->lnk)
480 if (a->typ == xx[i].typ) b++;
481 if (b == 0) continue; d++;
482 printf("\n\t%s by: ", xx[i].nm);
483 for (a = sp->access; a; a = a->lnk)
484 if (a->typ == xx[i].typ)
485 { printf("%s", a->who->name);
486 if (a->what) printf(" to %s", a->what->name);
487 if (a->cnt) printf(" par %d", a->cnt);
488 if (--b > 0) printf(", ");
491 printf("%s\n", (!d)?"\n\tnever used under this name":"");
498 extern int Caccess, separate;
499 extern short has_code;
501 for (walk = all_names; walk; walk = walk->next)
502 { if (!walk->entry->owner)
503 switch (walk->entry->type) {
505 if (Caccess) chan_check(walk->entry);
513 if ((walk->entry->hidden&128)) /* was: 32 */
517 && !walk->entry->context
520 walk->entry->hidden |= 1; /* auto-hide */
522 if (!(verbose&32) || has_code) continue;
524 printf("spin: warning, %s, ", Fname->name);
525 sputtype(buf, walk->entry->type);
526 if (walk->entry->context)
527 printf("proctype %s",
528 walk->entry->context->name);
531 printf(", '%s%s' variable is never used\n",
532 buf, walk->entry->name);