sym.c 14 KB

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