structs.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  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: structs.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. typedef struct UType {
  21. Symbol *nm; /* name of the type */
  22. Lextok *cn; /* contents */
  23. struct UType *nxt; /* linked list */
  24. } UType;
  25. extern Symbol *Fname;
  26. extern int lineno, depth, Expand_Ok, has_hidden, in_for;
  27. Symbol *owner;
  28. static UType *Unames = 0;
  29. static UType *Pnames = 0;
  30. static Lextok *cpnn(Lextok *, int, int, int);
  31. extern void sr_mesg(FILE *, int, int);
  32. void
  33. setuname(Lextok *n)
  34. { UType *tmp;
  35. if (!owner)
  36. fatal("illegal reference inside typedef", (char *) 0);
  37. for (tmp = Unames; tmp; tmp = tmp->nxt)
  38. if (!strcmp(owner->name, tmp->nm->name))
  39. { non_fatal("typename %s was defined before",
  40. tmp->nm->name);
  41. return;
  42. }
  43. tmp = (UType *) emalloc(sizeof(UType));
  44. tmp->nm = owner;
  45. tmp->cn = n;
  46. tmp->nxt = Unames;
  47. Unames = tmp;
  48. }
  49. static void
  50. putUname(FILE *fd, UType *tmp)
  51. { Lextok *fp, *tl;
  52. if (!tmp) return;
  53. putUname(fd, tmp->nxt); /* postorder */
  54. fprintf(fd, "struct %s { /* user defined type */\n",
  55. tmp->nm->name);
  56. for (fp = tmp->cn; fp; fp = fp->rgt)
  57. for (tl = fp->lft; tl; tl = tl->rgt)
  58. typ2c(tl->sym);
  59. fprintf(fd, "};\n");
  60. }
  61. void
  62. putunames(FILE *fd)
  63. {
  64. putUname(fd, Unames);
  65. }
  66. int
  67. isutype(char *t)
  68. { UType *tmp;
  69. for (tmp = Unames; tmp; tmp = tmp->nxt)
  70. { if (!strcmp(t, tmp->nm->name))
  71. return 1;
  72. }
  73. return 0;
  74. }
  75. Lextok *
  76. getuname(Symbol *t)
  77. { UType *tmp;
  78. for (tmp = Unames; tmp; tmp = tmp->nxt)
  79. { if (!strcmp(t->name, tmp->nm->name))
  80. return tmp->cn;
  81. }
  82. fatal("%s is not a typename", t->name);
  83. return (Lextok *)0;
  84. }
  85. void
  86. setutype(Lextok *p, Symbol *t, Lextok *vis) /* user-defined types */
  87. { int oln = lineno;
  88. Symbol *ofn = Fname;
  89. Lextok *m, *n;
  90. m = getuname(t);
  91. for (n = p; n; n = n->rgt)
  92. { lineno = n->ln;
  93. Fname = n->fn;
  94. if (n->sym->type)
  95. fatal("redeclaration of '%s'", n->sym->name);
  96. if (n->sym->nbits > 0)
  97. non_fatal("(%s) only an unsigned can have width-field",
  98. n->sym->name);
  99. if (Expand_Ok)
  100. n->sym->hidden |= (4|8|16); /* formal par */
  101. if (vis)
  102. { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
  103. { n->sym->hidden |= 1;
  104. has_hidden++;
  105. } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
  106. n->sym->hidden |= 2;
  107. else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
  108. n->sym->hidden |= 64;
  109. }
  110. n->sym->type = STRUCT; /* classification */
  111. n->sym->Slst = m; /* structure itself */
  112. n->sym->Snm = t; /* name of typedef */
  113. n->sym->Nid = 0; /* this is no chan */
  114. n->sym->hidden |= 4;
  115. if (n->sym->nel <= 0)
  116. non_fatal("bad array size for '%s'", n->sym->name);
  117. }
  118. lineno = oln;
  119. Fname = ofn;
  120. }
  121. static Symbol *
  122. do_same(Lextok *n, Symbol *v, int xinit)
  123. { Lextok *tmp, *fp, *tl;
  124. int ix = eval(n->lft);
  125. int oln = lineno;
  126. Symbol *ofn = Fname;
  127. lineno = n->ln;
  128. Fname = n->fn;
  129. /* n->sym->type == STRUCT
  130. * index: n->lft
  131. * subfields: n->rgt
  132. * structure template: n->sym->Slst
  133. * runtime values: n->sym->Sval
  134. */
  135. if (xinit) ini_struct(v); /* once, at top level */
  136. if (ix >= v->nel || ix < 0)
  137. { printf("spin: indexing %s[%d] - size is %d\n",
  138. v->name, ix, v->nel);
  139. fatal("indexing error \'%s\'", v->name);
  140. }
  141. if (!n->rgt || !n->rgt->lft)
  142. { non_fatal("no subfields %s", v->name); /* i.e., wants all */
  143. lineno = oln; Fname = ofn;
  144. return ZS;
  145. }
  146. if (n->rgt->ntyp != '.')
  147. { printf("bad subfield type %d\n", n->rgt->ntyp);
  148. alldone(1);
  149. }
  150. tmp = n->rgt->lft;
  151. if (tmp->ntyp != NAME && tmp->ntyp != TYPE)
  152. { printf("bad subfield entry %d\n", tmp->ntyp);
  153. alldone(1);
  154. }
  155. for (fp = v->Sval[ix]; fp; fp = fp->rgt)
  156. for (tl = fp->lft; tl; tl = tl->rgt)
  157. if (!strcmp(tl->sym->name, tmp->sym->name))
  158. { lineno = oln; Fname = ofn;
  159. return tl->sym;
  160. }
  161. fatal("cannot locate subfield %s", tmp->sym->name);
  162. return ZS;
  163. }
  164. int
  165. Rval_struct(Lextok *n, Symbol *v, int xinit) /* n varref, v valref */
  166. { Symbol *tl;
  167. Lextok *tmp;
  168. int ix;
  169. if (!n || !(tl = do_same(n, v, xinit)))
  170. return 0;
  171. tmp = n->rgt->lft;
  172. if (tmp->sym->type == STRUCT)
  173. { return Rval_struct(tmp, tl, 0);
  174. } else if (tmp->rgt)
  175. fatal("non-zero 'rgt' on non-structure", 0);
  176. ix = eval(tmp->lft);
  177. /* printf("%d: ix: %d (%d) %d\n", depth, ix, tl->nel, tl->val[ix]); */
  178. if (ix >= tl->nel || ix < 0)
  179. fatal("indexing error \'%s\'", tl->name);
  180. return cast_val(tl->type, tl->val[ix], tl->nbits);
  181. }
  182. int
  183. Lval_struct(Lextok *n, Symbol *v, int xinit, int a) /* a = assigned value */
  184. { Symbol *tl;
  185. Lextok *tmp;
  186. int ix;
  187. if (!(tl = do_same(n, v, xinit)))
  188. return 1;
  189. tmp = n->rgt->lft;
  190. if (tmp->sym->type == STRUCT)
  191. return Lval_struct(tmp, tl, 0, a);
  192. else if (tmp->rgt)
  193. fatal("non-zero 'rgt' on non-structure", 0);
  194. ix = eval(tmp->lft);
  195. if (ix >= tl->nel || ix < 0)
  196. fatal("indexing error \'%s\'", tl->name);
  197. if (tl->nbits > 0)
  198. a = (a & ((1<<tl->nbits)-1));
  199. if (a != tl->val[ix])
  200. { tl->val[ix] = a;
  201. tl->setat = depth;
  202. }
  203. return 1;
  204. }
  205. int
  206. Cnt_flds(Lextok *m)
  207. { Lextok *fp, *tl, *n;
  208. int cnt = 0;
  209. if (m->ntyp == ',')
  210. { n = m;
  211. goto is_lst;
  212. }
  213. if (!m->sym || m->ntyp != STRUCT)
  214. return 1;
  215. n = getuname(m->sym);
  216. is_lst:
  217. for (fp = n; fp; fp = fp->rgt)
  218. for (tl = fp->lft; tl; tl = tl->rgt)
  219. { if (tl->sym->type == STRUCT)
  220. { if (tl->sym->nel > 1 || tl->sym->isarray)
  221. fatal("array of structures in param list, %s",
  222. tl->sym->name);
  223. cnt += Cnt_flds(tl->sym->Slst);
  224. } else
  225. cnt += tl->sym->nel;
  226. }
  227. return cnt;
  228. }
  229. int
  230. Sym_typ(Lextok *t)
  231. { Symbol *s = t->sym;
  232. if (!s) return 0;
  233. if (s->type != STRUCT)
  234. return s->type;
  235. if (!t->rgt
  236. || t->rgt->ntyp != '.' /* gh: had ! in wrong place */
  237. || !t->rgt->lft)
  238. return STRUCT; /* not a field reference */
  239. return Sym_typ(t->rgt->lft);
  240. }
  241. int
  242. Width_set(int *wdth, int i, Lextok *n)
  243. { Lextok *fp, *tl;
  244. int j = i, k;
  245. for (fp = n; fp; fp = fp->rgt)
  246. for (tl = fp->lft; tl; tl = tl->rgt)
  247. { if (tl->sym->type == STRUCT)
  248. j = Width_set(wdth, j, tl->sym->Slst);
  249. else
  250. { for (k = 0; k < tl->sym->nel; k++, j++)
  251. wdth[j] = tl->sym->type;
  252. } }
  253. return j;
  254. }
  255. void
  256. ini_struct(Symbol *s)
  257. { int i; Lextok *fp, *tl;
  258. if (s->type != STRUCT) /* last step */
  259. { (void) checkvar(s, 0);
  260. return;
  261. }
  262. if (s->Sval == (Lextok **) 0)
  263. { s->Sval = (Lextok **) emalloc(s->nel * sizeof(Lextok *));
  264. for (i = 0; i < s->nel; i++)
  265. { s->Sval[i] = cpnn(s->Slst, 1, 1, 1);
  266. for (fp = s->Sval[i]; fp; fp = fp->rgt)
  267. for (tl = fp->lft; tl; tl = tl->rgt)
  268. ini_struct(tl->sym);
  269. } }
  270. }
  271. static Lextok *
  272. cpnn(Lextok *s, int L, int R, int S)
  273. { Lextok *d; extern int Nid;
  274. if (!s) return ZN;
  275. d = (Lextok *) emalloc(sizeof(Lextok));
  276. d->uiid = s->uiid;
  277. d->ntyp = s->ntyp;
  278. d->val = s->val;
  279. d->ln = s->ln;
  280. d->fn = s->fn;
  281. d->sym = s->sym;
  282. if (L) d->lft = cpnn(s->lft, 1, 1, S);
  283. if (R) d->rgt = cpnn(s->rgt, 1, 1, S);
  284. if (S && s->sym)
  285. { d->sym = (Symbol *) emalloc(sizeof(Symbol));
  286. memcpy(d->sym, s->sym, sizeof(Symbol));
  287. if (d->sym->type == CHAN)
  288. d->sym->Nid = ++Nid;
  289. }
  290. if (s->sq || s->sl)
  291. fatal("cannot happen cpnn", (char *) 0);
  292. return d;
  293. }
  294. int
  295. full_name(FILE *fd, Lextok *n, Symbol *v, int xinit)
  296. { Symbol *tl;
  297. Lextok *tmp;
  298. int hiddenarrays = 0;
  299. fprintf(fd, "%s", v->name);
  300. if (!n || !(tl = do_same(n, v, xinit)))
  301. return 0;
  302. tmp = n->rgt->lft;
  303. if (tmp->sym->type == STRUCT)
  304. { fprintf(fd, ".");
  305. hiddenarrays = full_name(fd, tmp, tl, 0);
  306. goto out;
  307. }
  308. fprintf(fd, ".%s", tl->name);
  309. out: if (tmp->sym->nel > 1 || tmp->sym->isarray == 1)
  310. { fprintf(fd, "[%d]", eval(tmp->lft));
  311. hiddenarrays = 1;
  312. }
  313. return hiddenarrays;
  314. }
  315. void
  316. validref(Lextok *p, Lextok *c)
  317. { Lextok *fp, *tl;
  318. char lbuf[512];
  319. for (fp = p->sym->Slst; fp; fp = fp->rgt)
  320. for (tl = fp->lft; tl; tl = tl->rgt)
  321. if (strcmp(tl->sym->name, c->sym->name) == 0)
  322. return;
  323. sprintf(lbuf, "no field '%s' defined in structure '%s'\n",
  324. c->sym->name, p->sym->name);
  325. non_fatal(lbuf, (char *) 0);
  326. }
  327. void
  328. struct_name(Lextok *n, Symbol *v, int xinit, char *buf)
  329. { Symbol *tl;
  330. Lextok *tmp;
  331. char lbuf[512];
  332. if (!n || !(tl = do_same(n, v, xinit)))
  333. return;
  334. tmp = n->rgt->lft;
  335. if (tmp->sym->type == STRUCT)
  336. { strcat(buf, ".");
  337. struct_name(tmp, tl, 0, buf);
  338. return;
  339. }
  340. sprintf(lbuf, ".%s", tl->name);
  341. strcat(buf, lbuf);
  342. if (tmp->sym->nel > 1 || tmp->sym->isarray == 1)
  343. { sprintf(lbuf, "[%d]", eval(tmp->lft));
  344. strcat(buf, lbuf);
  345. }
  346. }
  347. void
  348. walk2_struct(char *s, Symbol *z)
  349. { Lextok *fp, *tl;
  350. char eprefix[128];
  351. int ix;
  352. extern void Done_case(char *, Symbol *);
  353. ini_struct(z);
  354. if (z->nel == 1 && z->isarray == 0)
  355. sprintf(eprefix, "%s%s.", s, z->name);
  356. for (ix = 0; ix < z->nel; ix++)
  357. { if (z->nel > 1 || z->isarray == 1)
  358. sprintf(eprefix, "%s%s[%d].", s, z->name, ix);
  359. for (fp = z->Sval[ix]; fp; fp = fp->rgt)
  360. for (tl = fp->lft; tl; tl = tl->rgt)
  361. { if (tl->sym->type == STRUCT)
  362. walk2_struct(eprefix, tl->sym);
  363. else if (tl->sym->type == CHAN)
  364. Done_case(eprefix, tl->sym);
  365. } }
  366. }
  367. void
  368. walk_struct(FILE *ofd, int dowhat, char *s, Symbol *z, char *a,
  369. char *b, char *c)
  370. { Lextok *fp, *tl;
  371. char eprefix[128];
  372. int ix;
  373. ini_struct(z);
  374. if (z->nel == 1 && z->isarray == 0)
  375. sprintf(eprefix, "%s%s.", s, z->name);
  376. for (ix = 0; ix < z->nel; ix++)
  377. { if (z->nel > 1 || z->isarray == 1)
  378. sprintf(eprefix, "%s%s[%d].", s, z->name, ix);
  379. for (fp = z->Sval[ix]; fp; fp = fp->rgt)
  380. for (tl = fp->lft; tl; tl = tl->rgt)
  381. { if (tl->sym->type == STRUCT)
  382. walk_struct(ofd, dowhat, eprefix, tl->sym, a,b,c);
  383. else
  384. do_var(ofd, dowhat, eprefix, tl->sym, a,b,c);
  385. } }
  386. }
  387. void
  388. c_struct(FILE *fd, char *ipref, Symbol *z)
  389. { Lextok *fp, *tl;
  390. char pref[256], eprefix[300];
  391. int ix;
  392. ini_struct(z);
  393. for (ix = 0; ix < z->nel; ix++)
  394. for (fp = z->Sval[ix]; fp; fp = fp->rgt)
  395. for (tl = fp->lft; tl; tl = tl->rgt)
  396. { strcpy(eprefix, ipref);
  397. if (z->nel > 1 || z->isarray == 1)
  398. { /* insert index before last '.' */
  399. eprefix[strlen(eprefix)-1] = '\0';
  400. sprintf(pref, "[ %d ].", ix);
  401. strcat(eprefix, pref);
  402. }
  403. if (tl->sym->type == STRUCT)
  404. { strcat(eprefix, tl->sym->name);
  405. strcat(eprefix, ".");
  406. c_struct(fd, eprefix, tl->sym);
  407. } else
  408. c_var(fd, eprefix, tl->sym);
  409. }
  410. }
  411. void
  412. dump_struct(Symbol *z, char *prefix, RunList *r)
  413. { Lextok *fp, *tl;
  414. char eprefix[256];
  415. int ix, jx;
  416. ini_struct(z);
  417. for (ix = 0; ix < z->nel; ix++)
  418. { if (z->nel > 1 || z->isarray == 1)
  419. sprintf(eprefix, "%s[%d]", prefix, ix);
  420. else
  421. strcpy(eprefix, prefix);
  422. for (fp = z->Sval[ix]; fp; fp = fp->rgt)
  423. for (tl = fp->lft; tl; tl = tl->rgt)
  424. { if (tl->sym->type == STRUCT)
  425. { char pref[300];
  426. strcpy(pref, eprefix);
  427. strcat(pref, ".");
  428. strcat(pref, tl->sym->name);
  429. dump_struct(tl->sym, pref, r);
  430. } else
  431. for (jx = 0; jx < tl->sym->nel; jx++)
  432. { if (tl->sym->type == CHAN)
  433. doq(tl->sym, jx, r);
  434. else
  435. { printf("\t\t");
  436. if (r)
  437. printf("%s(%d):", r->n->name, r->pid);
  438. printf("%s.%s", eprefix, tl->sym->name);
  439. if (tl->sym->nel > 1 || tl->sym->isarray == 1)
  440. printf("[%d]", jx);
  441. printf(" = ");
  442. sr_mesg(stdout, tl->sym->val[jx],
  443. tl->sym->type == MTYPE);
  444. printf("\n");
  445. } } }
  446. }
  447. }
  448. static int
  449. retrieve(Lextok **targ, int i, int want, Lextok *n, int Ntyp)
  450. { Lextok *fp, *tl;
  451. int j = i, k;
  452. for (fp = n; fp; fp = fp->rgt)
  453. for (tl = fp->lft; tl; tl = tl->rgt)
  454. { if (tl->sym->type == STRUCT)
  455. { j = retrieve(targ, j, want, tl->sym->Slst, Ntyp);
  456. if (j < 0)
  457. { Lextok *x = cpnn(tl, 1, 0, 0);
  458. x->rgt = nn(ZN, '.', (*targ), ZN);
  459. (*targ) = x;
  460. return -1;
  461. }
  462. } else
  463. { for (k = 0; k < tl->sym->nel; k++, j++)
  464. { if (j == want)
  465. { *targ = cpnn(tl, 1, 0, 0);
  466. (*targ)->lft = nn(ZN, CONST, ZN, ZN);
  467. (*targ)->lft->val = k;
  468. if (Ntyp)
  469. (*targ)->ntyp = (int16_t) Ntyp;
  470. return -1;
  471. }
  472. } } }
  473. return j;
  474. }
  475. static int
  476. is_explicit(Lextok *n)
  477. {
  478. if (!n) return 0;
  479. if (!n->sym) fatal("unexpected - no symbol", 0);
  480. if (n->sym->type != STRUCT) return 1;
  481. if (!n->rgt) return 0;
  482. if (n->rgt->ntyp != '.')
  483. { lineno = n->ln;
  484. Fname = n->fn;
  485. printf("ntyp %d\n", n->rgt->ntyp);
  486. fatal("unexpected %s, no '.'", n->sym->name);
  487. }
  488. return is_explicit(n->rgt->lft);
  489. }
  490. Lextok *
  491. expand(Lextok *n, int Ok)
  492. /* turn rgt-lnked list of struct nms, into ',' list of flds */
  493. { Lextok *x = ZN, *y;
  494. if (!Ok) return n;
  495. while (n)
  496. { y = mk_explicit(n, 1, 0);
  497. if (x)
  498. (void) tail_add(x, y);
  499. else
  500. x = y;
  501. n = n->rgt;
  502. }
  503. return x;
  504. }
  505. Lextok *
  506. mk_explicit(Lextok *n, int Ok, int Ntyp)
  507. /* produce a single ',' list of fields */
  508. { Lextok *bld = ZN, *x;
  509. int i, cnt; extern int IArgs;
  510. if (n->sym->type != STRUCT
  511. || in_for
  512. || is_explicit(n))
  513. return n;
  514. if (n->rgt
  515. && n->rgt->ntyp == '.'
  516. && n->rgt->lft
  517. && n->rgt->lft->sym
  518. && n->rgt->lft->sym->type == STRUCT)
  519. { Lextok *y;
  520. bld = mk_explicit(n->rgt->lft, Ok, Ntyp);
  521. for (x = bld; x; x = x->rgt)
  522. { y = cpnn(n, 1, 0, 0);
  523. y->rgt = nn(ZN, '.', x->lft, ZN);
  524. x->lft = y;
  525. }
  526. return bld;
  527. }
  528. if (!Ok || !n->sym->Slst)
  529. { if (IArgs) return n;
  530. printf("spin: saw '");
  531. comment(stdout, n, 0);
  532. printf("'\n");
  533. fatal("incomplete structure ref '%s'", n->sym->name);
  534. }
  535. cnt = Cnt_flds(n->sym->Slst);
  536. for (i = cnt-1; i >= 0; i--)
  537. { bld = nn(ZN, ',', ZN, bld);
  538. if (retrieve(&(bld->lft), 0, i, n->sym->Slst, Ntyp) >= 0)
  539. { printf("cannot retrieve field %d\n", i);
  540. fatal("bad structure %s", n->sym->name);
  541. }
  542. x = cpnn(n, 1, 0, 0);
  543. x->rgt = nn(ZN, '.', bld->lft, ZN);
  544. bld->lft = x;
  545. }
  546. return bld;
  547. }
  548. Lextok *
  549. tail_add(Lextok *a, Lextok *b)
  550. { Lextok *t;
  551. for (t = a; t->rgt; t = t->rgt)
  552. if (t->ntyp != ',')
  553. fatal("unexpected type - tail_add", 0);
  554. t->rgt = b;
  555. return a;
  556. }
  557. void
  558. setpname(Lextok *n)
  559. { UType *tmp;
  560. for (tmp = Pnames; tmp; tmp = tmp->nxt)
  561. if (!strcmp(n->sym->name, tmp->nm->name))
  562. { non_fatal("proctype %s redefined",
  563. n->sym->name);
  564. return;
  565. }
  566. tmp = (UType *) emalloc(sizeof(UType));
  567. tmp->nm = n->sym;
  568. tmp->nxt = Pnames;
  569. Pnames = tmp;
  570. }
  571. int
  572. isproctype(char *t)
  573. { UType *tmp;
  574. for (tmp = Pnames; tmp; tmp = tmp->nxt)
  575. { if (!strcmp(t, tmp->nm->name))
  576. return 1;
  577. }
  578. return 0;
  579. }