convert from svn repository: remove tags directory
[lttv.git] / trunk / verif / Spin / Src5.1.6 / sym.c
1 /***** spin: sym.c *****/
2
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 */
11
12 #include "spin.h"
13 #include "y.tab.h"
14
15 extern Symbol *Fname, *owner;
16 extern int lineno, depth, verbose, NamesNotAdded, deadvar, has_hidden;
17 extern short has_xu;
18
19 Symbol *context = ZS;
20 Ordered *all_names = (Ordered *)0;
21 int Nid = 0;
22
23 Lextok *Mtype = (Lextok *) 0;
24
25 static Ordered *last_name = (Ordered *)0;
26 static Symbol *symtab[Nhash+1];
27 static Lextok *runstmnts = ZN;
28
29 static int
30 samename(Symbol *a, Symbol *b)
31 {
32 if (!a && !b) return 1;
33 if (!a || !b) return 0;
34 return !strcmp(a->name, b->name);
35 }
36
37 int
38 hash(char *s)
39 { int h=0;
40
41 while (*s)
42 { h += *s++;
43 h <<= 1;
44 if (h&(Nhash+1))
45 h |= 1;
46 }
47 return h&Nhash;
48 }
49
50 Symbol *
51 lookup(char *s)
52 { Symbol *sp; Ordered *no;
53 int h = hash(s);
54
55 for (sp = symtab[h]; sp; sp = sp->next)
56 if (strcmp(sp->name, s) == 0
57 && samename(sp->context, context)
58 && samename(sp->owner, owner))
59 return sp; /* found */
60
61 if (context) /* in proctype */
62 for (sp = symtab[h]; sp; sp = sp->next)
63 if (strcmp(sp->name, s) == 0
64 && !sp->context
65 && samename(sp->owner, owner))
66 return sp; /* global */
67
68 sp = (Symbol *) emalloc(sizeof(Symbol));
69 sp->name = (char *) emalloc(strlen(s) + 1);
70 strcpy(sp->name, s);
71 sp->nel = 1;
72 sp->setat = depth;
73 sp->context = context;
74 sp->owner = owner; /* if fld in struct */
75
76 if (NamesNotAdded == 0)
77 { sp->next = symtab[h];
78 symtab[h] = sp;
79 no = (Ordered *) emalloc(sizeof(Ordered));
80 no->entry = sp;
81 if (!last_name)
82 last_name = all_names = no;
83 else
84 { last_name->next = no;
85 last_name = no;
86 } }
87
88 return sp;
89 }
90
91 void
92 trackvar(Lextok *n, Lextok *m)
93 { Symbol *sp = n->sym;
94
95 if (!sp) return; /* a structure list */
96 switch (m->ntyp) {
97 case NAME:
98 if (m->sym->type != BIT)
99 { sp->hidden |= 4;
100 if (m->sym->type != BYTE)
101 sp->hidden |= 8;
102 }
103 break;
104 case CONST:
105 if (m->val != 0 && m->val != 1)
106 sp->hidden |= 4;
107 if (m->val < 0 || m->val > 256)
108 sp->hidden |= 8; /* ditto byte-equiv */
109 break;
110 default: /* unknown */
111 sp->hidden |= (4|8); /* not known bit-equiv */
112 }
113 }
114
115 void
116 trackrun(Lextok *n)
117 {
118 runstmnts = nn(ZN, 0, n, runstmnts);
119 }
120
121 void
122 checkrun(Symbol *parnm, int posno)
123 { Lextok *n, *now, *v; int i, m;
124 int res = 0; char buf[16], buf2[16];
125
126 for (n = runstmnts; n; n = n->rgt)
127 { now = n->lft;
128 if (now->sym != parnm->context)
129 continue;
130 for (v = now->lft, i = 0; v; v = v->rgt, i++)
131 if (i == posno)
132 { m = v->lft->ntyp;
133 if (m == CONST)
134 { m = v->lft->val;
135 if (m != 0 && m != 1)
136 res |= 4;
137 if (m < 0 || m > 256)
138 res |= 8;
139 } else if (m == NAME)
140 { m = v->lft->sym->type;
141 if (m != BIT)
142 { res |= 4;
143 if (m != BYTE)
144 res |= 8;
145 }
146 } else
147 res |= (4|8); /* unknown */
148 break;
149 } }
150 if (!(res&4) || !(res&8))
151 { if (!(verbose&32)) return;
152 strcpy(buf2, (!(res&4))?"bit":"byte");
153 sputtype(buf, parnm->type);
154 i = (int) strlen(buf);
155 while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
156 if (i == 0 || strcmp(buf, buf2) == 0) return;
157 prehint(parnm);
158 printf("proctype %s, '%s %s' could be declared",
159 parnm->context?parnm->context->name:"", buf, parnm->name);
160 printf(" '%s %s'\n", buf2, parnm->name);
161 }
162 }
163
164 void
165 trackchanuse(Lextok *m, Lextok *w, int t)
166 { Lextok *n = m; int cnt = 1;
167 while (n)
168 { if (n->lft
169 && n->lft->sym
170 && n->lft->sym->type == CHAN)
171 setaccess(n->lft->sym, w?w->sym:ZS, cnt, t);
172 n = n->rgt; cnt++;
173 }
174 }
175
176 void
177 setptype(Lextok *n, int t, Lextok *vis) /* predefined types */
178 { int oln = lineno, cnt = 1; extern int Expand_Ok;
179
180 while (n)
181 { if (n->sym->type && !(n->sym->hidden&32))
182 { lineno = n->ln; Fname = n->fn;
183 non_fatal("redeclaration of '%s'", n->sym->name);
184 lineno = oln;
185 }
186 n->sym->type = (short) t;
187
188 if (Expand_Ok)
189 { n->sym->hidden |= (4|8|16); /* formal par */
190 if (t == CHAN)
191 setaccess(n->sym, ZS, cnt, 'F');
192 }
193 if (t == UNSIGNED)
194 { if (n->sym->nbits < 0 || n->sym->nbits >= 32)
195 fatal("(%s) has invalid width-field", n->sym->name);
196 if (n->sym->nbits == 0)
197 { n->sym->nbits = 16;
198 non_fatal("unsigned without width-field", 0);
199 }
200 } else if (n->sym->nbits > 0)
201 { non_fatal("(%s) only an unsigned can have width-field",
202 n->sym->name);
203 }
204 if (vis)
205 { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
206 { n->sym->hidden |= 1;
207 has_hidden++;
208 if (t == BIT)
209 fatal("bit variable (%s) cannot be hidden",
210 n->sym->name);
211 } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
212 { n->sym->hidden |= 2;
213 } else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
214 { n->sym->hidden |= 64;
215 }
216 }
217 if (t == CHAN)
218 n->sym->Nid = ++Nid;
219 else
220 { n->sym->Nid = 0;
221 if (n->sym->ini
222 && n->sym->ini->ntyp == CHAN)
223 { Fname = n->fn;
224 lineno = n->ln;
225 fatal("chan initializer for non-channel %s",
226 n->sym->name);
227 }
228 }
229 if (n->sym->nel <= 0)
230 { lineno = n->ln; Fname = n->fn;
231 non_fatal("bad array size for '%s'", n->sym->name);
232 lineno = oln;
233 }
234 n = n->rgt; cnt++;
235 }
236 }
237
238 static void
239 setonexu(Symbol *sp, int t)
240 {
241 sp->xu |= t;
242 if (t == XR || t == XS)
243 { if (sp->xup[t-1]
244 && strcmp(sp->xup[t-1]->name, context->name))
245 { printf("error: x[rs] claims from %s and %s\n",
246 sp->xup[t-1]->name, context->name);
247 non_fatal("conflicting claims on chan '%s'",
248 sp->name);
249 }
250 sp->xup[t-1] = context;
251 }
252 }
253
254 static void
255 setallxu(Lextok *n, int t)
256 { Lextok *fp, *tl;
257
258 for (fp = n; fp; fp = fp->rgt)
259 for (tl = fp->lft; tl; tl = tl->rgt)
260 { if (tl->sym->type == STRUCT)
261 setallxu(tl->sym->Slst, t);
262 else if (tl->sym->type == CHAN)
263 setonexu(tl->sym, t);
264 }
265 }
266
267 Lextok *Xu_List = (Lextok *) 0;
268
269 void
270 setxus(Lextok *p, int t)
271 { Lextok *m, *n;
272
273 has_xu = 1;
274 if (!context)
275 { lineno = p->ln;
276 Fname = p->fn;
277 fatal("non-local x[rs] assertion", (char *)0);
278 }
279 for (m = p; m; m = m->rgt)
280 { Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok));
281 Xu_new->val = t;
282 Xu_new->lft = m->lft;
283 Xu_new->sym = context;
284 Xu_new->rgt = Xu_List;
285 Xu_List = Xu_new;
286
287 n = m->lft;
288 if (n->sym->type == STRUCT)
289 setallxu(n->sym->Slst, t);
290 else if (n->sym->type == CHAN)
291 setonexu(n->sym, t);
292 else
293 { int oln = lineno;
294 lineno = n->ln; Fname = n->fn;
295 non_fatal("xr or xs of non-chan '%s'",
296 n->sym->name);
297 lineno = oln;
298 }
299 }
300 }
301
302 void
303 setmtype(Lextok *m)
304 { Lextok *n;
305 int cnt, oln = lineno;
306
307 if (m) { lineno = m->ln; Fname = m->fn; }
308
309 if (!Mtype)
310 Mtype = m;
311 else
312 { for (n = Mtype; n->rgt; n = n->rgt)
313 ;
314 n->rgt = m; /* concatenate */
315 }
316
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);
322
323 /* label the name */
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",
331 n->lft->sym->name);
332 }
333 lineno = oln;
334 if (cnt > 256)
335 fatal("too many mtype elements (>255)", (char *)0);
336 }
337
338 int
339 ismtype(char *str) /* name to number */
340 { Lextok *n;
341 int cnt = 1;
342
343 for (n = Mtype; n; n = n->rgt)
344 { if (strcmp(str, n->lft->sym->name) == 0)
345 return cnt;
346 cnt++;
347 }
348 return 0;
349 }
350
351 int
352 sputtype(char *foo, int m)
353 {
354 switch (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;
366 }
367 return 1;
368 }
369
370
371 static int
372 puttype(int m)
373 { char buf[128];
374
375 if (sputtype(buf, m))
376 { printf("%s", buf);
377 return 1;
378 }
379 return 0;
380 }
381
382 void
383 symvar(Symbol *sp)
384 { Lextok *m;
385
386 if (!puttype(sp->type))
387 return;
388
389 printf("\t");
390 if (sp->owner) printf("%s.", sp->owner->name);
391 printf("%s", sp->name);
392 if (sp->nel > 1) printf("[%d]", sp->nel);
393
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);
398 else
399 printf("\t%d", eval(sp->ini));
400
401 if (sp->owner)
402 printf("\t<:struct-field:>");
403 else
404 if (!sp->context)
405 printf("\t<:global:>");
406 else
407 printf("\t<%s>", sp->context->name);
408
409 if (sp->Nid < 0) /* formal parameter */
410 printf("\t<parameter %d>", -(sp->Nid));
411 else
412 printf("\t<variable>");
413 if (sp->type == CHAN && sp->ini)
414 { int i;
415 for (m = sp->ini->rgt, i = 0; m; m = m->rgt)
416 i++;
417 printf("\t%d\t", i);
418 for (m = sp->ini->rgt; m; m = m->rgt)
419 { if (m->ntyp == STRUCT)
420 printf("struct %s", m->sym->name);
421 else
422 (void) puttype(m->ntyp);
423 if (m->rgt) printf("\t");
424 }
425 }
426 printf("\n");
427 }
428
429 void
430 symdump(void)
431 { Ordered *walk;
432
433 for (walk = all_names; walk; walk = walk->next)
434 symvar(walk->entry);
435 }
436
437 void
438 chname(Symbol *sp)
439 { printf("chan ");
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);
444 printf("\t");
445 }
446
447 static struct X {
448 int typ; char *nm;
449 } xx[] = {
450 { 'A', "exported as run parameter" },
451 { 'F', "imported as proctype parameter" },
452 { 'L', "used as l-value in asgnmnt" },
453 { 'V', "used as r-value in asgnmnt" },
454 { 'P', "polled in receive stmnt" },
455 { 'R', "used as parameter in receive stmnt" },
456 { 'S', "used as parameter in send stmnt" },
457 { 'r', "received from" },
458 { 's', "sent to" },
459 };
460
461 static void
462 chan_check(Symbol *sp)
463 { Access *a; int i, b=0, d;
464
465 if (verbose&1) goto report; /* -C -g */
466
467 for (a = sp->access; a; a = a->lnk)
468 if (a->typ == 'r')
469 b |= 1;
470 else if (a->typ == 's')
471 b |= 2;
472 if (b == 3 || (sp->hidden&16)) /* balanced or formal par */
473 return;
474 report:
475 chname(sp);
476 for (i = d = 0; i < (int) (sizeof(xx)/sizeof(struct X)); i++)
477 { b = 0;
478 for (a = sp->access; a; a = a->lnk)
479 if (a->typ == xx[i].typ) b++;
480 if (b == 0) continue; d++;
481 printf("\n\t%s by: ", xx[i].nm);
482 for (a = sp->access; a; a = a->lnk)
483 if (a->typ == xx[i].typ)
484 { printf("%s", a->who->name);
485 if (a->what) printf(" to %s", a->what->name);
486 if (a->cnt) printf(" par %d", a->cnt);
487 if (--b > 0) printf(", ");
488 }
489 }
490 printf("%s\n", (!d)?"\n\tnever used under this name":"");
491 }
492
493 void
494 chanaccess(void)
495 { Ordered *walk;
496 char buf[128];
497 extern int Caccess, separate;
498 extern short has_code;
499
500 for (walk = all_names; walk; walk = walk->next)
501 { if (!walk->entry->owner)
502 switch (walk->entry->type) {
503 case CHAN:
504 if (Caccess) chan_check(walk->entry);
505 break;
506 case MTYPE:
507 case BIT:
508 case BYTE:
509 case SHORT:
510 case INT:
511 case UNSIGNED:
512 if ((walk->entry->hidden&128)) /* was: 32 */
513 continue;
514
515 if (!separate
516 && !walk->entry->context
517 && !has_code
518 && deadvar)
519 walk->entry->hidden |= 1; /* auto-hide */
520
521 if (!(verbose&32) || has_code) continue;
522
523 printf("spin: warning, %s, ", Fname->name);
524 sputtype(buf, walk->entry->type);
525 if (walk->entry->context)
526 printf("proctype %s",
527 walk->entry->context->name);
528 else
529 printf("global");
530 printf(", '%s%s' variable is never used\n",
531 buf, walk->entry->name);
532 } }
533 }
This page took 0.048116 seconds and 4 git commands to generate.