1 /***** spin: pangen1.c *****/
3 /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
4 /* All Rights Reserved. This software is for educational purposes only. */
5 /* No guarantee whatsoever is expressed or implied by the distribution of */
6 /* this code. Permission is given to distribute this code provided that */
7 /* this introductory message is not removed and no monies are exchanged. */
8 /* Software written by Gerard J. Holzmann. For tool documentation see: */
9 /* http://spinroot.com/ */
10 /* Send all bug-reports and/or questions to: bugs@spinroot.com */
17 extern FILE *tc, *th, *tt;
19 extern Ordered *all_names;
23 extern int lineno, verbose, Pid, separate;
24 extern int nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
25 extern short has_sorted, has_random, has_provided;
27 int Npars=0, u_sync=0, u_async=0, hastrack = 1;
29 short has_state=0; /* code contains c_state */
31 static Symbol *LstSet=ZS;
32 static int acceptors=0, progressors=0, nBits=0;
33 static int Types[] = { UNSIGNED, BIT, BYTE, CHAN, MTYPE, SHORT, INT, STRUCT };
35 static int doglobal(char *, int);
36 static void dohidden(void);
37 static void do_init(FILE *, Symbol *);
38 static void end_labs(Symbol *, int);
39 static void put_ptype(char *, int, int, int);
40 static void tc_predef_np(void);
41 static void put_pinit(ProcList *);
42 void walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *);
45 reverse_names(ProcList *p)
48 reverse_names(p->nxt);
49 fprintf(th, " \"%s\",\n", p->n->name);
61 fprintf(th, "#define SYNC %d\n", u_sync);
62 fprintf(th, "#define ASYNC %d\n\n", u_async);
66 fprintf(tc, "short Air[] = { ");
67 for (p = rdy, i=0; p; p = p->nxt, i++)
68 fprintf(tc, "%s (short) Air%d", (p!=rdy)?",":"", i);
69 fprintf(tc, ", (short) Air%d", i); /* np_ */
72 fprintf(th, "char *procname[] = {\n");
74 fprintf(th, " \":np_:\",\n");
75 fprintf(th, "};\n\n");
78 for (p = rdy; p; p = p->nxt)
79 put_ptype(p->n->name, p->tn, mst, nrRdy+1);
81 put_ptype("np_", nrRdy, mst, nrRdy+1);
83 ntimes(th, 0, 1, Head0);
86 { extern void c_add_stack(FILE *);
88 ntimes(th, 0, 1, Header);
90 ntimes(th, 0, 1, Header0);
92 ntimes(th, 0, 1, Head1);
95 (void) doglobal("", PUTV);
97 hastrack = c_add_sv(th);
99 fprintf(th, " uchar sv[VECTORSZ];\n");
100 fprintf(th, "} State");
102 fprintf(th,"\n#ifdef GCC\n");
103 fprintf(th, "\t__attribute__ ((aligned(8)))");
104 fprintf(th, "\n#endif\n\t");
106 fprintf(th, ";\n\n");
108 fprintf(th, "#define HAS_TRACK %d\n", hastrack);
119 if (separate ==2) goto shortcut;
121 fprintf(tc, "int\naddproc(int n");
122 for (i = 0; i < Npars; i++)
123 fprintf(tc, ", int par%d", i);
125 ntimes(tc, 0, 1, Addp0);
126 ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
127 ntimes(tc, 0, 1, Addp1);
130 { fprintf(tt, "\nint\nprovided(int II, unsigned char ot, ");
131 fprintf(tt, "int tt, Trans *t)\n");
132 fprintf(tt, "{\n\tswitch(ot) {\n");
136 for (p = rdy; p; p = p->nxt)
140 if (separate == 2) return;
144 { fprintf(tt, "\tdefault: return 1; /* e.g., a claim */\n");
145 fprintf(tt, "\t}\n\treturn 0;\n}\n");
148 ntimes(tc, i, i+1, R6);
150 ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
152 ntimes(tc, 1, nrRdy, R5);
153 ntimes(tc, 0, 1, R8a);
157 do_locinits(FILE *fd)
160 for (p = rdy; p; p = p->nxt)
161 c_add_locinit(fd, p->tn, p->n->name);
171 ntimes(tc, claimnr, claimnr+1, R0); /* claim only */
174 ntimes(tc, 0, 1, Code0);
175 ntimes(tc, 0, claimnr, R0); /* all except claim */
176 ntimes(tc, claimnr+1, nrRdy, R0);
179 ntimes(tc, 0, 1, Code0);
180 ntimes(tc, 0, nrRdy+1, R0); /* +1 for np_ */
184 for (p = rdy; p; p = p->nxt)
185 end_labs(p->n, p->tn);
190 ntimes(tc, claimnr, claimnr+1, R0a); /* claim only */
193 ntimes(tc, 0, claimnr, R0a); /* all except claim */
194 ntimes(tc, claimnr+1, nrRdy, R0a);
195 fprintf(tc, " if (state_tables)\n");
196 fprintf(tc, " ini_claim(%d, 0);\n", claimnr);
199 ntimes(tc, 0, nrRdy, R0a); /* all */
203 ntimes(tc, 0, 1, R0b);
204 if (separate == 1 && acceptors == 0)
205 acceptors = 1; /* assume at least 1 acceptstate */
206 ntimes(th, acceptors, acceptors+1, Code1);
207 ntimes(th, progressors, progressors+1, Code3);
208 ntimes(th, nrRdy+1, nrRdy+2, R2); /* +1 for np_ */
210 fprintf(tc, " iniglobals();\n");
211 ntimes(tc, 0, 1, Code2a);
212 ntimes(tc, 0, 1, Code2b); /* bfs option */
213 ntimes(tc, 0, 1, Code2c);
214 ntimes(tc, 0, nrRdy, R4);
215 fprintf(tc, "}\n\n");
217 fprintf(tc, "void\n");
218 fprintf(tc, "iniglobals(void)\n{\n");
219 if (doglobal("", INIV) > 0)
220 { fprintf(tc, "#ifdef VAR_RANGES\n");
221 (void) doglobal("logval(\"", LOGV);
222 fprintf(tc, "#endif\n");
224 ntimes(tc, 1, nqs+1, R3);
225 fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);");
226 fprintf(tc, "\n}\n\n");
232 ntimes(tc, 0, 1, SvMap);
236 char *s, *t; int n, m, p;
238 {"end", "stopstate", 3, 0, 0},
239 {"progress", "progstate", 8, 0, 1},
240 {"accept", "accpstate", 6, 1, 0},
245 end_labs(Symbol *s, int i)
249 int j; char foo[128];
251 if ((i == claimnr && separate == 1)
252 || (i != claimnr && separate == 2))
255 for (l = labtab; l; l = l->nxt)
256 for (j = 0; ln[j].n; j++)
257 if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
258 && strcmp(l->c->name, s->name) == 0)
259 { fprintf(tc, "\t%s[%d][%d] = 1;\n",
260 ln[j].t, i, l->e->seqno);
261 acceptors += ln[j].m;
262 progressors += ln[j].p;
263 if (l->e->status & D_ATOM)
264 { sprintf(foo, "%s label inside d_step",
268 if (j > 0 && (l->e->status & ATOM))
269 { sprintf(foo, "%s label inside atomic",
271 complain: lineno = l->e->n->ln;
273 printf("spin: %3d:%s, warning, %s - is invisible\n",
274 lineno, Fname?Fname->name:"-", foo);
277 /* visible states -- through remote refs: */
278 for (l = labtab; l; l = l->nxt)
280 && strcmp(l->s->context->name, s->name) == 0)
281 fprintf(tc, "\tvisstate[%d][%d] = 1;\n",
289 ntimes(FILE *fd, int n, int m, char *c[])
292 for (j = 0; c[j]; j++)
293 for (i = n; i < m; i++)
294 { fprintf(fd, c[j], i, i, i, i, i, i);
303 printf("spin: warning, ");
306 n = (s->context != ZS)?s->context->ini:s->ini;
308 printf("line %3d %s, ", n->ln, n->fn->name);
312 checktype(Symbol *sp, char *s)
313 { char buf[128]; int i;
321 if (sp->hidden&16) /* formal parameter */
322 { ProcList *p; Lextok *f, *t;
324 for (p = rdy; p; p = p->nxt)
326 && strcmp(s, p->n->name) == 0)
329 for (f = p->p; f; f = f->rgt) /* list of types */
330 for (t = f->lft; t; t = t->rgt, posnr++)
332 && strcmp(t->sym->name, sp->name) == 0)
333 { checkrun(sp, posnr);
337 } else if (!(sp->hidden&4))
338 { if (!(verbose&32)) return;
339 sputtype(buf, sp->type);
340 i = (int) strlen(buf);
341 while (buf[--i] == ' ') buf[i] = '\0';
344 printf("proctype %s:", s);
347 printf(" '%s %s' could be declared 'bit %s'\n",
348 buf, sp->name, sp->name);
349 } else if (sp->type != BYTE && !(sp->hidden&8))
350 { if (!(verbose&32)) return;
351 sputtype(buf, sp->type);
352 i = (int) strlen(buf);
353 while (buf[--i] == ' ') buf[i] = '\0';
356 printf("proctype %s:", s);
359 printf(" '%s %s' could be declared 'byte %s'\n",
360 buf, sp->name, sp->name);
365 dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s)
366 { int h, j, k=0; extern int nr_errs;
369 char buf[64], buf2[128], buf3[128];
372 { /* initialize in order of declaration */
373 for (walk = all_names; walk; walk = walk->next)
377 && strcmp(s, sp->context->name) == 0)
378 { checktype(sp, s); /* fall through */
379 if (!(sp->hidden&16))
380 { sprintf(buf, "((P%d *)pptr(h))->", p);
381 do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
386 { for (j = 0; j < 8; j++)
387 for (h = 0; h <= 1; h++)
388 for (walk = all_names; walk; walk = walk->next)
392 && sp->type == Types[j]
393 && ((h == 0 && sp->nel == 1) || (h == 1 && sp->nel > 1))
394 && strcmp(s, sp->context->name) == 0)
400 sprintf(buf, "%s%s:", pre, s);
401 { sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
402 sprintf(buf3, ");\n");
404 do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
407 sprintf(buf, "((P%d *)pptr(h))->", p);
408 do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
412 if (strcmp(s, ":never:") == 0)
413 { printf("error: %s defines local %s\n",
428 { fprintf(fd, "void\nc_chandump(int unused) ");
429 fprintf(fd, "{ unused = unused++; /* avoid complaints */ }\n");
433 fprintf(fd, "void\nc_chandump(int from)\n");
434 fprintf(fd, "{ uchar *z; int slot;\n");
436 fprintf(fd, " from--;\n");
437 fprintf(fd, " if (from >= (int) now._nr_qs || from < 0)\n");
438 fprintf(fd, " { printf(\"pan: bad qid %%d\\n\", from+1);\n");
439 fprintf(fd, " return;\n");
441 fprintf(fd, " z = qptr(from);\n");
442 fprintf(fd, " switch (((Q0 *)z)->_t) {\n");
444 for (q = qtab; q; q = q->nxt)
445 { fprintf(fd, " case %d:\n\t\t", q->qid);
446 sprintf(buf, "((Q%d *)z)->", q->qid);
448 fprintf(fd, "for (slot = 0; slot < %sQlen; slot++)\n\t\t", buf);
449 fprintf(fd, "{ printf(\" [\");\n\t\t");
450 for (i = 0; i < q->nflds; i++)
451 { if (q->fld_width[i] == MTYPE)
452 { fprintf(fd, "\tprintm(%scontents[slot].fld%d);\n\t\t",
455 fprintf(fd, "\tprintf(\"%%d,\", %scontents[slot].fld%d);\n\t\t",
458 fprintf(fd, " printf(\"],\");\n\t\t");
459 fprintf(fd, "}\n\t\t");
460 fprintf(fd, "break;\n");
463 fprintf(fd, " printf(\"\\n\");\n}\n");
467 c_var(FILE *fd, char *pref, Symbol *sp)
473 /* c_struct(fd, pref, sp); */
474 fprintf(fd, "\t\tprintf(\"\t(struct %s)\\n\");\n",
476 sprintf(buf, "%s%s.", pref, sp->name);
477 c_struct(fd, buf, sp);
480 case SHORT: case INT:
482 sputtype(buf, sp->type);
484 { fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
485 buf, sp->name, pref, sp->name);
487 { fprintf(fd, "\t{\tint l_in;\n");
488 fprintf(fd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
489 fprintf(fd, "\t\t{\n");
490 fprintf(fd, "\t\t\tprintf(\"\t%s %s[%%d]:\t%%d\\n\", l_in, %s%s[l_in]);\n",
491 buf, sp->name, pref, sp->name);
492 fprintf(fd, "\t\t}\n");
493 fprintf(fd, "\t}\n");
498 { fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ",
500 fprintf(fd, "%s%s, q_len(%s%s));\n",
501 pref, sp->name, pref, sp->name);
502 fprintf(fd, "\tc_chandump(%s%s);\n", pref, sp->name);
504 for (i = 0; i < sp->nel; i++)
505 { fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
507 fprintf(fd, "%s%s[%d], q_len(%s%s[%d]));\n",
508 pref, sp->name, i, pref, sp->name, i);
509 fprintf(fd, "\tc_chandump(%s%s[%d]);\n",
517 c_splurge_any(ProcList *p)
521 if (strcmp(p->n->name, ":never:") != 0
522 && strcmp(p->n->name, ":trace:") != 0
523 && strcmp(p->n->name, ":notrace:") != 0)
524 for (walk = all_names; walk; walk = walk->next)
528 || strcmp(sp->context->name, p->n->name) != 0
529 || sp->owner || (sp->hidden&1)
530 || (sp->type == MTYPE && ismtype(sp->name)))
539 c_splurge(FILE *fd, ProcList *p)
544 if (strcmp(p->n->name, ":never:") != 0
545 && strcmp(p->n->name, ":trace:") != 0
546 && strcmp(p->n->name, ":notrace:") != 0)
547 for (walk = all_names; walk; walk = walk->next)
551 || strcmp(sp->context->name, p->n->name) != 0
552 || sp->owner || (sp->hidden&1)
553 || (sp->type == MTYPE && ismtype(sp->name)))
556 sprintf(pref, "((P%d *)pptr(pid))->", p->tn);
562 c_wrapper(FILE *fd) /* allow pan.c to print out global sv entries */
567 extern Lextok *Mtype;
570 fprintf(fd, "void\nc_globals(void)\n{\t/* int i; */\n");
571 fprintf(fd, " printf(\"global vars:\\n\");\n");
572 for (walk = all_names; walk; walk = walk->next)
574 if (sp->context || sp->owner || (sp->hidden&1)
575 || (sp->type == MTYPE && ismtype(sp->name)))
578 c_var(fd, "now.", sp);
582 fprintf(fd, "void\nc_locals(int pid, int tp)\n{\t/* int i; */\n");
583 fprintf(fd, " switch(tp) {\n");
584 for (p = rdy; p; p = p->nxt)
585 { fprintf(fd, " case %d:\n", p->tn);
586 fprintf(fd, " \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
588 if (c_splurge_any(p))
589 { fprintf(fd, " \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
593 { fprintf(fd, " \t/* none */\n");
595 fprintf(fd, " \tbreak;\n");
597 fprintf(fd, " }\n}\n");
599 fprintf(fd, "void\nprintm(int x)\n{\n");
600 fprintf(fd, " switch (x) {\n");
601 for (n = Mtype, j = 1; n && j; n = n->rgt, j++)
602 fprintf(fd, "\tcase %d: Printf(\"%s\"); break;\n",
603 j, n->lft->sym->name);
604 fprintf(fd, " default: Printf(\"%%d\", x);\n");
610 doglobal(char *pre, int dowhat)
615 for (j = 0; j < 8; j++)
616 for (walk = all_names; walk; walk = walk->next)
620 && sp->type == Types[j])
621 { if (Types[j] != MTYPE || !ismtype(sp->name))
629 do_var(tc, dowhat, "", sp,
630 pre, "\", now.", ");\n");
633 checktype(sp, (char *) 0);
634 cnt++; /* fall through */
636 do_var(tc, dowhat, (sp->hidden&1)?"":"now.", sp,
649 for (j = 0; j < 8; j++)
650 for (walk = all_names; walk; walk = walk->next)
653 && sp->type == Types[j])
654 { if (sp->context || sp->owner)
655 fatal("cannot hide non-globals (%s)", sp->name);
656 if (sp->type == CHAN)
657 fatal("cannot hide channels (%s)", sp->name);
658 fprintf(th, "/* hidden variable: */");
661 fprintf(th, "int _; /* a predefined write-only variable */\n\n");
665 do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
666 char *pre, char *sep, char *ter)
672 if (sp->hidden&1) break;
678 if (sp->type == STRUCT)
679 { /* struct may contain a chan */
680 walk_struct(ofd, dowhat, s, sp, pre, sep, ter);
683 if (!sp->ini && dowhat != LOGV) /* it defaults to 0 */
686 { fprintf(ofd, "\t\t%s%s%s%s",
687 pre, s, sp->name, sep);
689 fprintf(ofd, "%s%s", s, sp->name);
692 fprintf(ofd, "%s", ter);
694 { if (sp->ini && sp->ini->ntyp == CHAN)
695 { for (i = 0; i < sp->nel; i++)
696 { fprintf(ofd, "\t\t%s%s%s[%d]%s",
697 pre, s, sp->name, i, sep);
699 fprintf(ofd, "%s%s[%d]",
703 fprintf(ofd, "%s", ter);
706 { fprintf(ofd, "\t{\tint l_in;\n");
707 fprintf(ofd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
708 fprintf(ofd, "\t\t{\n");
709 fprintf(ofd, "\t\t\t%s%s%s[l_in]%s",
710 pre, s, sp->name, sep);
712 fprintf(ofd, "%s%s[l_in]", s, sp->name);
714 putstmnt(ofd, sp->ini, 0);
715 fprintf(ofd, "%s", ter);
716 fprintf(ofd, "\t\t}\n");
717 fprintf(ofd, "\t}\n");
724 do_init(FILE *ofd, Symbol *sp)
725 { int i; extern Queue *ltab[];
729 && ((i = qmake(sp)) > 0))
730 { if (sp->ini->ntyp == CHAN)
731 fprintf(ofd, "addqueue(%d, %d)",
732 i, ltab[i-1]->nslots == 0);
734 fprintf(ofd, "%d", i);
736 putstmnt(ofd, sp->ini, 0);
740 blog(int n) /* for small log2 without rounding problems */
743 while (r < n) { m++; r *= 2; }
748 put_ptype(char *s, int i, int m0, int m1)
751 if (strcmp(s, ":init:") == 0)
752 fprintf(th, "#define Pinit ((P%d *)this)\n", i);
754 if (strcmp(s, ":never:") != 0
755 && strcmp(s, ":trace:") != 0
756 && strcmp(s, ":notrace:") != 0
757 && strcmp(s, ":init:") != 0
758 && strcmp(s, "_:never_template:_") != 0
759 && strcmp(s, "np_") != 0)
760 fprintf(th, "#define P%s ((P%d *)this)\n", s, i);
762 fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
763 fprintf(th, " unsigned _pid : 8; /* 0..255 */\n");
764 fprintf(th, " unsigned _t : %d; /* proctype */\n", blog(m1));
765 fprintf(th, " unsigned _p : %d; /* state */\n", blog(m0));
767 nBits = 8 + blog(m1) + blog(m0);
768 k = dolocal(tc, "", PUTV, i, s); /* includes pars */
772 fprintf(th, "} P%d;\n", i);
773 if ((!LstSet && k > 0) || has_state)
774 fprintf(th, "#define Air%d 0\n", i);
776 { fprintf(th, "#define Air%d (sizeof(P%d) - ", i, i);
778 { fprintf(th, "%d", (nBits+7)/8);
781 if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
783 { fprintf(th, "Offsetof(P%d, %s) - %d*sizeof(",
784 i, LstSet->name, LstSet->nel);
786 switch(LstSet->type) {
788 fprintf(th, "%d", (nBits+7)/8);
791 if (LstSet->nel == 1)
792 { fprintf(th, "%d", (nBits+7)/8);
794 } /* else fall through */
795 case MTYPE: case BYTE: case CHAN:
796 fprintf(th, "uchar)"); break;
798 fprintf(th, "short)"); break;
800 fprintf(th, "int)"); break;
802 fatal("cannot happen Air %s",
805 done: fprintf(th, ")\n");
811 { int i = nrRdy; /* 1+ highest proctype nr */
813 fprintf(th, "#define _NP_ %d\n", i);
814 /* if (separate == 2) fprintf(th, "extern "); */
815 fprintf(th, "uchar reached%d[3]; /* np_ */\n", i);
817 fprintf(th, "#define nstates%d 3 /* np_ */\n", i);
818 fprintf(th, "#define endstate%d 2 /* np_ */\n\n", i);
819 fprintf(th, "#define start%d 0 /* np_ */\n", i);
821 fprintf(tc, "\tcase %d: /* np_ */\n", i);
823 { fprintf(tc, "\t\tini_claim(%d, h);\n", i);
825 { fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
826 fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", i);
827 fprintf(tc, "\t\treached%d[0] = 1;\n", i);
828 fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", i);
830 fprintf(tc, "\t\tbreak;\n");
834 put_pinit(ProcList *P)
835 { Lextok *fp, *fpt, *t;
836 Element *e = P->s->frst;
844 { fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
845 fprintf(tc, "\t\tini_claim(%d, h);\n", i);
846 fprintf(tc, "\t\tbreak;\n");
853 ini = huntele(e, e->status, -1)->seqno;
854 fprintf(th, "#define start%d %d\n", i, ini);
856 fprintf(th, "#define start_claim %d\n", ini);
858 fprintf(th, "#define start_event %d\n", ini);
860 fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
862 fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
863 fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;", i, ini);
864 fprintf(tc, " reached%d[%d]=1;\n", i, ini);
867 { fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
869 { fprintf(tt, "if (");
870 putstmnt(tt, P->prov, 0);
871 fprintf(tt, ")\n\t\t\t");
873 fprintf(tt, "return 1;\n");
875 fprintf(tt, "\t\tbreak;\n");
878 fprintf(tc, "\t\t/* params: */\n");
879 for (fp = p, j=0; fp; fp = fp->rgt)
880 for (fpt = fp->lft; fpt; fpt = fpt->rgt, j++)
881 { t = (fpt->ntyp == ',') ? fpt->lft : fpt;
882 if (t->sym->nel != 1)
885 fatal("array in parameter list, %s",
888 fprintf(tc, "\t\t((P%d *)pptr(h))->", i);
889 if (t->sym->type == STRUCT)
890 { if (full_name(tc, t, t->sym, 1))
893 fatal("hidden array in parameter %s",
897 fprintf(tc, "%s", t->sym->name);
898 fprintf(tc, " = par%d;\n", j);
900 fprintf(tc, "\t\t/* locals: */\n");
901 k = dolocal(tc, "", INIV, i, s->name);
903 { fprintf(tc, "#ifdef VAR_RANGES\n");
904 (void) dolocal(tc, "logval(\"", LOGV, i, s->name);
905 fprintf(tc, "#endif\n");
908 fprintf(tc, "#ifdef HAS_CODE\n");
909 fprintf(tc, "\t\tlocinit%d(h);\n", i);
910 fprintf(tc, "#endif\n");
912 dumpclaims(tc, i, s->name);
913 fprintf(tc, "\t break;\n");
917 huntstart(Element *f)
919 Element *elast = (Element *) 0;
922 while (elast != e && cnt++ < 200) /* new 4.0.8 */
925 { if (e->n->ntyp == '.' && e->nxt)
927 else if (e->n->ntyp == UNLESS)
928 e = e->sub->this->frst;
931 if (cnt >= 200 || !e)
932 fatal("confusing control structure", (char *) 0);
937 huntele(Element *f, int o, int stopat)
938 { Element *g, *e = f;
939 int cnt=0; /* a precaution against loops */
942 for (cnt = 0; cnt < 200 && e->n; cnt++)
944 if (e->seqno == stopat)
947 switch (e->n->ntyp) {
950 cross_dsteps(e->n, g->n);
959 g = huntele(e->sub->this->frst, o, stopat);
967 if ((o & ATOM) && !(g->status & ATOM))
971 if (cnt >= 200 || !e)
972 fatal("confusing control structure", (char *) 0);
978 { int wsbits = sizeof(long)*8; /* wordsize in bits */
982 fprintf(th, "\tuchar %s;", sp->name);
984 fprintf(th, "\tunsigned %s : %d",
985 sp->name, sp->nbits);
988 && wsbits - nBits%wsbits < sp->nbits)
989 { /* must padd to a word-boundary */
990 nBits += wsbits - nBits%wsbits;
995 if (sp->nel == 1 && !(sp->hidden&1))
996 { fprintf(th, "\tunsigned %s : 1", sp->name);
1000 } /* else fall through */
1001 if (!(sp->hidden&1) && (verbose&32))
1002 printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
1004 nBits += 8*sp->nel; /* mapped onto array of uchars */
1007 case CHAN: /* good for up to 255 channels */
1008 fprintf(th, "\tuchar %s", sp->name);
1012 fprintf(th, "\tshort %s", sp->name);
1016 fprintf(th, "\tint %s", sp->name);
1021 fatal("undeclared structure element %s", sp->name);
1022 fprintf(th, "\tstruct %s %s",
1031 fatal("variable %s undeclared", sp->name);
1035 fprintf(th, "[%d]", sp->nel);
1040 ncases(FILE *fd, int p, int n, int m, char *c[])
1043 for (j = 0; c[j]; j++)
1044 for (i = n; i < m; i++)
1045 { fprintf(fd, c[j], i, p, i);
1055 fprintf(th, "uchar");
1056 else if (qmax < 65535)
1057 fprintf(th, "ushort");
1059 fprintf(th, "uint");
1060 fprintf(th, " Qlen; /* q_size */\n");
1069 ntimes(tc, 0, 1, Addq0);
1071 fprintf(th, "#define NQS 1 /* nqs=%d, but has_io */\n", nqs);
1073 fprintf(th, "#define NQS %d\n", nqs);
1074 fprintf(th, "short q_flds[%d];\n", nqs+1);
1075 fprintf(th, "short q_max[%d];\n", nqs+1);
1077 for (q = qtab; q; q = q->nxt)
1078 if (q->nslots > qmax)
1081 for (q = qtab; q; q = q->nxt)
1083 fprintf(tc, "\tcase %d: j = sizeof(Q%d);", j, j);
1084 fprintf(tc, " q_flds[%d] = %d;", j, q->nflds);
1085 fprintf(tc, " q_max[%d] = %d;", j, max(1,q->nslots));
1086 fprintf(tc, " break;\n");
1088 fprintf(th, "typedef struct Q%d {\n", j);
1089 qlen_type(qmax); /* 4.2.2 */
1090 fprintf(th, " uchar _t; /* q_type */\n");
1091 fprintf(th, " struct {\n");
1093 for (j = 0; j < q->nflds; j++)
1094 { switch (q->fld_width[j]) {
1097 { fprintf(th, "\t\tunsigned");
1098 fprintf(th, " fld%d : 1;\n", j);
1100 } /* else fall through: smaller struct */
1104 fprintf(th, "\t\tuchar fld%d;\n", j);
1107 fprintf(th, "\t\tshort fld%d;\n", j);
1110 fprintf(th, "\t\tint fld%d;\n", j);
1113 fatal("bad channel spec", "");
1116 fprintf(th, " } contents[%d];\n", max(1, q->nslots));
1117 fprintf(th, "} Q%d;\n", q->qid);
1120 fprintf(th, "typedef struct Q0 {\t/* generic q */\n");
1121 qlen_type(qmax); /* 4.2.2 */
1122 fprintf(th, " uchar _t;\n");
1123 fprintf(th, "} Q0;\n");
1125 ntimes(tc, 0, 1, Addq1);
1128 { fprintf(th, "int Q_has(int");
1129 for (j = 0; j < Mpars; j++)
1130 fprintf(th, ", int, int");
1131 fprintf(th, ");\n");
1133 fprintf(tc, "int\nQ_has(int into");
1134 for (j = 0; j < Mpars; j++)
1135 fprintf(tc, ", int want%d, int fld%d", j, j);
1137 fprintf(tc, "{ int i;\n\n");
1138 fprintf(tc, " if (!into--)\n");
1139 fprintf(tc, " uerror(\"ref to unknown chan ");
1140 fprintf(tc, "(recv-poll)\");\n\n");
1141 fprintf(tc, " if (into >= now._nr_qs || into < 0)\n");
1142 fprintf(tc, " Uerror(\"qrecv bad queue#\");\n\n");
1143 fprintf(tc, " for (i = 0; i < ((Q0 *)qptr(into))->Qlen;");
1144 fprintf(tc, " i++)\n");
1145 fprintf(tc, " {\n");
1146 for (j = 0; j < Mpars; j++)
1147 { fprintf(tc, " if (want%d && ", j);
1148 fprintf(tc, "qrecv(into+1, i, %d, 0) != fld%d)\n",
1150 fprintf(tc, " continue;\n");
1152 fprintf(tc, " return i+1;\n");
1153 fprintf(tc, " }\n");
1154 fprintf(tc, " return 0;\n");
1158 fprintf(tc, "#if NQS>0\n");
1159 fprintf(tc, "void\nqsend(int into, int sorted");
1160 for (j = 0; j < Mpars; j++)
1161 fprintf(tc, ", int fld%d", j);
1163 ntimes(tc, 0, 1, Addq11);
1165 for (q = qtab; q; q = q->nxt)
1166 { sprintf(buf0, "((Q%d *)z)->", q->qid);
1167 fprintf(tc, "\tcase %d:%s\n", q->qid,
1168 (q->nslots)?"":" /* =rv= */");
1169 if (q->nslots == 0) /* reset handshake point */
1170 fprintf(tc, "\t\t(trpt+2)->o_m = 0;\n");
1173 { fprintf(tc, "\t\tif (!sorted) goto append%d;\n", q->qid);
1174 fprintf(tc, "\t\tfor (j = 0; j < %sQlen; j++)\n", buf0);
1175 fprintf(tc, "\t\t{\t/* find insertion point */\n");
1176 sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
1177 for (j = 0; j < q->nflds; j++)
1178 { fprintf(tc, "\t\t\tif (fld%d > %s%d) continue;\n",
1180 fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
1181 fprintf(tc, "goto found%d;\n\n", q->qid);
1183 fprintf(tc, "\t\t}\n");
1184 fprintf(tc, "\tfound%d:\n", q->qid);
1185 sprintf(buf0, "((Q%d *)z)->", q->qid);
1186 fprintf(tc, "\t\tfor (k = %sQlen - 1; k >= j; k--)\n", buf0);
1187 fprintf(tc, "\t\t{\t/* shift up */\n");
1188 for (j = 0; j < q->nflds; j++)
1189 { fprintf(tc, "\t\t\t%scontents[k+1].fld%d = ",
1191 fprintf(tc, "%scontents[k].fld%d;\n",
1194 fprintf(tc, "\t\t}\n");
1195 fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
1198 fprintf(tc, "#ifdef HAS_SORTED\n");
1199 fprintf(tc, "\t\t(trpt+1)->ipt = j;\n"); /* ipt was bup.oval */
1200 fprintf(tc, "#endif\n");
1201 fprintf(tc, "\t\t%sQlen = %sQlen + 1;\n", buf0, buf0);
1202 sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
1203 for (j = 0; j < q->nflds; j++)
1204 fprintf(tc, "\t\t%s%d = fld%d;\n", buf0, j, j);
1205 fprintf(tc, "\t\tbreak;\n");
1207 ntimes(tc, 0, 1, Addq2);
1209 for (q = qtab; q; q = q->nxt)
1210 fprintf(tc, "\tcase %d: return %d;\n", q->qid, (!q->nslots));
1212 ntimes(tc, 0, 1, Addq3);
1214 for (q = qtab; q; q = q->nxt)
1215 fprintf(tc, "\tcase %d: return (q_sz(from) == %d);\n",
1216 q->qid, max(1, q->nslots));
1218 ntimes(tc, 0, 1, Addq4);
1219 for (q = qtab; q; q = q->nxt)
1220 { sprintf(buf0, "((Q%d *)z)->", q->qid);
1221 fprintf(tc, " case %d:%s\n\t\t",
1222 q->qid, (q->nslots)?"":" /* =rv= */");
1224 { fprintf(tc, "if (fld == 0) r = %s", buf0);
1225 fprintf(tc, "contents[slot].fld0;\n");
1227 { fprintf(tc, "switch (fld) {\n");
1228 ncases(tc, q->qid, 0, q->nflds, R12);
1229 fprintf(tc, "\t\tdefault: Uerror");
1230 fprintf(tc, "(\"too many fields in recv\");\n");
1231 fprintf(tc, "\t\t}\n");
1233 fprintf(tc, "\t\tif (done)\n");
1235 { fprintf(tc, "\t\t{ j = %sQlen - 1;\n", buf0);
1236 fprintf(tc, "\t\t %sQlen = 0;\n", buf0);
1237 sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
1239 { fprintf(tc, "\t\t{ j = %sQlen;\n", buf0);
1240 fprintf(tc, "\t\t %sQlen = --j;\n", buf0);
1241 fprintf(tc, "\t\t for (k=slot; k<j; k++)\n");
1242 fprintf(tc, "\t\t {\n");
1243 sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
1244 for (j = 0; j < q->nflds; j++)
1245 { fprintf(tc, "\t%s[k].fld%d = \n", buf0, j);
1246 fprintf(tc, "\t\t%s[k+1].fld%d;\n", buf0, j);
1248 fprintf(tc, "\t\t }\n");
1251 for (j = 0; j < q->nflds; j++)
1252 fprintf(tc, "%s[j].fld%d = 0;\n", buf0, j);
1253 fprintf(tc, "\t\t\tif (fld+1 != %d)\n\t\t\t", q->nflds);
1254 fprintf(tc, "\tuerror(\"missing pars in receive\");\n");
1255 /* incompletely received msgs cannot be unrecv'ed */
1256 fprintf(tc, "\t\t}\n");
1257 fprintf(tc, "\t\tbreak;\n");
1259 ntimes(tc, 0, 1, Addq5);
1260 for (q = qtab; q; q = q->nxt)
1261 fprintf(tc, " case %d: j = sizeof(Q%d); break;\n",
1263 ntimes(tc, 0, 1, R8b);
1265 ntimes(th, 0, 1, Proto); /* tag on function prototypes */
1266 fprintf(th, "void qsend(int, int");
1267 for (j = 0; j < Mpars; j++)
1268 fprintf(th, ", int");
1269 fprintf(th, ");\n");
1271 fprintf(th, "#define Addproc(x) addproc(x");
1272 for (j = 0; j < Npars; j++)