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
, has_hidden
;
20 Ordered
*all_names
= (Ordered
*)0;
23 Lextok
*Mtype
= (Lextok
*) 0;
25 static Ordered
*last_name
= (Ordered
*)0;
26 static Symbol
*symtab
[Nhash
+1];
27 static Lextok
*runstmnts
= ZN
;
30 samename(Symbol
*a
, Symbol
*b
)
32 if (!a
&& !b
) return 1;
33 if (!a
|| !b
) return 0;
34 return !strcmp(a
->name
, b
->name
);
52 { Symbol
*sp
; Ordered
*no
;
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 */
61 if (context
) /* in proctype */
62 for (sp
= symtab
[h
]; sp
; sp
= sp
->next
)
63 if (strcmp(sp
->name
, s
) == 0
65 && samename(sp
->owner
, owner
))
66 return sp
; /* global */
68 sp
= (Symbol
*) emalloc(sizeof(Symbol
));
69 sp
->name
= (char *) emalloc(strlen(s
) + 1);
73 sp
->context
= context
;
74 sp
->owner
= owner
; /* if fld in struct */
76 if (NamesNotAdded
== 0)
77 { sp
->next
= symtab
[h
];
79 no
= (Ordered
*) emalloc(sizeof(Ordered
));
82 last_name
= all_names
= no
;
84 { last_name
->next
= no
;
92 trackvar(Lextok
*n
, Lextok
*m
)
93 { Symbol
*sp
= n
->sym
;
95 if (!sp
) return; /* a structure list */
98 if (m
->sym
->type
!= BIT
)
100 if (m
->sym
->type
!= BYTE
)
105 if (m
->val
!= 0 && m
->val
!= 1)
107 if (m
->val
< 0 || m
->val
> 256)
108 sp
->hidden
|= 8; /* ditto byte-equiv */
110 default: /* unknown */
111 sp
->hidden
|= (4|8); /* not known bit-equiv */
118 runstmnts
= nn(ZN
, 0, n
, runstmnts
);
122 checkrun(Symbol
*parnm
, int posno
)
123 { Lextok
*n
, *now
, *v
; int i
, m
;
124 int res
= 0; char buf
[16], buf2
[16];
126 for (n
= runstmnts
; n
; n
= n
->rgt
)
128 if (now
->sym
!= parnm
->context
)
130 for (v
= now
->lft
, i
= 0; v
; v
= v
->rgt
, i
++)
135 if (m
!= 0 && m
!= 1)
137 if (m
< 0 || m
> 256)
139 } else if (m
== NAME
)
140 { m
= v
->lft
->sym
->type
;
147 res
|= (4|8); /* unknown */
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;
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
);
165 trackchanuse(Lextok
*m
, Lextok
*w
, int t
)
166 { Lextok
*n
= m
; int cnt
= 1;
170 && n
->lft
->sym
->type
== CHAN
)
171 setaccess(n
->lft
->sym
, w
?w
->sym
:ZS
, cnt
, t
);
177 setptype(Lextok
*n
, int t
, Lextok
*vis
) /* predefined types */
178 { int oln
= lineno
, cnt
= 1; extern int Expand_Ok
;
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
);
186 n
->sym
->type
= (short) t
;
189 { n
->sym
->hidden
|= (4|8|16); /* formal par */
191 setaccess(n
->sym
, ZS
, cnt
, 'F');
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);
200 } else if (n
->sym
->nbits
> 0)
201 { non_fatal("(%s) only an unsigned can have width-field",
205 { if (strncmp(vis
->sym
->name
, ":hide:", (size_t) 6) == 0)
206 { n
->sym
->hidden
|= 1;
209 fatal("bit variable (%s) cannot be hidden",
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;
222 && n
->sym
->ini
->ntyp
== CHAN
)
225 fatal("chan initializer for non-channel %s",
229 if (n
->sym
->nel
<= 0)
230 { lineno
= n
->ln
; Fname
= n
->fn
;
231 non_fatal("bad array size for '%s'", n
->sym
->name
);
239 setonexu(Symbol
*sp
, int t
)
242 if (t
== XR
|| t
== XS
)
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'",
250 sp
->xup
[t
-1] = context
;
255 setallxu(Lextok
*n
, int t
)
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
);
267 Lextok
*Xu_List
= (Lextok
*) 0;
270 setxus(Lextok
*p
, int t
)
277 fatal("non-local x[rs] assertion", (char *)0);
279 for (m
= p
; m
; m
= m
->rgt
)
280 { Lextok
*Xu_new
= (Lextok
*) emalloc(sizeof(Lextok
));
282 Xu_new
->lft
= m
->lft
;
283 Xu_new
->sym
= context
;
284 Xu_new
->rgt
= Xu_List
;
288 if (n
->sym
->type
== STRUCT
)
289 setallxu(n
->sym
->Slst
, t
);
290 else if (n
->sym
->type
== CHAN
)
294 lineno
= n
->ln
; Fname
= n
->fn
;
295 non_fatal("xr or xs of non-chan '%s'",
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
);
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" },
462 chan_check(Symbol
*sp
)
463 { Access
*a
; int i
, b
=0, d
;
465 if (verbose
&1) goto report
; /* -C -g */
467 for (a
= sp
->access
; a
; a
= a
->lnk
)
470 else if (a
->typ
== 's')
472 if (b
== 3 || (sp
->hidden
&16)) /* balanced or formal par */
476 for (i
= d
= 0; i
< (int) (sizeof(xx
)/sizeof(struct X
)); i
++)
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(", ");
490 printf("%s\n", (!d
)?"\n\tnever used under this name":"");
497 extern int Caccess
, separate
;
498 extern short has_code
;
500 for (walk
= all_names
; walk
; walk
= walk
->next
)
501 { if (!walk
->entry
->owner
)
502 switch (walk
->entry
->type
) {
504 if (Caccess
) chan_check(walk
->entry
);
512 if ((walk
->entry
->hidden
&128)) /* was: 32 */
516 && !walk
->entry
->context
519 walk
->entry
->hidden
|= 1; /* auto-hide */
521 if (!(verbose
&32) || has_code
) continue;
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
);
530 printf(", '%s%s' variable is never used\n",
531 buf
, walk
->entry
->name
);
This page took 0.04408 seconds and 5 git commands to generate.