pangen1.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275
  1. /***** spin: pangen1.c *****/
  2. /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* No guarantee whatsoever is expressed or implied by the distribution of */
  5. /* this code. Permission is given to distribute this code provided that */
  6. /* this introductory message is not removed and no monies are exchanged. */
  7. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  8. /* http://spinroot.com/ */
  9. /* Send all bug-reports and/or questions to: bugs@spinroot.com */
  10. #include "spin.h"
  11. #include "y.tab.h"
  12. #include "pangen1.h"
  13. #include "pangen3.h"
  14. extern FILE *tc, *th, *tt;
  15. extern Label *labtab;
  16. extern Ordered *all_names;
  17. extern ProcList *rdy;
  18. extern Queue *qtab;
  19. extern Symbol *Fname;
  20. extern int lineno, verbose, Pid, separate;
  21. extern int nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
  22. extern short has_sorted, has_random, has_provided;
  23. int Npars=0, u_sync=0, u_async=0, hastrack = 1;
  24. short has_io = 0;
  25. short has_state=0; /* code contains c_state */
  26. static Symbol *LstSet=ZS;
  27. static int acceptors=0, progressors=0, nBits=0;
  28. static int Types[] = { UNSIGNED, BIT, BYTE, CHAN, MTYPE, SHORT, INT, STRUCT };
  29. static int doglobal(char *, int);
  30. static void dohidden(void);
  31. static void do_init(FILE *, Symbol *);
  32. static void end_labs(Symbol *, int);
  33. static void put_ptype(char *, int, int, int);
  34. static void tc_predef_np(void);
  35. static void put_pinit(ProcList *);
  36. void walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *);
  37. static void
  38. reverse_names(ProcList *p)
  39. {
  40. if (!p) return;
  41. reverse_names(p->nxt);
  42. fprintf(th, " \"%s\",\n", p->n->name);
  43. }
  44. void
  45. genheader(void)
  46. { ProcList *p; int i;
  47. if (separate == 2)
  48. { putunames(th);
  49. goto here;
  50. }
  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. { extern void c_add_stack(FILE *);
  71. ntimes(th, 0, 1, Header);
  72. c_add_stack(th);
  73. ntimes(th, 0, 1, Header0);
  74. }
  75. ntimes(th, 0, 1, Head1);
  76. LstSet = ZS;
  77. (void) doglobal("", PUTV);
  78. hastrack = c_add_sv(th);
  79. fprintf(th, " uchar sv[VECTORSZ];\n");
  80. fprintf(th, "} State");
  81. #ifdef SOLARIS
  82. fprintf(th,"\n#ifdef GCC\n");
  83. fprintf(th, "\t__attribute__ ((aligned(8)))");
  84. fprintf(th, "\n#endif\n\t");
  85. #endif
  86. fprintf(th, ";\n\n");
  87. fprintf(th, "#define HAS_TRACK %d\n", hastrack);
  88. if (separate != 2)
  89. dohidden();
  90. }
  91. void
  92. genaddproc(void)
  93. { ProcList *p;
  94. int i = 0;
  95. if (separate ==2) goto shortcut;
  96. fprintf(tc, "int\naddproc(int n");
  97. for (i = 0; i < Npars; i++)
  98. fprintf(tc, ", int par%d", i);
  99. ntimes(tc, 0, 1, Addp0);
  100. ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
  101. ntimes(tc, 0, 1, Addp1);
  102. if (has_provided)
  103. { fprintf(tt, "\nint\nprovided(int II, unsigned char ot, ");
  104. fprintf(tt, "int tt, Trans *t)\n");
  105. fprintf(tt, "{\n\tswitch(ot) {\n");
  106. }
  107. shortcut:
  108. tc_predef_np();
  109. for (p = rdy; p; p = p->nxt)
  110. { Pid = p->tn;
  111. put_pinit(p);
  112. }
  113. if (separate == 2) return;
  114. Pid = 0;
  115. if (has_provided)
  116. { fprintf(tt, "\tdefault: return 1; /* e.g., a claim */\n");
  117. fprintf(tt, "\t}\n\treturn 0;\n}\n");
  118. }
  119. ntimes(tc, i, i+1, R6);
  120. if (separate == 0)
  121. ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
  122. else
  123. ntimes(tc, 1, nrRdy, R5);
  124. ntimes(tc, 0, 1, R8a);
  125. }
  126. void
  127. do_locinits(FILE *fd)
  128. { ProcList *p;
  129. for (p = rdy; p; p = p->nxt)
  130. c_add_locinit(fd, p->tn, p->n->name);
  131. }
  132. void
  133. genother(void)
  134. { ProcList *p;
  135. switch (separate) {
  136. case 2:
  137. if (claimnr >= 0)
  138. ntimes(tc, claimnr, claimnr+1, R0); /* claim only */
  139. break;
  140. case 1:
  141. ntimes(tc, 0, 1, Code0);
  142. ntimes(tc, 0, claimnr, R0); /* all except claim */
  143. ntimes(tc, claimnr+1, nrRdy, R0);
  144. break;
  145. case 0:
  146. ntimes(tc, 0, 1, Code0);
  147. ntimes(tc, 0, nrRdy+1, R0); /* +1 for np_ */
  148. break;
  149. }
  150. for (p = rdy; p; p = p->nxt)
  151. end_labs(p->n, p->tn);
  152. switch (separate) {
  153. case 2:
  154. if (claimnr >= 0)
  155. ntimes(tc, claimnr, claimnr+1, R0a); /* claim only */
  156. return;
  157. case 1:
  158. ntimes(tc, 0, claimnr, R0a); /* all except claim */
  159. ntimes(tc, claimnr+1, nrRdy, R0a);
  160. fprintf(tc, " if (state_tables)\n");
  161. fprintf(tc, " ini_claim(%d, 0);\n", claimnr);
  162. break;
  163. case 0:
  164. ntimes(tc, 0, nrRdy, R0a); /* all */
  165. break;
  166. }
  167. ntimes(tc, 0, 1, R0b);
  168. if (separate == 1 && acceptors == 0)
  169. acceptors = 1; /* assume at least 1 acceptstate */
  170. ntimes(th, acceptors, acceptors+1, Code1);
  171. ntimes(th, progressors, progressors+1, Code3);
  172. ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */
  173. fprintf(tc, " iniglobals();\n");
  174. ntimes(tc, 0, 1, Code2a);
  175. ntimes(tc, 0, 1, Code2b); /* bfs option */
  176. ntimes(tc, 0, 1, Code2c);
  177. ntimes(tc, 0, nrRdy, R4);
  178. fprintf(tc, "}\n\n");
  179. fprintf(tc, "void\n");
  180. fprintf(tc, "iniglobals(void)\n{\n");
  181. if (doglobal("", INIV) > 0)
  182. { fprintf(tc, "#ifdef VAR_RANGES\n");
  183. (void) doglobal("logval(\"", LOGV);
  184. fprintf(tc, "#endif\n");
  185. }
  186. ntimes(tc, 1, nqs+1, R3);
  187. fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);");
  188. fprintf(tc, "\n}\n\n");
  189. }
  190. void
  191. gensvmap(void)
  192. {
  193. ntimes(tc, 0, 1, SvMap);
  194. }
  195. static struct {
  196. char *s, *t; int n, m, p;
  197. } ln[] = {
  198. {"end", "stopstate", 3, 0, 0},
  199. {"progress", "progstate", 8, 0, 1},
  200. {"accept", "accpstate", 6, 1, 0},
  201. {0, 0, 0, 0, 0},
  202. };
  203. static void
  204. end_labs(Symbol *s, int i)
  205. { int oln = lineno;
  206. Symbol *ofn = Fname;
  207. Label *l;
  208. int j; char foo[128];
  209. if ((i == claimnr && separate == 1)
  210. || (i != claimnr && separate == 2))
  211. return;
  212. for (l = labtab; l; l = l->nxt)
  213. for (j = 0; ln[j].n; j++)
  214. if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
  215. && strcmp(l->c->name, s->name) == 0)
  216. { fprintf(tc, "\t%s[%d][%d] = 1;\n",
  217. ln[j].t, i, l->e->seqno);
  218. acceptors += ln[j].m;
  219. progressors += ln[j].p;
  220. if (l->e->status & D_ATOM)
  221. { sprintf(foo, "%s label inside d_step",
  222. ln[j].s);
  223. goto complain;
  224. }
  225. if (j > 0 && (l->e->status & ATOM))
  226. { sprintf(foo, "%s label inside atomic",
  227. ln[j].s);
  228. complain: lineno = l->e->n->ln;
  229. Fname = l->e->n->fn;
  230. printf("spin: %3d:%s, warning, %s - is invisible\n",
  231. lineno, Fname?Fname->name:"-", foo);
  232. }
  233. }
  234. /* visible states -- through remote refs: */
  235. for (l = labtab; l; l = l->nxt)
  236. if (l->visible
  237. && strcmp(l->s->context->name, s->name) == 0)
  238. fprintf(tc, "\tvisstate[%d][%d] = 1;\n",
  239. i, l->e->seqno);
  240. lineno = oln;
  241. Fname = ofn;
  242. }
  243. void
  244. ntimes(FILE *fd, int n, int m, char *c[])
  245. {
  246. int i, j;
  247. for (j = 0; c[j]; j++)
  248. for (i = n; i < m; i++)
  249. { fprintf(fd, c[j], i, i, i, i, i, i);
  250. fprintf(fd, "\n");
  251. }
  252. }
  253. void
  254. prehint(Symbol *s)
  255. { Lextok *n;
  256. printf("spin: warning, ");
  257. if (!s) return;
  258. n = (s->context != ZS)?s->context->ini:s->ini;
  259. if (n)
  260. printf("line %3d %s, ", n->ln, n->fn->name);
  261. }
  262. void
  263. checktype(Symbol *sp, char *s)
  264. { char buf[128]; int i;
  265. if (!s
  266. || (sp->type != BYTE
  267. && sp->type != SHORT
  268. && sp->type != INT))
  269. return;
  270. if (sp->hidden&16) /* formal parameter */
  271. { ProcList *p; Lextok *f, *t;
  272. int posnr = 0;
  273. for (p = rdy; p; p = p->nxt)
  274. if (p->n->name
  275. && strcmp(s, p->n->name) == 0)
  276. break;
  277. if (p)
  278. for (f = p->p; f; f = f->rgt) /* list of types */
  279. for (t = f->lft; t; t = t->rgt, posnr++)
  280. if (t->sym
  281. && strcmp(t->sym->name, sp->name) == 0)
  282. { checkrun(sp, posnr);
  283. return;
  284. }
  285. } else if (!(sp->hidden&4))
  286. { if (!(verbose&32)) return;
  287. sputtype(buf, sp->type);
  288. i = (int) strlen(buf);
  289. while (buf[--i] == ' ') buf[i] = '\0';
  290. prehint(sp);
  291. if (sp->context)
  292. printf("proctype %s:", s);
  293. else
  294. printf("global");
  295. printf(" '%s %s' could be declared 'bit %s'\n",
  296. buf, sp->name, sp->name);
  297. } else if (sp->type != BYTE && !(sp->hidden&8))
  298. { if (!(verbose&32)) return;
  299. sputtype(buf, sp->type);
  300. i = (int) strlen(buf);
  301. while (buf[--i] == ' ') buf[i] = '\0';
  302. prehint(sp);
  303. if (sp->context)
  304. printf("proctype %s:", s);
  305. else
  306. printf("global");
  307. printf(" '%s %s' could be declared 'byte %s'\n",
  308. buf, sp->name, sp->name);
  309. }
  310. }
  311. int
  312. dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s)
  313. { int h, j, k=0; extern int nr_errs;
  314. Ordered *walk;
  315. Symbol *sp;
  316. char buf[64], buf2[128], buf3[128];
  317. if (dowhat == INIV)
  318. { /* initialize in order of declaration */
  319. for (walk = all_names; walk; walk = walk->next)
  320. { sp = walk->entry;
  321. if (sp->context
  322. && !sp->owner
  323. && strcmp(s, sp->context->name) == 0)
  324. { checktype(sp, s); /* fall through */
  325. if (!(sp->hidden&16))
  326. { sprintf(buf, "((P%d *)pptr(h))->", p);
  327. do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
  328. }
  329. k++;
  330. } }
  331. } else
  332. { for (j = 0; j < 8; j++)
  333. for (h = 0; h <= 1; h++)
  334. for (walk = all_names; walk; walk = walk->next)
  335. { sp = walk->entry;
  336. if (sp->context
  337. && !sp->owner
  338. && sp->type == Types[j]
  339. && ((h == 0 && sp->nel == 1) || (h == 1 && sp->nel > 1))
  340. && strcmp(s, sp->context->name) == 0)
  341. { switch (dowhat) {
  342. case LOGV:
  343. if (sp->type == CHAN
  344. && verbose == 0)
  345. break;
  346. sprintf(buf, "%s%s:", pre, s);
  347. { sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
  348. sprintf(buf3, ");\n");
  349. }
  350. do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
  351. break;
  352. case PUTV:
  353. sprintf(buf, "((P%d *)pptr(h))->", p);
  354. do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
  355. k++;
  356. break;
  357. }
  358. if (strcmp(s, ":never:") == 0)
  359. { printf("error: %s defines local %s\n",
  360. s, sp->name);
  361. nr_errs++;
  362. } } } }
  363. return k;
  364. }
  365. void
  366. c_chandump(FILE *fd)
  367. { Queue *q;
  368. char buf[256];
  369. int i;
  370. if (!qtab)
  371. { fprintf(fd, "void\nc_chandump(int unused) ");
  372. fprintf(fd, "{ unused = unused++; /* avoid complaints */ }\n");
  373. return;
  374. }
  375. fprintf(fd, "void\nc_chandump(int from)\n");
  376. fprintf(fd, "{ uchar *z; int slot;\n");
  377. fprintf(fd, " from--;\n");
  378. fprintf(fd, " if (from >= (int) now._nr_qs || from < 0)\n");
  379. fprintf(fd, " { printf(\"pan: bad qid %%d\\n\", from+1);\n");
  380. fprintf(fd, " return;\n");
  381. fprintf(fd, " }\n");
  382. fprintf(fd, " z = qptr(from);\n");
  383. fprintf(fd, " switch (((Q0 *)z)->_t) {\n");
  384. for (q = qtab; q; q = q->nxt)
  385. { fprintf(fd, " case %d:\n\t\t", q->qid);
  386. sprintf(buf, "((Q%d *)z)->", q->qid);
  387. fprintf(fd, "for (slot = 0; slot < %sQlen; slot++)\n\t\t", buf);
  388. fprintf(fd, "{ printf(\" [\");\n\t\t");
  389. for (i = 0; i < q->nflds; i++)
  390. { if (q->fld_width[i] == MTYPE)
  391. { fprintf(fd, "\tprintm(%scontents[slot].fld%d);\n\t\t",
  392. buf, i);
  393. } else
  394. fprintf(fd, "\tprintf(\"%%d,\", %scontents[slot].fld%d);\n\t\t",
  395. buf, i);
  396. }
  397. fprintf(fd, " printf(\"],\");\n\t\t");
  398. fprintf(fd, "}\n\t\t");
  399. fprintf(fd, "break;\n");
  400. }
  401. fprintf(fd, " }\n");
  402. fprintf(fd, " printf(\"\\n\");\n}\n");
  403. }
  404. void
  405. c_var(FILE *fd, char *pref, Symbol *sp)
  406. { char buf[256];
  407. int i;
  408. switch (sp->type) {
  409. case STRUCT:
  410. /* c_struct(fd, pref, sp); */
  411. fprintf(fd, "\t\tprintf(\"\t(struct %s)\\n\");\n",
  412. sp->name);
  413. sprintf(buf, "%s%s.", pref, sp->name);
  414. c_struct(fd, buf, sp);
  415. break;
  416. case BIT: case BYTE:
  417. case SHORT: case INT:
  418. case UNSIGNED:
  419. sputtype(buf, sp->type);
  420. if (sp->nel == 1)
  421. { fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
  422. buf, sp->name, pref, sp->name);
  423. } else
  424. { fprintf(fd, "\t{\tint l_in;\n");
  425. fprintf(fd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
  426. fprintf(fd, "\t\t{\n");
  427. fprintf(fd, "\t\t\tprintf(\"\t%s %s[%%d]:\t%%d\\n\", l_in, %s%s[l_in]);\n",
  428. buf, sp->name, pref, sp->name);
  429. fprintf(fd, "\t\t}\n");
  430. fprintf(fd, "\t}\n");
  431. }
  432. break;
  433. case CHAN:
  434. if (sp->nel == 1)
  435. { fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ",
  436. sp->name);
  437. fprintf(fd, "%s%s, q_len(%s%s));\n",
  438. pref, sp->name, pref, sp->name);
  439. fprintf(fd, "\tc_chandump(%s%s);\n", pref, sp->name);
  440. } else
  441. for (i = 0; i < sp->nel; i++)
  442. { fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
  443. sp->name, i);
  444. fprintf(fd, "%s%s[%d], q_len(%s%s[%d]));\n",
  445. pref, sp->name, i, pref, sp->name, i);
  446. fprintf(fd, "\tc_chandump(%s%s[%d]);\n",
  447. pref, sp->name, i);
  448. }
  449. break;
  450. }
  451. }
  452. int
  453. c_splurge_any(ProcList *p)
  454. { Ordered *walk;
  455. Symbol *sp;
  456. if (strcmp(p->n->name, ":never:") != 0
  457. && strcmp(p->n->name, ":trace:") != 0
  458. && strcmp(p->n->name, ":notrace:") != 0)
  459. for (walk = all_names; walk; walk = walk->next)
  460. { sp = walk->entry;
  461. if (!sp->context
  462. || sp->type == 0
  463. || strcmp(sp->context->name, p->n->name) != 0
  464. || sp->owner || (sp->hidden&1)
  465. || (sp->type == MTYPE && ismtype(sp->name)))
  466. continue;
  467. return 1;
  468. }
  469. return 0;
  470. }
  471. void
  472. c_splurge(FILE *fd, ProcList *p)
  473. { Ordered *walk;
  474. Symbol *sp;
  475. char pref[64];
  476. if (strcmp(p->n->name, ":never:") != 0
  477. && strcmp(p->n->name, ":trace:") != 0
  478. && strcmp(p->n->name, ":notrace:") != 0)
  479. for (walk = all_names; walk; walk = walk->next)
  480. { sp = walk->entry;
  481. if (!sp->context
  482. || sp->type == 0
  483. || strcmp(sp->context->name, p->n->name) != 0
  484. || sp->owner || (sp->hidden&1)
  485. || (sp->type == MTYPE && ismtype(sp->name)))
  486. continue;
  487. sprintf(pref, "((P%d *)pptr(pid))->", p->tn);
  488. c_var(fd, pref, sp);
  489. }
  490. }
  491. void
  492. c_wrapper(FILE *fd) /* allow pan.c to print out global sv entries */
  493. { Ordered *walk;
  494. ProcList *p;
  495. Symbol *sp;
  496. Lextok *n;
  497. extern Lextok *Mtype;
  498. int j;
  499. fprintf(fd, "void\nc_globals(void)\n{\t/* int i; */\n");
  500. fprintf(fd, " printf(\"global vars:\\n\");\n");
  501. for (walk = all_names; walk; walk = walk->next)
  502. { sp = walk->entry;
  503. if (sp->context || sp->owner || (sp->hidden&1)
  504. || (sp->type == MTYPE && ismtype(sp->name)))
  505. continue;
  506. c_var(fd, "now.", sp);
  507. }
  508. fprintf(fd, "}\n");
  509. fprintf(fd, "void\nc_locals(int pid, int tp)\n{\t/* int i; */\n");
  510. fprintf(fd, " switch(tp) {\n");
  511. for (p = rdy; p; p = p->nxt)
  512. { fprintf(fd, " case %d:\n", p->tn);
  513. fprintf(fd, " \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
  514. p->n->name);
  515. if (c_splurge_any(p))
  516. { fprintf(fd, " \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
  517. p->n->name);
  518. c_splurge(fd, p);
  519. } else
  520. { fprintf(fd, " \t/* none */\n");
  521. }
  522. fprintf(fd, " \tbreak;\n");
  523. }
  524. fprintf(fd, " }\n}\n");
  525. fprintf(fd, "void\nprintm(int x)\n{\n");
  526. fprintf(fd, " switch (x) {\n");
  527. for (n = Mtype, j = 1; n && j; n = n->rgt, j++)
  528. fprintf(fd, "\tcase %d: Printf(\"%s\"); break;\n",
  529. j, n->lft->sym->name);
  530. fprintf(fd, " default: Printf(\"%%d\", x);\n");
  531. fprintf(fd, " }\n");
  532. fprintf(fd, "}\n");
  533. }
  534. static int
  535. doglobal(char *pre, int dowhat)
  536. { Ordered *walk;
  537. Symbol *sp;
  538. int j, cnt = 0;
  539. for (j = 0; j < 8; j++)
  540. for (walk = all_names; walk; walk = walk->next)
  541. { sp = walk->entry;
  542. if (!sp->context
  543. && !sp->owner
  544. && sp->type == Types[j])
  545. { if (Types[j] != MTYPE || !ismtype(sp->name))
  546. switch (dowhat) {
  547. case LOGV:
  548. if (sp->type == CHAN
  549. && verbose == 0)
  550. break;
  551. if (sp->hidden&1)
  552. break;
  553. do_var(tc, dowhat, "", sp,
  554. pre, "\", now.", ");\n");
  555. break;
  556. case INIV:
  557. checktype(sp, (char *) 0);
  558. cnt++; /* fall through */
  559. case PUTV:
  560. do_var(tc, dowhat, (sp->hidden&1)?"":"now.", sp,
  561. "", " = ", ";\n");
  562. break;
  563. } } }
  564. return cnt;
  565. }
  566. static void
  567. dohidden(void)
  568. { Ordered *walk;
  569. Symbol *sp;
  570. int j;
  571. for (j = 0; j < 8; j++)
  572. for (walk = all_names; walk; walk = walk->next)
  573. { sp = walk->entry;
  574. if ((sp->hidden&1)
  575. && sp->type == Types[j])
  576. { if (sp->context || sp->owner)
  577. fatal("cannot hide non-globals (%s)", sp->name);
  578. if (sp->type == CHAN)
  579. fatal("cannot hide channels (%s)", sp->name);
  580. fprintf(th, "/* hidden variable: */");
  581. typ2c(sp);
  582. } }
  583. fprintf(th, "int _; /* a predefined write-only variable */\n\n");
  584. }
  585. void
  586. do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
  587. char *pre, char *sep, char *ter)
  588. { int i;
  589. switch(dowhat) {
  590. case PUTV:
  591. if (sp->hidden&1) break;
  592. typ2c(sp);
  593. break;
  594. case LOGV:
  595. case INIV:
  596. if (sp->type == STRUCT)
  597. { /* struct may contain a chan */
  598. walk_struct(ofd, dowhat, s, sp, pre, sep, ter);
  599. break;
  600. }
  601. if (!sp->ini && dowhat != LOGV) /* it defaults to 0 */
  602. break;
  603. if (sp->nel == 1)
  604. { fprintf(ofd, "\t\t%s%s%s%s",
  605. pre, s, sp->name, sep);
  606. if (dowhat == LOGV)
  607. fprintf(ofd, "%s%s", s, sp->name);
  608. else
  609. do_init(ofd, sp);
  610. fprintf(ofd, "%s", ter);
  611. } else
  612. { if (sp->ini && sp->ini->ntyp == CHAN)
  613. { for (i = 0; i < sp->nel; i++)
  614. { fprintf(ofd, "\t\t%s%s%s[%d]%s",
  615. pre, s, sp->name, i, sep);
  616. if (dowhat == LOGV)
  617. fprintf(ofd, "%s%s[%d]",
  618. s, sp->name, i);
  619. else
  620. do_init(ofd, sp);
  621. fprintf(ofd, "%s", ter);
  622. }
  623. } else
  624. { fprintf(ofd, "\t{\tint l_in;\n");
  625. fprintf(ofd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
  626. fprintf(ofd, "\t\t{\n");
  627. fprintf(ofd, "\t\t\t%s%s%s[l_in]%s",
  628. pre, s, sp->name, sep);
  629. if (dowhat == LOGV)
  630. fprintf(ofd, "%s%s[l_in]", s, sp->name);
  631. else
  632. putstmnt(ofd, sp->ini, 0);
  633. fprintf(ofd, "%s", ter);
  634. fprintf(ofd, "\t\t}\n");
  635. fprintf(ofd, "\t}\n");
  636. } }
  637. break;
  638. }
  639. }
  640. static void
  641. do_init(FILE *ofd, Symbol *sp)
  642. { int i; extern Queue *ltab[];
  643. if (sp->ini
  644. && sp->type == CHAN
  645. && ((i = qmake(sp)) > 0))
  646. { if (sp->ini->ntyp == CHAN)
  647. fprintf(ofd, "addqueue(%d, %d)",
  648. i, ltab[i-1]->nslots == 0);
  649. else
  650. fprintf(ofd, "%d", i);
  651. } else
  652. putstmnt(ofd, sp->ini, 0);
  653. }
  654. static int
  655. blog(int n) /* for small log2 without rounding problems */
  656. { int m=1, r=2;
  657. while (r < n) { m++; r *= 2; }
  658. return 1+m;
  659. }
  660. static void
  661. put_ptype(char *s, int i, int m0, int m1)
  662. { int k;
  663. if (strcmp(s, ":init:") == 0)
  664. fprintf(th, "#define Pinit ((P%d *)this)\n", i);
  665. if (strcmp(s, ":never:") != 0
  666. && strcmp(s, ":trace:") != 0
  667. && strcmp(s, ":notrace:") != 0
  668. && strcmp(s, ":init:") != 0
  669. && strcmp(s, "_:never_template:_") != 0
  670. && strcmp(s, "np_") != 0)
  671. fprintf(th, "#define P%s ((P%d *)this)\n", s, i);
  672. fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
  673. fprintf(th, " unsigned _pid : 8; /* 0..255 */\n");
  674. fprintf(th, " unsigned _t : %d; /* proctype */\n", blog(m1));
  675. fprintf(th, " unsigned _p : %d; /* state */\n", blog(m0));
  676. LstSet = ZS;
  677. nBits = 8 + blog(m1) + blog(m0);
  678. k = dolocal(tc, "", PUTV, i, s); /* includes pars */
  679. c_add_loc(th, s);
  680. fprintf(th, "} P%d;\n", i);
  681. if ((!LstSet && k > 0) || has_state)
  682. fprintf(th, "#define Air%d 0\n", i);
  683. else
  684. { fprintf(th, "#define Air%d (sizeof(P%d) - ", i, i);
  685. if (k == 0)
  686. { fprintf(th, "%d", (nBits+7)/8);
  687. goto done;
  688. }
  689. if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
  690. || LstSet->nel != 1)
  691. { fprintf(th, "Offsetof(P%d, %s) - %d*sizeof(",
  692. i, LstSet->name, LstSet->nel);
  693. }
  694. switch(LstSet->type) {
  695. case UNSIGNED:
  696. fprintf(th, "%d", (nBits+7)/8);
  697. break;
  698. case BIT:
  699. if (LstSet->nel == 1)
  700. { fprintf(th, "%d", (nBits+7)/8);
  701. break;
  702. } /* else fall through */
  703. case MTYPE: case BYTE: case CHAN:
  704. fprintf(th, "uchar)"); break;
  705. case SHORT:
  706. fprintf(th, "short)"); break;
  707. case INT:
  708. fprintf(th, "int)"); break;
  709. default:
  710. fatal("cannot happen Air %s",
  711. LstSet->name);
  712. }
  713. done: fprintf(th, ")\n");
  714. }
  715. }
  716. static void
  717. tc_predef_np(void)
  718. { int i = nrRdy; /* 1+ highest proctype nr */
  719. fprintf(th, "#define _NP_ %d\n", i);
  720. /* if (separate == 2) fprintf(th, "extern "); */
  721. fprintf(th, "uchar reached%d[3]; /* np_ */\n", i);
  722. fprintf(th, "#define nstates%d 3 /* np_ */\n", i);
  723. fprintf(th, "#define endstate%d 2 /* np_ */\n\n", i);
  724. fprintf(th, "#define start%d 0 /* np_ */\n", i);
  725. fprintf(tc, "\tcase %d: /* np_ */\n", i);
  726. if (separate == 1)
  727. { fprintf(tc, "\t\tini_claim(%d, h);\n", i);
  728. } else
  729. { fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
  730. fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", i);
  731. fprintf(tc, "\t\treached%d[0] = 1;\n", i);
  732. fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", i);
  733. }
  734. fprintf(tc, "\t\tbreak;\n");
  735. }
  736. static void
  737. put_pinit(ProcList *P)
  738. { Lextok *fp, *fpt, *t;
  739. Element *e = P->s->frst;
  740. Symbol *s = P->n;
  741. Lextok *p = P->p;
  742. int i = P->tn;
  743. int ini, j, k;
  744. if (i == claimnr
  745. && separate == 1)
  746. { fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
  747. fprintf(tc, "\t\tini_claim(%d, h);\n", i);
  748. fprintf(tc, "\t\tbreak;\n");
  749. return;
  750. }
  751. if (i != claimnr
  752. && separate == 2)
  753. return;
  754. ini = huntele(e, e->status, -1)->seqno;
  755. fprintf(th, "#define start%d %d\n", i, ini);
  756. if (i == claimnr)
  757. fprintf(th, "#define start_claim %d\n", ini);
  758. if (i == eventmapnr)
  759. fprintf(th, "#define start_event %d\n", ini);
  760. fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
  761. fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
  762. fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;", i, ini);
  763. fprintf(tc, " reached%d[%d]=1;\n", i, ini);
  764. if (has_provided)
  765. { fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
  766. if (P->prov)
  767. { fprintf(tt, "if (");
  768. putstmnt(tt, P->prov, 0);
  769. fprintf(tt, ")\n\t\t\t");
  770. }
  771. fprintf(tt, "return 1;\n");
  772. if (P->prov)
  773. fprintf(tt, "\t\tbreak;\n");
  774. }
  775. fprintf(tc, "\t\t/* params: */\n");
  776. for (fp = p, j=0; fp; fp = fp->rgt)
  777. for (fpt = fp->lft; fpt; fpt = fpt->rgt, j++)
  778. { t = (fpt->ntyp == ',') ? fpt->lft : fpt;
  779. if (t->sym->nel != 1)
  780. { lineno = t->ln;
  781. Fname = t->fn;
  782. fatal("array in parameter list, %s",
  783. t->sym->name);
  784. }
  785. fprintf(tc, "\t\t((P%d *)pptr(h))->", i);
  786. if (t->sym->type == STRUCT)
  787. { if (full_name(tc, t, t->sym, 1))
  788. { lineno = t->ln;
  789. Fname = t->fn;
  790. fatal("hidden array in parameter %s",
  791. t->sym->name);
  792. }
  793. } else
  794. fprintf(tc, "%s", t->sym->name);
  795. fprintf(tc, " = par%d;\n", j);
  796. }
  797. fprintf(tc, "\t\t/* locals: */\n");
  798. k = dolocal(tc, "", INIV, i, s->name);
  799. if (k > 0)
  800. { fprintf(tc, "#ifdef VAR_RANGES\n");
  801. (void) dolocal(tc, "logval(\"", LOGV, i, s->name);
  802. fprintf(tc, "#endif\n");
  803. }
  804. fprintf(tc, "#ifdef HAS_CODE\n");
  805. fprintf(tc, "\t\tlocinit%d(h);\n", i);
  806. fprintf(tc, "#endif\n");
  807. dumpclaims(tc, i, s->name);
  808. fprintf(tc, "\t break;\n");
  809. }
  810. Element *
  811. huntstart(Element *f)
  812. { Element *e = f;
  813. Element *elast = (Element *) 0;
  814. int cnt = 0;
  815. while (elast != e && cnt++ < 200) /* new 4.0.8 */
  816. { elast = e;
  817. if (e->n)
  818. { if (e->n->ntyp == '.' && e->nxt)
  819. e = e->nxt;
  820. else if (e->n->ntyp == UNLESS)
  821. e = e->sub->this->frst;
  822. } }
  823. if (cnt >= 200 || !e)
  824. fatal("confusing control structure", (char *) 0);
  825. return e;
  826. }
  827. Element *
  828. huntele(Element *f, int o, int stopat)
  829. { Element *g, *e = f;
  830. int cnt=0; /* a precaution against loops */
  831. if (e)
  832. for (cnt = 0; cnt < 200 && e->n; cnt++)
  833. {
  834. if (e->seqno == stopat)
  835. break;
  836. switch (e->n->ntyp) {
  837. case GOTO:
  838. g = get_lab(e->n,1);
  839. cross_dsteps(e->n, g->n);
  840. break;
  841. case '.':
  842. case BREAK:
  843. if (!e->nxt)
  844. return e;
  845. g = e->nxt;
  846. break;
  847. case UNLESS:
  848. g = huntele(e->sub->this->frst, o, stopat);
  849. break;
  850. case D_STEP:
  851. case ATOMIC:
  852. case NON_ATOMIC:
  853. default:
  854. return e;
  855. }
  856. if ((o & ATOM) && !(g->status & ATOM))
  857. return e;
  858. e = g;
  859. }
  860. if (cnt >= 200 || !e)
  861. fatal("confusing control structure", (char *) 0);
  862. return e;
  863. }
  864. void
  865. typ2c(Symbol *sp)
  866. { int wsbits = sizeof(long)*8; /* wordsize in bits */
  867. switch (sp->type) {
  868. case UNSIGNED:
  869. if (sp->hidden&1)
  870. fprintf(th, "\tuchar %s;", sp->name);
  871. else
  872. fprintf(th, "\tunsigned %s : %d",
  873. sp->name, sp->nbits);
  874. LstSet = sp;
  875. if (nBits%wsbits > 0
  876. && wsbits - nBits%wsbits < sp->nbits)
  877. { /* must padd to a word-boundary */
  878. nBits += wsbits - nBits%wsbits;
  879. }
  880. nBits += sp->nbits;
  881. break;
  882. case BIT:
  883. if (sp->nel == 1 && !(sp->hidden&1))
  884. { fprintf(th, "\tunsigned %s : 1", sp->name);
  885. LstSet = sp;
  886. nBits++;
  887. break;
  888. } /* else fall through */
  889. if (!(sp->hidden&1) && (verbose&32))
  890. printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
  891. sp->name, sp->nel);
  892. nBits += 8*sp->nel; /* mapped onto array of uchars */
  893. case MTYPE:
  894. case BYTE:
  895. case CHAN: /* good for up to 255 channels */
  896. fprintf(th, "\tuchar %s", sp->name);
  897. LstSet = sp;
  898. break;
  899. case SHORT:
  900. fprintf(th, "\tshort %s", sp->name);
  901. LstSet = sp;
  902. break;
  903. case INT:
  904. fprintf(th, "\tint %s", sp->name);
  905. LstSet = sp;
  906. break;
  907. case STRUCT:
  908. if (!sp->Snm)
  909. fatal("undeclared structure element %s", sp->name);
  910. fprintf(th, "\tstruct %s %s",
  911. sp->Snm->name,
  912. sp->name);
  913. LstSet = ZS;
  914. break;
  915. case CODE_FRAG:
  916. case PREDEF:
  917. return;
  918. default:
  919. fatal("variable %s undeclared", sp->name);
  920. }
  921. if (sp->nel != 1)
  922. fprintf(th, "[%d]", sp->nel);
  923. fprintf(th, ";\n");
  924. }
  925. static void
  926. ncases(FILE *fd, int p, int n, int m, char *c[])
  927. { int i, j;
  928. for (j = 0; c[j]; j++)
  929. for (i = n; i < m; i++)
  930. { fprintf(fd, c[j], i, p, i);
  931. fprintf(fd, "\n");
  932. }
  933. }
  934. void
  935. qlen_type(int qmax)
  936. {
  937. fprintf(th, "\t");
  938. if (qmax < 256)
  939. fprintf(th, "uchar");
  940. else if (qmax < 65535)
  941. fprintf(th, "ushort");
  942. else
  943. fprintf(th, "uint");
  944. fprintf(th, " Qlen; /* q_size */\n");
  945. }
  946. void
  947. genaddqueue(void)
  948. { char buf0[256];
  949. int j, qmax = 0;
  950. Queue *q;
  951. ntimes(tc, 0, 1, Addq0);
  952. if (has_io && !nqs)
  953. fprintf(th, "#define NQS 1 /* nqs=%d, but has_io */\n", nqs);
  954. else
  955. fprintf(th, "#define NQS %d\n", nqs);
  956. fprintf(th, "short q_flds[%d];\n", nqs+1);
  957. fprintf(th, "short q_max[%d];\n", nqs+1);
  958. for (q = qtab; q; q = q->nxt)
  959. if (q->nslots > qmax)
  960. qmax = q->nslots;
  961. for (q = qtab; q; q = q->nxt)
  962. { j = q->qid;
  963. fprintf(tc, "\tcase %d: j = sizeof(Q%d);", j, j);
  964. fprintf(tc, " q_flds[%d] = %d;", j, q->nflds);
  965. fprintf(tc, " q_max[%d] = %d;", j, max(1,q->nslots));
  966. fprintf(tc, " break;\n");
  967. fprintf(th, "typedef struct Q%d {\n", j);
  968. qlen_type(qmax); /* 4.2.2 */
  969. fprintf(th, " uchar _t; /* q_type */\n");
  970. fprintf(th, " struct {\n");
  971. for (j = 0; j < q->nflds; j++)
  972. { switch (q->fld_width[j]) {
  973. case BIT:
  974. if (q->nflds != 1)
  975. { fprintf(th, "\t\tunsigned");
  976. fprintf(th, " fld%d : 1;\n", j);
  977. break;
  978. } /* else fall through: smaller struct */
  979. case MTYPE:
  980. case CHAN:
  981. case BYTE:
  982. fprintf(th, "\t\tuchar fld%d;\n", j);
  983. break;
  984. case SHORT:
  985. fprintf(th, "\t\tshort fld%d;\n", j);
  986. break;
  987. case INT:
  988. fprintf(th, "\t\tint fld%d;\n", j);
  989. break;
  990. default:
  991. fatal("bad channel spec", "");
  992. }
  993. }
  994. fprintf(th, " } contents[%d];\n", max(1, q->nslots));
  995. fprintf(th, "} Q%d;\n", q->qid);
  996. }
  997. fprintf(th, "typedef struct Q0 {\t/* generic q */\n");
  998. qlen_type(qmax); /* 4.2.2 */
  999. fprintf(th, " uchar _t;\n");
  1000. fprintf(th, "} Q0;\n");
  1001. ntimes(tc, 0, 1, Addq1);
  1002. if (has_random)
  1003. { fprintf(th, "int Q_has(int");
  1004. for (j = 0; j < Mpars; j++)
  1005. fprintf(th, ", int, int");
  1006. fprintf(th, ");\n");
  1007. fprintf(tc, "int\nQ_has(int into");
  1008. for (j = 0; j < Mpars; j++)
  1009. fprintf(tc, ", int want%d, int fld%d", j, j);
  1010. fprintf(tc, ")\n");
  1011. fprintf(tc, "{ int i;\n\n");
  1012. fprintf(tc, " if (!into--)\n");
  1013. fprintf(tc, " uerror(\"ref to unknown chan ");
  1014. fprintf(tc, "(recv-poll)\");\n\n");
  1015. fprintf(tc, " if (into >= now._nr_qs || into < 0)\n");
  1016. fprintf(tc, " Uerror(\"qrecv bad queue#\");\n\n");
  1017. fprintf(tc, " for (i = 0; i < ((Q0 *)qptr(into))->Qlen;");
  1018. fprintf(tc, " i++)\n");
  1019. fprintf(tc, " {\n");
  1020. for (j = 0; j < Mpars; j++)
  1021. { fprintf(tc, " if (want%d && ", j);
  1022. fprintf(tc, "qrecv(into+1, i, %d, 0) != fld%d)\n",
  1023. j, j);
  1024. fprintf(tc, " continue;\n");
  1025. }
  1026. fprintf(tc, " return i+1;\n");
  1027. fprintf(tc, " }\n");
  1028. fprintf(tc, " return 0;\n");
  1029. fprintf(tc, "}\n");
  1030. }
  1031. fprintf(tc, "#if NQS>0\n");
  1032. fprintf(tc, "void\nqsend(int into, int sorted");
  1033. for (j = 0; j < Mpars; j++)
  1034. fprintf(tc, ", int fld%d", j);
  1035. fprintf(tc, ")\n");
  1036. ntimes(tc, 0, 1, Addq11);
  1037. for (q = qtab; q; q = q->nxt)
  1038. { sprintf(buf0, "((Q%d *)z)->", q->qid);
  1039. fprintf(tc, "\tcase %d:%s\n", q->qid,
  1040. (q->nslots)?"":" /* =rv= */");
  1041. if (q->nslots == 0) /* reset handshake point */
  1042. fprintf(tc, "\t\t(trpt+2)->o_m = 0;\n");
  1043. if (has_sorted)
  1044. { fprintf(tc, "\t\tif (!sorted) goto append%d;\n", q->qid);
  1045. fprintf(tc, "\t\tfor (j = 0; j < %sQlen; j++)\n", buf0);
  1046. fprintf(tc, "\t\t{\t/* find insertion point */\n");
  1047. sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
  1048. for (j = 0; j < q->nflds; j++)
  1049. { fprintf(tc, "\t\t\tif (fld%d > %s%d) continue;\n",
  1050. j, buf0, j);
  1051. fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
  1052. fprintf(tc, "goto found%d;\n\n", q->qid);
  1053. }
  1054. fprintf(tc, "\t\t}\n");
  1055. fprintf(tc, "\tfound%d:\n", q->qid);
  1056. sprintf(buf0, "((Q%d *)z)->", q->qid);
  1057. fprintf(tc, "\t\tfor (k = %sQlen - 1; k >= j; k--)\n", buf0);
  1058. fprintf(tc, "\t\t{\t/* shift up */\n");
  1059. for (j = 0; j < q->nflds; j++)
  1060. { fprintf(tc, "\t\t\t%scontents[k+1].fld%d = ",
  1061. buf0, j);
  1062. fprintf(tc, "%scontents[k].fld%d;\n",
  1063. buf0, j);
  1064. }
  1065. fprintf(tc, "\t\t}\n");
  1066. fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
  1067. }
  1068. fprintf(tc, "#ifdef HAS_SORTED\n");
  1069. fprintf(tc, "\t\t(trpt+1)->ipt = j;\n"); /* ipt was bup.oval */
  1070. fprintf(tc, "#endif\n");
  1071. fprintf(tc, "\t\t%sQlen = %sQlen + 1;\n", buf0, buf0);
  1072. sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
  1073. for (j = 0; j < q->nflds; j++)
  1074. fprintf(tc, "\t\t%s%d = fld%d;\n", buf0, j, j);
  1075. fprintf(tc, "\t\tbreak;\n");
  1076. }
  1077. ntimes(tc, 0, 1, Addq2);
  1078. for (q = qtab; q; q = q->nxt)
  1079. fprintf(tc, "\tcase %d: return %d;\n", q->qid, (!q->nslots));
  1080. ntimes(tc, 0, 1, Addq3);
  1081. for (q = qtab; q; q = q->nxt)
  1082. fprintf(tc, "\tcase %d: return (q_sz(from) == %d);\n",
  1083. q->qid, max(1, q->nslots));
  1084. ntimes(tc, 0, 1, Addq4);
  1085. for (q = qtab; q; q = q->nxt)
  1086. { sprintf(buf0, "((Q%d *)z)->", q->qid);
  1087. fprintf(tc, " case %d:%s\n\t\t",
  1088. q->qid, (q->nslots)?"":" /* =rv= */");
  1089. if (q->nflds == 1)
  1090. { fprintf(tc, "if (fld == 0) r = %s", buf0);
  1091. fprintf(tc, "contents[slot].fld0;\n");
  1092. } else
  1093. { fprintf(tc, "switch (fld) {\n");
  1094. ncases(tc, q->qid, 0, q->nflds, R12);
  1095. fprintf(tc, "\t\tdefault: Uerror");
  1096. fprintf(tc, "(\"too many fields in recv\");\n");
  1097. fprintf(tc, "\t\t}\n");
  1098. }
  1099. fprintf(tc, "\t\tif (done)\n");
  1100. if (q->nslots == 0)
  1101. { fprintf(tc, "\t\t{ j = %sQlen - 1;\n", buf0);
  1102. fprintf(tc, "\t\t %sQlen = 0;\n", buf0);
  1103. sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
  1104. } else
  1105. { fprintf(tc, "\t\t{ j = %sQlen;\n", buf0);
  1106. fprintf(tc, "\t\t %sQlen = --j;\n", buf0);
  1107. fprintf(tc, "\t\t for (k=slot; k<j; k++)\n");
  1108. fprintf(tc, "\t\t {\n");
  1109. sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
  1110. for (j = 0; j < q->nflds; j++)
  1111. { fprintf(tc, "\t%s[k].fld%d = \n", buf0, j);
  1112. fprintf(tc, "\t\t%s[k+1].fld%d;\n", buf0, j);
  1113. }
  1114. fprintf(tc, "\t\t }\n");
  1115. }
  1116. for (j = 0; j < q->nflds; j++)
  1117. fprintf(tc, "%s[j].fld%d = 0;\n", buf0, j);
  1118. fprintf(tc, "\t\t\tif (fld+1 != %d)\n\t\t\t", q->nflds);
  1119. fprintf(tc, "\tuerror(\"missing pars in receive\");\n");
  1120. /* incompletely received msgs cannot be unrecv'ed */
  1121. fprintf(tc, "\t\t}\n");
  1122. fprintf(tc, "\t\tbreak;\n");
  1123. }
  1124. ntimes(tc, 0, 1, Addq5);
  1125. for (q = qtab; q; q = q->nxt)
  1126. fprintf(tc, " case %d: j = sizeof(Q%d); break;\n",
  1127. q->qid, q->qid);
  1128. ntimes(tc, 0, 1, R8b);
  1129. ntimes(th, 0, 1, Proto); /* tag on function prototypes */
  1130. fprintf(th, "void qsend(int, int");
  1131. for (j = 0; j < Mpars; j++)
  1132. fprintf(th, ", int");
  1133. fprintf(th, ");\n");
  1134. fprintf(th, "#define Addproc(x) addproc(x");
  1135. for (j = 0; j < Npars; j++)
  1136. fprintf(th, ", 0");
  1137. fprintf(th, ")\n");
  1138. }