Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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