pangen1.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976
  1. /***** spin: pangen1.c *****/
  2. /* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* Permission is given to distribute this code provided that this intro- */
  5. /* ductory message is not removed and no monies are exchanged. */
  6. /* No guarantee is expressed or implied by the distribution of this code. */
  7. /* Software written by Gerard J. Holzmann as part of the book: */
  8. /* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4, */
  9. /* Prentice Hall, Englewood Cliffs, NJ, 07632. */
  10. /* Send bug-reports and/or questions to: gerard@research.bell-labs.com */
  11. #include "spin.h"
  12. #ifdef PC
  13. #include "y_tab.h"
  14. #else
  15. #include "y.tab.h"
  16. #endif
  17. #include "pangen1.h"
  18. #include "pangen3.h"
  19. extern FILE *tc, *th, *tt;
  20. extern Label *labtab;
  21. extern Ordered *all_names;
  22. extern ProcList *rdy;
  23. extern Queue *qtab;
  24. extern Symbol *Fname;
  25. extern int lineno, verbose, Pid, separate;
  26. extern int nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
  27. extern short has_sorted, has_random, has_provided;
  28. int Npars=0, u_sync=0, u_async=0;
  29. static Symbol *LstSet=ZS;
  30. static int acceptors=0, progressors=0, nBits=0;
  31. static int Types[] = { UNSIGNED, BIT, BYTE, CHAN, MTYPE, SHORT, INT, STRUCT };
  32. static int doglobal(char *, int);
  33. static void dohidden(void);
  34. static void do_init(FILE *, Symbol *);
  35. static void end_labs(Symbol *, int);
  36. static void put_ptype(char *, int, int, int);
  37. static void tc_predef_np(void);
  38. static void put_pinit(ProcList *);
  39. void walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *);
  40. static void
  41. reverse_names(ProcList *p)
  42. {
  43. if (!p) return;
  44. reverse_names(p->nxt);
  45. fprintf(th, " \"%s\",\n", p->n->name);
  46. }
  47. void
  48. genheader(void)
  49. { ProcList *p; int i;
  50. if (separate == 2) goto here;
  51. fprintf(th, "#define SYNC %d\n", u_sync);
  52. fprintf(th, "#define ASYNC %d\n\n", u_async);
  53. putunames(th);
  54. fprintf(tc, "short Air[] = { ");
  55. for (p = rdy, i=0; p; p = p->nxt, i++)
  56. fprintf(tc, "%s (short) Air%d", (p!=rdy)?",":"", i);
  57. fprintf(tc, ", (short) Air%d", i); /* np_ */
  58. fprintf(tc, " };\n");
  59. fprintf(th, "char *procname[] = {\n");
  60. reverse_names(rdy);
  61. fprintf(th, " \":np_:\",\n");
  62. fprintf(th, "};\n\n");
  63. here:
  64. for (p = rdy; p; p = p->nxt)
  65. put_ptype(p->n->name, p->tn, mst, nrRdy+1);
  66. /* +1 for np_ */
  67. put_ptype("np_", nrRdy, mst, nrRdy+1);
  68. ntimes(th, 0, 1, Head0);
  69. if (separate == 2)
  70. { ntimes(th, 0, 1, Head1);
  71. LstSet = ZS;
  72. (void) doglobal("", PUTV);
  73. fprintf(th, " uchar sv[VECTORSZ];\n");
  74. fprintf(th, "} State;\n\n");
  75. } else
  76. {
  77. ntimes(th, 0, 1, Header);
  78. ntimes(th, 0, 1, Head1);
  79. LstSet = ZS;
  80. (void) doglobal("", PUTV);
  81. fprintf(th, " uchar sv[VECTORSZ];\n");
  82. fprintf(th, "} State;\n\n");
  83. dohidden();
  84. }
  85. }
  86. void
  87. genaddproc(void)
  88. { ProcList *p;
  89. int i;
  90. if (separate ==2) goto shortcut;
  91. fprintf(tc, "int\naddproc(int n");
  92. for (i = 0; i < Npars; i++)
  93. fprintf(tc, ", int par%d", i);
  94. ntimes(tc, 0, 1, Addp0);
  95. ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
  96. ntimes(tc, 0, 1, Addp1);
  97. if (has_provided)
  98. { fprintf(tt, "\nint\nprovided(int II, int ot, ");
  99. fprintf(tt, "int tt, Trans *t)\n");
  100. fprintf(tt, "{\n\tswitch(ot) {\n");
  101. }
  102. shortcut:
  103. tc_predef_np();
  104. for (p = rdy; p; p = p->nxt)
  105. { Pid = p->tn;
  106. put_pinit(p);
  107. }
  108. if (separate == 2) return;
  109. Pid = 0;
  110. if (has_provided)
  111. { fprintf(tt, "\tdefault: return 1; /* e.g., a claim */\n");
  112. fprintf(tt, "\t}\n\treturn 0;\n}\n");
  113. }
  114. ntimes(tc, i, i+1, R6);
  115. if (separate == 0)
  116. ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
  117. else
  118. ntimes(tc, 1, nrRdy, R5);
  119. ntimes(tc, 0, 1, R8a);
  120. }
  121. void
  122. genother(void)
  123. { ProcList *p;
  124. switch (separate) {
  125. case 2:
  126. if (claimnr >= 0)
  127. ntimes(tc, claimnr, claimnr+1, R0); /* claim only */
  128. break;
  129. case 1:
  130. ntimes(tc, 0, 1, Code0);
  131. ntimes(tc, 0, claimnr, R0); /* all except claim */
  132. ntimes(tc, claimnr+1, nrRdy, R0);
  133. break;
  134. case 0:
  135. ntimes(tc, 0, 1, Code0);
  136. ntimes(tc, 0, nrRdy+1, R0); /* +1 for np_ */
  137. break;
  138. }
  139. for (p = rdy; p; p = p->nxt)
  140. end_labs(p->n, p->tn);
  141. switch (separate) {
  142. case 2:
  143. if (claimnr >= 0)
  144. ntimes(tc, claimnr, claimnr+1, R0a); /* claim only */
  145. return;
  146. case 1:
  147. ntimes(tc, 0, claimnr, R0a); /* all except claim */
  148. ntimes(tc, claimnr+1, nrRdy, R0a);
  149. fprintf(tc, " if (state_tables)\n");
  150. fprintf(tc, " ini_claim(%d, 0);\n", claimnr);
  151. break;
  152. case 0:
  153. ntimes(tc, 0, nrRdy, R0a); /* all */
  154. break;
  155. }
  156. ntimes(tc, 0, 1, R0b);
  157. if (separate == 1 && acceptors == 0)
  158. acceptors = 1; /* assume at least 1 acceptstate */
  159. ntimes(th, acceptors, acceptors+1, Code1);
  160. ntimes(th, progressors, progressors+1, Code3);
  161. ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */
  162. fprintf(tc, " iniglobals();\n");
  163. ntimes(tc, 0, 1, Code2);
  164. ntimes(tc, 0, nrRdy, R4);
  165. fprintf(tc, "}\n\n");
  166. fprintf(tc, "void\n");
  167. fprintf(tc, "iniglobals(void)\n{\n");
  168. if (doglobal("", INIV) > 0)
  169. { fprintf(tc, "#ifdef VAR_RANGES\n");
  170. (void) doglobal("logval(\"", LOGV);
  171. fprintf(tc, "#endif\n");
  172. }
  173. ntimes(tc, 1, nqs+1, R3);
  174. fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);");
  175. fprintf(tc, "\n}\n\n");
  176. }
  177. void
  178. gensvmap(void)
  179. {
  180. ntimes(tc, 0, 1, SvMap);
  181. }
  182. static struct {
  183. char *s, *t; int n, m, p;
  184. } ln[] = {
  185. {"end", "stopstate", 3, 0, 0},
  186. {"progress", "progstate", 8, 0, 1},
  187. {"accept", "accpstate", 6, 1, 0},
  188. {0, 0, 0, 0, 0},
  189. };
  190. static void
  191. end_labs(Symbol *s, int i)
  192. { int oln = lineno;
  193. Symbol *ofn = Fname;
  194. Label *l;
  195. int j; char foo[128];
  196. if ((i == claimnr && separate == 1)
  197. || (i != claimnr && separate == 2))
  198. return;
  199. for (l = labtab; l; l = l->nxt)
  200. for (j = 0; ln[j].n; j++)
  201. if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
  202. && strcmp(l->c->name, s->name) == 0)
  203. { fprintf(tc, "\t%s[%d][%d] = 1;\n",
  204. ln[j].t, i, l->e->seqno);
  205. acceptors += ln[j].m;
  206. progressors += ln[j].p;
  207. if (l->e->status & D_ATOM)
  208. { sprintf(foo, "%s label inside d_step",
  209. ln[j].s);
  210. goto complain;
  211. }
  212. if (l->e->status & ATOM)
  213. { sprintf(foo, "%s label inside atomic",
  214. ln[j].s);
  215. complain: lineno = l->e->n->ln;
  216. Fname = l->e->n->fn;
  217. printf("spin: %3d:%s, warning, %s - is invisible\n",
  218. lineno, Fname?Fname->name:"-", foo);
  219. }
  220. }
  221. /* visible states -- through remote refs: */
  222. for (l = labtab; l; l = l->nxt)
  223. if (l->visible
  224. && strcmp(l->s->context->name, s->name) == 0)
  225. fprintf(tc, "\tvisstate[%d][%d] = 1;\n",
  226. i, l->e->seqno);
  227. lineno = oln;
  228. Fname = ofn;
  229. }
  230. void
  231. ntimes(FILE *fd, int n, int m, char *c[])
  232. {
  233. int i, j;
  234. for (j = 0; c[j]; j++)
  235. for (i = n; i < m; i++)
  236. { fprintf(fd, c[j], i, i, i, i, i, i);
  237. fprintf(fd, "\n");
  238. }
  239. }
  240. void
  241. prehint(Symbol *s)
  242. { Lextok *n;
  243. printf("spin: warning, ");
  244. if (!s) return;
  245. n = (s->context != ZS)?s->context->ini:s->ini;
  246. if (n)
  247. printf("line %3d %s, ", n->ln, n->fn->name);
  248. }
  249. void
  250. checktype(Symbol *sp, char *s)
  251. { char buf[128]; int i;
  252. if (!s
  253. || (sp->type != BYTE
  254. && sp->type != SHORT
  255. && sp->type != INT))
  256. return;
  257. if (sp->hidden&16) /* formal parameter */
  258. { ProcList *p; Lextok *f, *t;
  259. int posnr = 0;
  260. for (p = rdy; p; p = p->nxt)
  261. if (p->n->name
  262. && strcmp(s, p->n->name) == 0)
  263. break;
  264. if (p)
  265. for (f = p->p; f; f = f->rgt) /* list of types */
  266. for (t = f->lft; t; t = t->rgt, posnr++)
  267. if (t->sym
  268. && strcmp(t->sym->name, sp->name) == 0)
  269. { checkrun(sp, posnr);
  270. return;
  271. }
  272. } else if (!(sp->hidden&4))
  273. { if (!(verbose&32)) return;
  274. sputtype(buf, sp->type);
  275. i = strlen(buf);
  276. while (buf[--i] == ' ') buf[i] = '\0';
  277. prehint(sp);
  278. if (sp->context)
  279. printf("proctype %s:", s);
  280. else
  281. printf("global");
  282. printf(" '%s %s' could be declared 'bit %s'\n",
  283. buf, sp->name, sp->name);
  284. } else if (sp->type != BYTE && !(sp->hidden&8))
  285. { if (!(verbose&32)) return;
  286. sputtype(buf, sp->type);
  287. i = strlen(buf);
  288. while (buf[--i] == ' ') buf[i] = '\0';
  289. prehint(sp);
  290. if (sp->context)
  291. printf("proctype %s:", s);
  292. else
  293. printf("global");
  294. printf(" '%s %s' could be declared 'byte %s'\n",
  295. buf, sp->name, sp->name);
  296. }
  297. }
  298. int
  299. dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, char *how)
  300. { int h, j, k=0; extern int nr_errs;
  301. Ordered *walk;
  302. Symbol *sp;
  303. char buf[64], buf2[128], buf3[128];
  304. for (j = 0; j < 8; j++)
  305. for (h = 0; h <= 1; h++)
  306. for (walk = all_names; walk; walk = walk->next)
  307. { sp = walk->entry;
  308. if (sp->context
  309. && !sp->owner
  310. && sp->type == Types[j]
  311. && ((h == 0 && sp->nel == 1) || (h == 1 && sp->nel > 1))
  312. && strcmp(s, sp->context->name) == 0)
  313. { switch (dowhat) {
  314. case LOGV:
  315. if (sp->type == CHAN
  316. && verbose == 0)
  317. break;
  318. sprintf(buf, "%s%s:", pre, s);
  319. { sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
  320. sprintf(buf3, ");\n", p);
  321. }
  322. do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
  323. break;
  324. case INIV:
  325. checktype(sp, s); /* fall through */
  326. if (sp->hidden&16) { k++; break; }
  327. case PUTV:
  328. sprintf(buf, "((P%d *)pptr(h))->", p);
  329. do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
  330. k++;
  331. break;
  332. }
  333. if (strcmp(s, ":never:") == 0)
  334. { printf("error: %s defines local %s\n",
  335. s, sp->name);
  336. nr_errs++;
  337. } } }
  338. return k;
  339. }
  340. static int
  341. doglobal(char *pre, int dowhat)
  342. { Ordered *walk;
  343. Symbol *sp;
  344. int j, cnt = 0;
  345. for (j = 0; j < 8; j++)
  346. for (walk = all_names; walk; walk = walk->next)
  347. { sp = walk->entry;
  348. if (!sp->context
  349. && !sp->owner
  350. /* && !(sp->hidden&1) */
  351. && sp->type == Types[j])
  352. { if (Types[j] != MTYPE || !ismtype(sp->name))
  353. switch (dowhat) {
  354. case LOGV:
  355. if (sp->type == CHAN
  356. && verbose == 0)
  357. break;
  358. if (sp->hidden&1)
  359. break;
  360. do_var(tc, dowhat, "", sp,
  361. pre, "\", now.", ");\n");
  362. break;
  363. case INIV:
  364. checktype(sp, (char *) 0);
  365. cnt++; /* fall through */
  366. case PUTV:
  367. do_var(tc, dowhat, (sp->hidden&1)?"":"now.", sp,
  368. "", " = ", ";\n");
  369. break;
  370. } } }
  371. return cnt;
  372. }
  373. static void
  374. dohidden(void)
  375. { Ordered *walk;
  376. Symbol *sp;
  377. int j;
  378. for (j = 0; j < 8; j++)
  379. for (walk = all_names; walk; walk = walk->next)
  380. { sp = walk->entry;
  381. if ((sp->hidden&1)
  382. && sp->type == Types[j])
  383. { if (sp->context || sp->owner)
  384. fatal("cannot hide non-globals (%s)", sp->name);
  385. if (sp->type == CHAN)
  386. fatal("cannot hide channels (%s)", sp->name);
  387. fprintf(th, "/* hidden variable: */");
  388. typ2c(sp);
  389. } }
  390. fprintf(th, "int _; /* a predefined write-only variable */\n\n");
  391. }
  392. void
  393. do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
  394. char *pre, char *sep, char *ter)
  395. { int i;
  396. switch(dowhat) {
  397. case PUTV:
  398. if (sp->hidden&1) break;
  399. typ2c(sp);
  400. break;
  401. case LOGV:
  402. case INIV:
  403. if (sp->type == STRUCT)
  404. { /* struct may contain a chan */
  405. walk_struct(ofd, dowhat, s, sp, pre, sep, ter);
  406. break;
  407. }
  408. if (!sp->ini && dowhat != LOGV) /* it defaults to 0 */
  409. break;
  410. if (sp->nel == 1)
  411. { fprintf(ofd, "\t\t%s%s%s%s",
  412. pre, s, sp->name, sep);
  413. if (dowhat == LOGV)
  414. fprintf(ofd, "%s%s", s, sp->name);
  415. else
  416. do_init(ofd, sp);
  417. fprintf(ofd, "%s", ter);
  418. } else
  419. for (i = 0; i < sp->nel; i++)
  420. { fprintf(ofd, "\t\t%s%s%s[%d]%s",
  421. pre, s, sp->name, i, sep);
  422. if (dowhat == LOGV)
  423. fprintf(ofd, "%s%s[%d]",
  424. s, sp->name, i);
  425. else
  426. do_init(ofd, sp);
  427. fprintf(ofd, "%s", ter);
  428. }
  429. break;
  430. }
  431. }
  432. static void
  433. do_init(FILE *ofd, Symbol *sp)
  434. { int i; extern Queue *ltab[];
  435. if (sp->ini
  436. && sp->type == CHAN
  437. && ((i = qmake(sp)) > 0))
  438. { if (sp->ini->ntyp == CHAN)
  439. fprintf(ofd, "addqueue(%d, %d)",
  440. i, ltab[i-1]->nslots == 0);
  441. else
  442. fprintf(ofd, "%d", i);
  443. } else
  444. putstmnt(ofd, sp->ini, 0);
  445. }
  446. static int
  447. blog(int n) /* for small log2 without rounding problems */
  448. { int m=1, r=2;
  449. while (r < n) { m++; r *= 2; }
  450. return 1+m;
  451. }
  452. static void
  453. put_ptype(char *s, int i, int m0, int m1)
  454. { int k;
  455. fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
  456. fprintf(th, " unsigned _pid : 8; /* 0..255 */\n");
  457. fprintf(th, " unsigned _t : %d; /* proctype */\n", blog(m1));
  458. fprintf(th, " unsigned _p : %d; /* state */\n", blog(m0));
  459. LstSet = ZS;
  460. nBits = 8 + blog(m1) + blog(m0);
  461. k = dolocal(tc, "", PUTV, i, s, ""); /* includes pars */
  462. fprintf(th, "} P%d;\n", i);
  463. if (!LstSet && k > 0)
  464. fprintf(th, "#define Air%d 0\n", i);
  465. else
  466. { fprintf(th, "#define Air%d (sizeof(P%d) - ", i, i);
  467. if (k == 0)
  468. { fprintf(th, "%d", (nBits+7)/8);
  469. goto done;
  470. }
  471. if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
  472. || LstSet->nel != 1)
  473. { fprintf(th, "Offsetof(P%d, %s%s) - %d*sizeof(",
  474. i,
  475. LstSet->name,
  476. #if 1
  477. "",
  478. #else
  479. (LstSet->nel > 1)?"[0]":"",
  480. #endif
  481. LstSet->nel);
  482. }
  483. switch(LstSet->type) {
  484. case UNSIGNED:
  485. fprintf(th, "%d", (nBits+7)/8);
  486. break;
  487. case BIT:
  488. if (LstSet->nel == 1)
  489. { fprintf(th, "%d", (nBits+7)/8);
  490. break;
  491. } /* else fall through */
  492. case MTYPE: case BYTE: case CHAN:
  493. fprintf(th, "uchar)"); break;
  494. case SHORT:
  495. fprintf(th, "short)"); break;
  496. case INT:
  497. fprintf(th, "int)"); break;
  498. default:
  499. fatal("cannot happen Air %s",
  500. LstSet->name);
  501. }
  502. done: fprintf(th, ")\n");
  503. }
  504. }
  505. static void
  506. tc_predef_np(void)
  507. { int i = nrRdy; /* 1+ highest proctype nr */
  508. fprintf(th, "#define _NP_ %d\n", i);
  509. if (separate == 2) fprintf(th, "extern ");
  510. fprintf(th, "uchar reached%d[3]; /* np_ */\n", i);
  511. fprintf(th, "#define nstates%d 3 /* np_ */\n", i);
  512. fprintf(th, "#define endstate%d 2 /* np_ */\n\n", i);
  513. fprintf(th, "#define start%d 0 /* np_ */\n", i);
  514. fprintf(tc, "\tcase %d: /* np_ */\n", i);
  515. if (separate == 1)
  516. { fprintf(tc, "\t\tini_claim(%d, h);\n", i);
  517. } else
  518. { fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
  519. fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", i);
  520. fprintf(tc, "\t\treached%d[0] = 1;\n", i);
  521. fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", i);
  522. }
  523. fprintf(tc, "\t\tbreak;\n");
  524. }
  525. static void
  526. put_pinit(ProcList *P)
  527. { Lextok *fp, *fpt, *t;
  528. Element *e = P->s->frst;
  529. Symbol *s = P->n;
  530. Lextok *p = P->p;
  531. int i = P->tn;
  532. int ini, j, k;
  533. if (i == claimnr
  534. && separate == 1)
  535. { fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
  536. fprintf(tc, "\t\tini_claim(%d, h);\n", i);
  537. fprintf(tc, "\t\tbreak;\n");
  538. return;
  539. }
  540. if (i != claimnr
  541. && separate == 2)
  542. return;
  543. ini = huntele(e, e->status)->seqno;
  544. fprintf(th, "#define start%d %d\n", i, ini);
  545. if (i == claimnr)
  546. fprintf(th, "#define start_claim %d\n", ini);
  547. if (i == eventmapnr)
  548. fprintf(th, "#define start_event %d\n", ini);
  549. fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
  550. fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
  551. fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;", i, ini);
  552. fprintf(tc, " reached%d[%d]=1;\n", i, ini);
  553. if (has_provided)
  554. { fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
  555. if (P->prov)
  556. { fprintf(tt, "if (");
  557. putstmnt(tt, P->prov, 0);
  558. fprintf(tt, ")\n\t\t\t");
  559. }
  560. fprintf(tt, "return 1;\n");
  561. if (P->prov)
  562. fprintf(tt, "\t\tbreak;\n");
  563. }
  564. fprintf(tc, "\t\t/* params: */\n");
  565. for (fp = p, j=0; fp; fp = fp->rgt)
  566. for (fpt = fp->lft; fpt; fpt = fpt->rgt, j++)
  567. { t = (fpt->ntyp == ',') ? fpt->lft : fpt;
  568. if (t->sym->nel != 1)
  569. { lineno = t->ln;
  570. Fname = t->fn;
  571. fatal("array in parameter list, %s",
  572. t->sym->name);
  573. }
  574. fprintf(tc, "\t\t((P%d *)pptr(h))->", i);
  575. if (t->sym->type == STRUCT)
  576. { if (full_name(tc, t, t->sym, 1))
  577. { lineno = t->ln;
  578. Fname = t->fn;
  579. fatal("hidden array in parameter, %s",
  580. t->sym->name);
  581. }
  582. } else
  583. fprintf(tc, "%s", t->sym->name);
  584. fprintf(tc, " = par%d;\n", j);
  585. }
  586. fprintf(tc, "\t\t/* locals: */\n");
  587. k = dolocal(tc, "", INIV, i, s->name, "");
  588. if (k > 0)
  589. { fprintf(tc, "#ifdef VAR_RANGES\n");
  590. (void) dolocal(tc, "logval(\"", LOGV, i, s->name, "");
  591. fprintf(tc, "#endif\n");
  592. }
  593. dumpclaims(tc, i, s->name);
  594. fprintf(tc, "\t break;\n");
  595. }
  596. Element *
  597. huntstart(Element *f)
  598. { Element *e = f;
  599. if (e->n)
  600. { if (e->n->ntyp == '.' && e->nxt)
  601. e = e->nxt;
  602. else if (e->n->ntyp == ATOMIC
  603. || e->n->ntyp == D_STEP
  604. || e->n->ntyp == NON_ATOMIC)
  605. e->n->sl->this->last->nxt = e->nxt;
  606. else if (e->n->ntyp == UNLESS)
  607. return e->sub->this->frst;
  608. }
  609. return e;
  610. }
  611. Element *
  612. huntele(Element *f, int o)
  613. { Element *g, *e = f;
  614. int cnt; /* a precaution against loops */
  615. if (e)
  616. for (cnt=0; cnt < 10 && e->n; cnt++)
  617. { switch (e->n->ntyp) {
  618. case GOTO:
  619. g = get_lab(e->n,1);
  620. cross_dsteps(e->n, g->n);
  621. break;
  622. case '.':
  623. case BREAK:
  624. if (!e->nxt)
  625. return e;
  626. g = e->nxt;
  627. break;
  628. case UNLESS:
  629. g = huntele(e->sub->this->frst, o);
  630. break;
  631. case D_STEP:
  632. case ATOMIC:
  633. case NON_ATOMIC:
  634. e->n->sl->this->last->nxt = e->nxt;
  635. default: /* fall through */
  636. return e;
  637. }
  638. if ((o & ATOM) && !(g->status & ATOM))
  639. return e;
  640. e = g;
  641. }
  642. return e;
  643. }
  644. void
  645. typ2c(Symbol *sp)
  646. { int wsbits = sizeof(long)*8; /* wordsize in bits */
  647. switch (sp->type) {
  648. case UNSIGNED:
  649. if (sp->hidden&1)
  650. fprintf(th, "\tuchar %s;", sp->name);
  651. else
  652. fprintf(th, "\tunsigned %s : %d",
  653. sp->name, sp->nbits);
  654. LstSet = sp;
  655. if (nBits%wsbits > 0
  656. && wsbits - nBits%wsbits < sp->nbits)
  657. { /* must padd to a word-boundary */
  658. nBits += wsbits - nBits%wsbits;
  659. }
  660. nBits += sp->nbits;
  661. break;
  662. case BIT:
  663. if (sp->nel == 1 && !(sp->hidden&1))
  664. { fprintf(th, "\tunsigned %s : 1", sp->name);
  665. LstSet = sp;
  666. nBits++;
  667. break;
  668. } /* else fall through */
  669. printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
  670. sp->name, sp->nel);
  671. nBits += 8*sp->nel; /* mapped onto array of uchars */
  672. case MTYPE:
  673. case BYTE:
  674. case CHAN: /* good for up to 255 channels */
  675. fprintf(th, "\tuchar %s", sp->name);
  676. LstSet = sp;
  677. break;
  678. case SHORT:
  679. fprintf(th, "\tshort %s", sp->name);
  680. LstSet = sp;
  681. break;
  682. case INT:
  683. fprintf(th, "\tint %s", sp->name);
  684. LstSet = sp;
  685. break;
  686. case STRUCT:
  687. if (!sp->Snm)
  688. fatal("undeclared structure element %s", sp->name);
  689. fprintf(th, "\tstruct %s %s",
  690. sp->Snm->name,
  691. sp->name);
  692. LstSet = ZS;
  693. break;
  694. case PREDEF:
  695. return;
  696. default:
  697. fatal("variable %s undeclared", sp->name);
  698. }
  699. if (sp->nel != 1)
  700. fprintf(th, "[%d]", sp->nel);
  701. fprintf(th, ";\n");
  702. }
  703. static void
  704. ncases(FILE *fd, int p, int n, int m, char *c[])
  705. { int i, j;
  706. for (j = 0; c[j]; j++)
  707. for (i = n; i < m; i++)
  708. { fprintf(fd, c[j], i, p, i);
  709. fprintf(fd, "\n");
  710. }
  711. }
  712. void
  713. genaddqueue(void)
  714. { char buf0[256];
  715. int j;
  716. Queue *q;
  717. ntimes(tc, 0, 1, Addq0);
  718. fprintf(th, "short q_flds[%d];\n", nqs+1);
  719. fprintf(th, "short q_max[%d];\n", nqs+1);
  720. for (q = qtab; q; q = q->nxt)
  721. { j = q->qid;
  722. fprintf(tc, "\tcase %d: j = sizeof(Q%d);", j, j);
  723. fprintf(tc, " q_flds[%d] = %d;", j, q->nflds);
  724. fprintf(tc, " q_max[%d] = %d;", j, max(1,q->nslots));
  725. fprintf(tc, " break;\n");
  726. ntimes(th, j, j+1, R9);
  727. for (j = 0; j < q->nflds; j++)
  728. { switch (q->fld_width[j]) {
  729. case BIT:
  730. if (q->nflds != 1)
  731. { fprintf(th, "\t\tunsigned");
  732. fprintf(th, " fld%d : 1;\n", j);
  733. break;
  734. } /* else fall through: smaller struct */
  735. case MTYPE:
  736. case CHAN:
  737. case BYTE:
  738. fprintf(th, "\t\tuchar fld%d;\n", j);
  739. break;
  740. case SHORT:
  741. fprintf(th, "\t\tshort fld%d;\n", j);
  742. break;
  743. case INT:
  744. fprintf(th, "\t\tint fld%d;\n", j);
  745. break;
  746. default:
  747. fatal("bad channel spec", "");
  748. }
  749. }
  750. fprintf(th, " } contents[%d];\n", max(1, q->nslots));
  751. fprintf(th, "} Q%d;\n", q->qid);
  752. }
  753. ntimes(th, 0, 1, R10);
  754. ntimes(tc, 0, 1, Addq1);
  755. if (has_random)
  756. { fprintf(th, "int Q_has(int");
  757. for (j = 0; j < Mpars; j++)
  758. fprintf(th, ", int, int");
  759. fprintf(th, ");\n");
  760. fprintf(tc, "int\nQ_has(int into");
  761. for (j = 0; j < Mpars; j++)
  762. fprintf(tc, ", int want%d, int fld%d", j, j);
  763. fprintf(tc, ")\n");
  764. fprintf(tc, "{ int i;\n\n");
  765. fprintf(tc, " if (!into--)\n");
  766. fprintf(tc, " uerror(\"ref to unknown chan ");
  767. fprintf(tc, "(recv-poll)\");\n\n");
  768. fprintf(tc, " if (into >= now._nr_qs || into < 0)\n");
  769. fprintf(tc, " Uerror(\"qrecv bad queue#\");\n\n");
  770. fprintf(tc, " for (i = 0; i < ((Q0 *)qptr(into))->Qlen;");
  771. fprintf(tc, " i++)\n");
  772. fprintf(tc, " {\n");
  773. for (j = 0; j < Mpars; j++)
  774. { fprintf(tc, " if (want%d && ", j);
  775. fprintf(tc, "qrecv(into+1, i, %d, 0) != fld%d)\n",
  776. j, j);
  777. fprintf(tc, " continue;\n");
  778. }
  779. fprintf(tc, " return i+1;\n");
  780. fprintf(tc, " }\n");
  781. fprintf(tc, " return 0;\n");
  782. fprintf(tc, "}\n");
  783. }
  784. fprintf(tc, "void\nqsend(int into, int sorted");
  785. for (j = 0; j < Mpars; j++)
  786. fprintf(tc, ", int fld%d", j);
  787. fprintf(tc, ")\n");
  788. ntimes(tc, 0, 1, Addq11);
  789. for (q = qtab; q; q = q->nxt)
  790. { sprintf(buf0, "((Q%d *)z)->", q->qid);
  791. fprintf(tc, "\tcase %d:%s\n", q->qid,
  792. (q->nslots)?"":" /* =rv= */");
  793. if (q->nslots == 0) /* reset handshake point */
  794. fprintf(tc, "\t\t(trpt+2)->o_m = 0;\n");
  795. if (has_sorted)
  796. { fprintf(tc, "\t\tif (!sorted) goto append%d;\n", q->qid);
  797. fprintf(tc, "\t\tfor (j = 0; j < %sQlen; j++)\n", buf0);
  798. fprintf(tc, "\t\t{\t/* find insertion point */\n");
  799. sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
  800. for (j = 0; j < q->nflds; j++)
  801. { fprintf(tc, "\t\t\tif (fld%d > %s%d) continue;\n",
  802. j, buf0, j);
  803. fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
  804. fprintf(tc, "goto found%d;\n\n", q->qid);
  805. }
  806. fprintf(tc, "\t\t}\n");
  807. fprintf(tc, "\tfound%d:\n", q->qid);
  808. sprintf(buf0, "((Q%d *)z)->", q->qid);
  809. fprintf(tc, "\t\tfor (k = %sQlen - 1; k >= j; k--)\n", buf0);
  810. fprintf(tc, "\t\t{\t/* shift up */\n");
  811. for (j = 0; j < q->nflds; j++)
  812. { fprintf(tc, "\t\t\t%scontents[k+1].fld%d = ",
  813. buf0, j);
  814. fprintf(tc, "%scontents[k].fld%d;\n",
  815. buf0, j);
  816. }
  817. fprintf(tc, "\t\t}\n");
  818. fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
  819. }
  820. fprintf(tc, "\t\t(trpt+1)->bup.oval = j;\n");
  821. fprintf(tc, "\t\t%sQlen = %sQlen + 1;\n", buf0, buf0);
  822. sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
  823. for (j = 0; j < q->nflds; j++)
  824. fprintf(tc, "\t\t%s%d = fld%d;\n", buf0, j, j);
  825. fprintf(tc, "\t\tbreak;\n");
  826. }
  827. ntimes(tc, 0, 1, Addq2);
  828. for (q = qtab; q; q = q->nxt)
  829. fprintf(tc, "\tcase %d: return %d;\n", q->qid, (!q->nslots));
  830. ntimes(tc, 0, 1, Addq3);
  831. for (q = qtab; q; q = q->nxt)
  832. fprintf(tc, "\tcase %d: return (q_sz(from) == %d);\n",
  833. q->qid, max(1, q->nslots));
  834. ntimes(tc, 0, 1, Addq4);
  835. for (q = qtab; q; q = q->nxt)
  836. { sprintf(buf0, "((Q%d *)z)->", q->qid);
  837. fprintf(tc, " case %d:%s\n\t\t",
  838. q->qid, (q->nslots)?"":" /* =rv= */");
  839. if (q->nflds == 1)
  840. { fprintf(tc, "if (fld == 0) r = %s", buf0);
  841. fprintf(tc, "contents[slot].fld0;\n");
  842. } else
  843. { fprintf(tc, "switch (fld) {\n");
  844. ncases(tc, q->qid, 0, q->nflds, R12);
  845. fprintf(tc, "\t\tdefault: Uerror");
  846. fprintf(tc, "(\"too many fields in recv\");\n");
  847. fprintf(tc, "\t\t}\n");
  848. }
  849. fprintf(tc, "\t\tif (done)\n");
  850. fprintf(tc, "\t\t{ j = %sQlen;\n", buf0);
  851. fprintf(tc, "\t\t %sQlen = --j;\n", buf0);
  852. fprintf(tc, "\t\t for (k=slot; k<j; k++)\n");
  853. fprintf(tc, "\t\t {\n");
  854. sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
  855. for (j = 0; j < q->nflds; j++)
  856. { fprintf(tc, "\t%s[k].fld%d = \n", buf0, j);
  857. fprintf(tc, "\t\t%s[k+1].fld%d;\n", buf0, j);
  858. }
  859. fprintf(tc, "\t\t }\n");
  860. for (j = 0; j < q->nflds; j++)
  861. fprintf(tc, "%s[j].fld%d = 0;\n", buf0, j);
  862. fprintf(tc, "\t\t\tif (fld+1 != %d)\n\t\t\t", q->nflds);
  863. fprintf(tc, "\tuerror(\"missing pars in receive\");\n");
  864. /* incompletely received msgs cannot be unrecv'ed */
  865. fprintf(tc, "\t\t}\n");
  866. fprintf(tc, "\t\tbreak;\n");
  867. }
  868. ntimes(tc, 0, 1, Addq5);
  869. for (q = qtab; q; q = q->nxt)
  870. fprintf(tc, " case %d: j = sizeof(Q%d); break;\n",
  871. q->qid, q->qid);
  872. ntimes(tc, 0, 1, R8b);
  873. ntimes(th, 0, 1, Proto); /* tag on function prototypes */
  874. fprintf(th, "void qsend(int, int");
  875. for (j = 0; j < Mpars; j++)
  876. fprintf(th, ", int");
  877. fprintf(th, ");\n");
  878. fprintf(th, "#define Addproc(x) addproc(x");
  879. for (j = 0; j < Npars; j++)
  880. fprintf(th, ", 0");
  881. fprintf(th, ")\n");
  882. }