diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/spin/sym.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/spin/sym.c')
-rwxr-xr-x | sys/src/cmd/spin/sym.c | 534 |
1 files changed, 534 insertions, 0 deletions
diff --git a/sys/src/cmd/spin/sym.c b/sys/src/cmd/spin/sym.c new file mode 100755 index 000000000..0001d2f5f --- /dev/null +++ b/sys/src/cmd/spin/sym.c @@ -0,0 +1,534 @@ +/***** spin: sym.c *****/ + +/* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ +/* All Rights Reserved. This software is for educational purposes only. */ +/* No guarantee whatsoever is expressed or implied by the distribution of */ +/* this code. Permission is given to distribute this code provided that */ +/* this introductory message is not removed and no monies are exchanged. */ +/* Software written by Gerard J. Holzmann. For tool documentation see: */ +/* http://spinroot.com/ */ +/* Send all bug-reports and/or questions to: bugs@spinroot.com */ + +#include "spin.h" +#include "y.tab.h" + +extern Symbol *Fname, *owner; +extern int lineno, depth, verbose, NamesNotAdded, deadvar; +extern short has_xu; + +Symbol *context = ZS; +Ordered *all_names = (Ordered *)0; +int Nid = 0; + +static Ordered *last_name = (Ordered *)0; +static Symbol *symtab[Nhash+1]; + +static int +samename(Symbol *a, Symbol *b) +{ + if (!a && !b) return 1; + if (!a || !b) return 0; + return !strcmp(a->name, b->name); +} + +int +hash(char *s) +{ int h=0; + + while (*s) + { h += *s++; + h <<= 1; + if (h&(Nhash+1)) + h |= 1; + } + return h&Nhash; +} + +Symbol * +lookup(char *s) +{ Symbol *sp; Ordered *no; + int h = hash(s); + + for (sp = symtab[h]; sp; sp = sp->next) + if (strcmp(sp->name, s) == 0 + && samename(sp->context, context) + && samename(sp->owner, owner)) + return sp; /* found */ + + if (context) /* in proctype */ + for (sp = symtab[h]; sp; sp = sp->next) + if (strcmp(sp->name, s) == 0 + && !sp->context + && samename(sp->owner, owner)) + return sp; /* global */ + + sp = (Symbol *) emalloc(sizeof(Symbol)); + sp->name = (char *) emalloc((int) strlen(s) + 1); + strcpy(sp->name, s); + sp->nel = 1; + sp->setat = depth; + sp->context = context; + sp->owner = owner; /* if fld in struct */ + + if (NamesNotAdded == 0) + { sp->next = symtab[h]; + symtab[h] = sp; + no = (Ordered *) emalloc(sizeof(Ordered)); + no->entry = sp; + if (!last_name) + last_name = all_names = no; + else + { last_name->next = no; + last_name = no; + } } + + return sp; +} + +void +trackvar(Lextok *n, Lextok *m) +{ Symbol *sp = n->sym; + + if (!sp) return; /* a structure list */ + switch (m->ntyp) { + case NAME: + if (m->sym->type != BIT) + { sp->hidden |= 4; + if (m->sym->type != BYTE) + sp->hidden |= 8; + } + break; + case CONST: + if (m->val != 0 && m->val != 1) + sp->hidden |= 4; + if (m->val < 0 || m->val > 256) + sp->hidden |= 8; /* ditto byte-equiv */ + break; + default: /* unknown */ + sp->hidden |= (4|8); /* not known bit-equiv */ + } +} + +Lextok *runstmnts = ZN; + +void +trackrun(Lextok *n) +{ + runstmnts = nn(ZN, 0, n, runstmnts); +} + +void +checkrun(Symbol *parnm, int posno) +{ Lextok *n, *now, *v; int i, m; + int res = 0; char buf[16], buf2[16]; + + for (n = runstmnts; n; n = n->rgt) + { now = n->lft; + if (now->sym != parnm->context) + continue; + for (v = now->lft, i = 0; v; v = v->rgt, i++) + if (i == posno) + { m = v->lft->ntyp; + if (m == CONST) + { m = v->lft->val; + if (m != 0 && m != 1) + res |= 4; + if (m < 0 || m > 256) + res |= 8; + } else if (m == NAME) + { m = v->lft->sym->type; + if (m != BIT) + { res |= 4; + if (m != BYTE) + res |= 8; + } + } else + res |= (4|8); /* unknown */ + break; + } } + if (!(res&4) || !(res&8)) + { if (!(verbose&32)) return; + strcpy(buf2, (!(res&4))?"bit":"byte"); + sputtype(buf, parnm->type); + i = (int) strlen(buf); + while (buf[--i] == ' ') buf[i] = '\0'; + if (strcmp(buf, buf2) == 0) return; + prehint(parnm); + printf("proctype %s, '%s %s' could be declared", + parnm->context->name, buf, parnm->name); + printf(" '%s %s'\n", buf2, parnm->name); + } +} + +void +trackchanuse(Lextok *m, Lextok *w, int t) +{ Lextok *n = m; int cnt = 1; + while (n) + { if (n->lft + && n->lft->sym + && n->lft->sym->type == CHAN) + setaccess(n->lft->sym, w?w->sym:ZS, cnt, t); + n = n->rgt; cnt++; + } +} + +void +setptype(Lextok *n, int t, Lextok *vis) /* predefined types */ +{ int oln = lineno, cnt = 1; extern int Expand_Ok; + + while (n) + { if (n->sym->type && !(n->sym->hidden&32)) + { lineno = n->ln; Fname = n->fn; + non_fatal("redeclaration of '%s'", n->sym->name); + lineno = oln; + } + n->sym->type = (short) t; + + if (Expand_Ok) + { n->sym->hidden |= (4|8|16); /* formal par */ + if (t == CHAN) + setaccess(n->sym, ZS, cnt, 'F'); + } + if (t == UNSIGNED) + { if (n->sym->nbits < 0 || n->sym->nbits >= 32) + fatal("(%s) has invalid width-field", n->sym->name); + if (n->sym->nbits == 0) + { n->sym->nbits = 16; + non_fatal("unsigned without width-field", 0); + } + } else if (n->sym->nbits > 0) + { non_fatal("(%s) only an unsigned can have width-field", + n->sym->name); + } + if (vis) + { if (strncmp(vis->sym->name, ":hide:", 6) == 0) + { n->sym->hidden |= 1; + if (t == BIT) + fatal("bit variable (%s) cannot be hidden", + n->sym->name); + } else if (strncmp(vis->sym->name, ":show:", 6) == 0) + { n->sym->hidden |= 2; + } else if (strncmp(vis->sym->name, ":local:", 7) == 0) + { n->sym->hidden |= 64; + } + } + if (t == CHAN) + n->sym->Nid = ++Nid; + else + { n->sym->Nid = 0; + if (n->sym->ini + && n->sym->ini->ntyp == CHAN) + { Fname = n->fn; + lineno = n->ln; + fatal("chan initializer for non-channel %s", + n->sym->name); + } + } + if (n->sym->nel <= 0) + { lineno = n->ln; Fname = n->fn; + non_fatal("bad array size for '%s'", n->sym->name); + lineno = oln; + } + n = n->rgt; cnt++; + } +} + +static void +setonexu(Symbol *sp, int t) +{ + sp->xu |= t; + if (t == XR || t == XS) + { if (sp->xup[t-1] + && strcmp(sp->xup[t-1]->name, context->name)) + { printf("error: x[rs] claims from %s and %s\n", + sp->xup[t-1]->name, context->name); + non_fatal("conflicting claims on chan '%s'", + sp->name); + } + sp->xup[t-1] = context; + } +} + +static void +setallxu(Lextok *n, int t) +{ Lextok *fp, *tl; + + for (fp = n; fp; fp = fp->rgt) + for (tl = fp->lft; tl; tl = tl->rgt) + { if (tl->sym->type == STRUCT) + setallxu(tl->sym->Slst, t); + else if (tl->sym->type == CHAN) + setonexu(tl->sym, t); + } +} + +Lextok *Xu_List = (Lextok *) 0; + +void +setxus(Lextok *p, int t) +{ Lextok *m, *n; + + has_xu = 1; + if (!context) + { lineno = p->ln; + Fname = p->fn; + fatal("non-local x[rs] assertion", (char *)0); + } + for (m = p; m; m = m->rgt) + { Lextok *Xu_new = (Lextok *) emalloc(sizeof(Lextok)); + Xu_new->val = t; + Xu_new->lft = m->lft; + Xu_new->sym = context; + Xu_new->rgt = Xu_List; + Xu_List = Xu_new; + + n = m->lft; + if (n->sym->type == STRUCT) + setallxu(n->sym->Slst, t); + else if (n->sym->type == CHAN) + setonexu(n->sym, t); + else + { int oln = lineno; + lineno = n->ln; Fname = n->fn; + non_fatal("xr or xs of non-chan '%s'", + n->sym->name); + lineno = oln; + } + } +} + +Lextok *Mtype = (Lextok *) 0; + +void +setmtype(Lextok *m) +{ Lextok *n; + int cnt, oln = lineno; + + if (m) { lineno = m->ln; Fname = m->fn; } + + if (!Mtype) + Mtype = m; + else + { for (n = Mtype; n->rgt; n = n->rgt) + ; + n->rgt = m; /* concatenate */ + } + + for (n = Mtype, cnt = 1; n; n = n->rgt, cnt++) /* syntax check */ + { if (!n->lft || !n->lft->sym + || n->lft->ntyp != NAME + || n->lft->lft) /* indexed variable */ + fatal("bad mtype definition", (char *)0); + + /* label the name */ + if (n->lft->sym->type != MTYPE) + { n->lft->sym->hidden |= 128; /* is used */ + n->lft->sym->type = MTYPE; + n->lft->sym->ini = nn(ZN,CONST,ZN,ZN); + n->lft->sym->ini->val = cnt; + } else if (n->lft->sym->ini->val != cnt) + non_fatal("name %s appears twice in mtype declaration", + n->lft->sym->name); + } + lineno = oln; + if (cnt > 256) + fatal("too many mtype elements (>255)", (char *)0); +} + +int +ismtype(char *str) /* name to number */ +{ Lextok *n; + int cnt = 1; + + for (n = Mtype; n; n = n->rgt) + { if (strcmp(str, n->lft->sym->name) == 0) + return cnt; + cnt++; + } + return 0; +} + +int +sputtype(char *foo, int m) +{ + switch (m) { + case UNSIGNED: strcpy(foo, "unsigned "); break; + case BIT: strcpy(foo, "bit "); break; + case BYTE: strcpy(foo, "byte "); break; + case CHAN: strcpy(foo, "chan "); break; + case SHORT: strcpy(foo, "short "); break; + case INT: strcpy(foo, "int "); break; + case MTYPE: strcpy(foo, "mtype "); break; + case STRUCT: strcpy(foo, "struct"); break; + case PROCTYPE: strcpy(foo, "proctype"); break; + case LABEL: strcpy(foo, "label "); return 0; + default: strcpy(foo, "value "); return 0; + } + return 1; +} + + +static int +puttype(int m) +{ char buf[128]; + + if (sputtype(buf, m)) + { printf("%s", buf); + return 1; + } + return 0; +} + +void +symvar(Symbol *sp) +{ Lextok *m; + + if (!puttype(sp->type)) + return; + + printf("\t"); + if (sp->owner) printf("%s.", sp->owner->name); + printf("%s", sp->name); + if (sp->nel > 1) printf("[%d]", sp->nel); + + if (sp->type == CHAN) + printf("\t%d", (sp->ini)?sp->ini->val:0); + else if (sp->type == STRUCT) /* Frank Weil, 2.9.8 */ + printf("\t%s", sp->Snm->name); + else + printf("\t%d", eval(sp->ini)); + + if (sp->owner) + printf("\t<:struct-field:>"); + else + if (!sp->context) + printf("\t<:global:>"); + else + printf("\t<%s>", sp->context->name); + + if (sp->Nid < 0) /* formal parameter */ + printf("\t<parameter %d>", -(sp->Nid)); + else + printf("\t<variable>"); + if (sp->type == CHAN && sp->ini) + { int i; + for (m = sp->ini->rgt, i = 0; m; m = m->rgt) + i++; + printf("\t%d\t", i); + for (m = sp->ini->rgt; m; m = m->rgt) + { if (m->ntyp == STRUCT) + printf("struct %s", m->sym->name); + else + (void) puttype(m->ntyp); + if (m->rgt) printf("\t"); + } + } + printf("\n"); +} + +void +symdump(void) +{ Ordered *walk; + + for (walk = all_names; walk; walk = walk->next) + symvar(walk->entry); +} + +void +chname(Symbol *sp) +{ printf("chan "); + if (sp->context) printf("%s-", sp->context->name); + if (sp->owner) printf("%s.", sp->owner->name); + printf("%s", sp->name); + if (sp->nel > 1) printf("[%d]", sp->nel); + printf("\t"); +} + + +static struct X { + int typ; char *nm; +} xx[] = { + { 'A', "exported as run parameter" }, + { 'F', "imported as proctype parameter" }, + { 'L', "used as l-value in asgnmnt" }, + { 'V', "used as r-value in asgnmnt" }, + { 'P', "polled in receive stmnt" }, + { 'R', "used as parameter in receive stmnt" }, + { 'S', "used as parameter in send stmnt" }, + { 'r', "received from" }, + { 's', "sent to" }, +}; + +static void +chan_check(Symbol *sp) +{ Access *a; int i, b=0, d; + + if (verbose&1) goto report; /* -C -g */ + + for (a = sp->access; a; a = a->lnk) + if (a->typ == 'r') + b |= 1; + else if (a->typ == 's') + b |= 2; + if (b == 3 || (sp->hidden&16)) /* balanced or formal par */ + return; +report: + chname(sp); + for (i = d = 0; i < (int) (sizeof(xx)/sizeof(struct X)); i++) + { b = 0; + for (a = sp->access; a; a = a->lnk) + if (a->typ == xx[i].typ) b++; + if (b == 0) continue; d++; + printf("\n\t%s by: ", xx[i].nm); + for (a = sp->access; a; a = a->lnk) + if (a->typ == xx[i].typ) + { printf("%s", a->who->name); + if (a->what) printf(" to %s", a->what->name); + if (a->cnt) printf(" par %d", a->cnt); + if (--b > 0) printf(", "); + } + } + printf("%s\n", (!d)?"\n\tnever used under this name":""); +} + +void +chanaccess(void) +{ Ordered *walk; + char buf[128]; + extern int Caccess, separate; + extern short has_code; + + for (walk = all_names; walk; walk = walk->next) + { if (!walk->entry->owner) + switch (walk->entry->type) { + case CHAN: + if (Caccess) chan_check(walk->entry); + break; + case MTYPE: + case BIT: + case BYTE: + case SHORT: + case INT: + case UNSIGNED: + if ((walk->entry->hidden&128)) /* was: 32 */ + continue; + + if (!separate + && !walk->entry->context + && !has_code + && deadvar) + walk->entry->hidden |= 1; /* auto-hide */ + + if (!(verbose&32) || has_code) continue; + + printf("spin: warning, %s, ", Fname->name); + sputtype(buf, walk->entry->type); + if (walk->entry->context) + printf("proctype %s", + walk->entry->context->name); + else + printf("global"); + printf(", '%s%s' variable is never used\n", + buf, walk->entry->name); + } } +} |