]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/spin/pangen1.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / cmd / spin / pangen1.c
1 /***** spin: pangen1.c *****/
2
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            */
11
12 #include "spin.h"
13 #include "y.tab.h"
14 #include "pangen1.h"
15 #include "pangen3.h"
16
17 extern FILE     *tc, *th, *tt;
18 extern Label    *labtab;
19 extern Ordered  *all_names;
20 extern ProcList *rdy;
21 extern Queue    *qtab;
22 extern Symbol   *Fname;
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;
26
27 int     Npars=0, u_sync=0, u_async=0, hastrack = 1;
28 short   has_io = 0;
29 short   has_state=0;    /* code contains c_state */
30
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 };
34
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 *);
43
44 static void
45 reverse_names(ProcList *p)
46 {
47         if (!p) return;
48         reverse_names(p->nxt);
49         fprintf(th, "   \"%s\",\n", p->n->name);
50 }
51
52 void
53 genheader(void)
54 {       ProcList *p; int i;
55
56         if (separate == 2)
57         {       putunames(th);
58                 goto here;
59         }
60
61         fprintf(th, "#define SYNC       %d\n", u_sync);
62         fprintf(th, "#define ASYNC      %d\n\n", u_async);
63
64         putunames(th);
65
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_ */
70         fprintf(tc, " };\n");
71
72         fprintf(th, "char *procname[] = {\n");
73                 reverse_names(rdy);
74         fprintf(th, "   \":np_:\",\n");
75         fprintf(th, "};\n\n");
76
77 here:
78         for (p = rdy; p; p = p->nxt)
79                 put_ptype(p->n->name, p->tn, mst, nrRdy+1);
80                 /* +1 for np_ */
81         put_ptype("np_", nrRdy, mst, nrRdy+1);
82
83         ntimes(th, 0, 1, Head0);
84
85         if (separate != 2)
86         {       extern void c_add_stack(FILE *);
87
88                 ntimes(th, 0, 1, Header);
89                 c_add_stack(th);
90                 ntimes(th, 0, 1, Header0);
91         }
92         ntimes(th, 0, 1, Head1);
93
94         LstSet = ZS;
95         (void) doglobal("", PUTV);
96
97         hastrack = c_add_sv(th);
98
99         fprintf(th, "   uchar sv[VECTORSZ];\n");
100         fprintf(th, "} State");
101 #ifdef SOLARIS
102         fprintf(th,"\n#ifdef GCC\n");
103         fprintf(th, "\t__attribute__ ((aligned(8)))");
104         fprintf(th, "\n#endif\n\t");
105 #endif
106         fprintf(th, ";\n\n");
107
108         fprintf(th, "#define HAS_TRACK  %d\n", hastrack);
109
110         if (separate != 2)
111                 dohidden();
112 }
113
114 void
115 genaddproc(void)
116 {       ProcList *p;
117         int i = 0;
118
119         if (separate ==2) goto shortcut;
120
121         fprintf(tc, "int\naddproc(int n");
122         for (i = 0; i < Npars; i++)
123                 fprintf(tc, ", int par%d", i);
124
125         ntimes(tc, 0, 1, Addp0);
126         ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
127         ntimes(tc, 0, 1, Addp1);
128
129         if (has_provided)
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");
133         }
134 shortcut:
135         tc_predef_np();
136         for (p = rdy; p; p = p->nxt)
137         {       Pid = p->tn;
138                 put_pinit(p);
139         }
140         if (separate == 2) return;
141
142         Pid = 0;
143         if (has_provided)
144         {       fprintf(tt, "\tdefault: return 1; /* e.g., a claim */\n");
145                 fprintf(tt, "\t}\n\treturn 0;\n}\n");
146         }
147
148         ntimes(tc, i, i+1, R6);
149         if (separate == 0)
150                 ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
151         else
152                 ntimes(tc, 1, nrRdy, R5);
153         ntimes(tc, 0, 1, R8a);
154 }
155
156 void
157 do_locinits(FILE *fd)
158 {       ProcList *p;
159
160         for (p = rdy; p; p = p->nxt)
161                 c_add_locinit(fd, p->tn, p->n->name);
162 }
163
164 void
165 genother(void)
166 {       ProcList *p;
167
168         switch (separate) {
169         case 2:
170                 if (claimnr >= 0)
171                 ntimes(tc, claimnr, claimnr+1, R0); /* claim only */
172                 break;
173         case 1:
174                 ntimes(tc,     0,    1, Code0);
175                 ntimes(tc, 0, claimnr, R0);     /* all except claim */
176                 ntimes(tc, claimnr+1, nrRdy, R0);
177                 break;
178         case 0:
179                 ntimes(tc,     0,    1, Code0);
180                 ntimes(tc,     0, nrRdy+1, R0); /* +1 for np_ */
181                 break;
182         }
183
184         for (p = rdy; p; p = p->nxt)
185                 end_labs(p->n, p->tn);
186
187         switch (separate) {
188         case 2:
189                 if (claimnr >= 0)
190                 ntimes(tc, claimnr, claimnr+1, R0a); /* claim only */
191                 return;
192         case 1:
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);
197                 break;
198         case 0:
199                 ntimes(tc, 0, nrRdy, R0a);      /* all */
200                 break;
201         }
202
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_ */
209
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");
216
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");
223         }
224         ntimes(tc, 1, nqs+1, R3);
225         fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);");
226         fprintf(tc, "\n}\n\n");
227 }
228
229 void
230 gensvmap(void)
231 {
232         ntimes(tc, 0, 1, SvMap);
233 }
234
235 static struct {
236         char *s,        *t;             int n,  m,      p;
237 } ln[] = {
238         {"end",         "stopstate",    3,      0,      0},
239         {"progress",    "progstate",    8,      0,      1},
240         {"accept",      "accpstate",    6,      1,      0},
241         {0,             0,              0,      0,      0},
242 };
243
244 static void
245 end_labs(Symbol *s, int i)
246 {       int oln = lineno;
247         Symbol *ofn = Fname;
248         Label *l;
249         int j; char foo[128];
250
251         if ((i == claimnr && separate == 1)
252         ||  (i != claimnr && separate == 2))
253                 return;
254
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",
265                                         ln[j].s);
266                                 goto complain;
267                         }
268                         if (j > 0 && (l->e->status & ATOM))
269                         {       sprintf(foo, "%s label inside atomic",
270                                         ln[j].s);
271                 complain:       lineno = l->e->n->ln;
272                                 Fname  = l->e->n->fn;
273                                 printf("spin: %3d:%s, warning, %s - is invisible\n",
274                                         lineno, Fname?Fname->name:"-", foo);
275                         }
276                 }       
277         /* visible states -- through remote refs: */
278         for (l = labtab; l; l = l->nxt)
279                 if (l->visible
280                 &&  strcmp(l->s->context->name, s->name) == 0)
281                 fprintf(tc, "\tvisstate[%d][%d] = 1;\n",
282                                 i, l->e->seqno);
283
284         lineno = oln;
285         Fname  = ofn;
286 }
287
288 void
289 ntimes(FILE *fd, int n, int m, char *c[])
290 {
291         int i, j;
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);
295                 fprintf(fd, "\n");
296         }
297 }
298
299 void
300 prehint(Symbol *s)
301 {       Lextok *n;
302
303         printf("spin: warning, ");
304         if (!s) return;
305
306         n = (s->context != ZS)?s->context->ini:s->ini;
307         if (n)
308         printf("line %3d %s, ", n->ln, n->fn->name);
309 }
310
311 void
312 checktype(Symbol *sp, char *s)
313 {       char buf[128]; int i;
314
315         if (!s
316         || (sp->type != BYTE
317         &&  sp->type != SHORT
318         &&  sp->type != INT))
319                 return;
320
321         if (sp->hidden&16)      /* formal parameter */
322         {       ProcList *p; Lextok *f, *t;
323                 int posnr = 0;
324                 for (p = rdy; p; p = p->nxt)
325                         if (p->n->name
326                         &&  strcmp(s, p->n->name) == 0)
327                                 break;
328                 if (p)
329                 for (f = p->p; f; f = f->rgt) /* list of types */
330                 for (t = f->lft; t; t = t->rgt, posnr++)
331                         if (t->sym
332                         &&  strcmp(t->sym->name, sp->name) == 0)
333                         {       checkrun(sp, posnr);
334                                 return;
335                         }
336
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';
342                 prehint(sp);
343                 if (sp->context)
344                         printf("proctype %s:", s);
345                 else
346                         printf("global");
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';
354                 prehint(sp);
355                 if (sp->context)
356                         printf("proctype %s:", s);
357                 else
358                         printf("global");
359                 printf(" '%s %s' could be declared 'byte %s'\n",
360                         buf, sp->name, sp->name);
361         }
362 }
363
364 int
365 dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s)
366 {       int h, j, k=0; extern int nr_errs;
367         Ordered *walk;
368         Symbol *sp;
369         char buf[64], buf2[128], buf3[128];
370
371         if (dowhat == INIV)
372         {       /* initialize in order of declaration */
373                 for (walk = all_names; walk; walk = walk->next)
374                 {       sp = walk->entry;
375                         if (sp->context
376                         && !sp->owner
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");
382                                 }
383                                 k++;
384                 }       }
385         } else
386         {       for (j = 0; j < 8; j++)
387                 for (h = 0; h <= 1; h++)
388                 for (walk = all_names; walk; walk = walk->next)
389                 {       sp = walk->entry;
390                         if (sp->context
391                         && !sp->owner
392                         &&  sp->type == Types[j]
393                         &&  ((h == 0 && sp->nel == 1) || (h == 1 && sp->nel > 1))
394                         &&  strcmp(s, sp->context->name) == 0)
395                         {       switch (dowhat) {
396                                 case LOGV:
397                                         if (sp->type == CHAN
398                                         &&  verbose == 0)
399                                                 break;
400                                         sprintf(buf, "%s%s:", pre, s);
401                                         { sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
402                                           sprintf(buf3, ");\n");
403                                         }
404                                         do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
405                                         break;
406                                 case PUTV:
407                                         sprintf(buf, "((P%d *)pptr(h))->", p);
408                                         do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
409                                         k++;
410                                         break;
411                                 }
412                                 if (strcmp(s, ":never:") == 0)
413                                 {       printf("error: %s defines local %s\n",
414                                                 s, sp->name);
415                                         nr_errs++;
416         }       }       }       }
417
418         return k;
419 }
420
421 void
422 c_chandump(FILE *fd)
423 {       Queue *q;
424         char buf[256];
425         int i;
426
427         if (!qtab)
428         {       fprintf(fd, "void\nc_chandump(int unused) ");
429                 fprintf(fd, "{ unused = unused++; /* avoid complaints */ }\n");
430                 return;
431         }
432
433         fprintf(fd, "void\nc_chandump(int from)\n");
434         fprintf(fd, "{  uchar *z; int slot;\n");
435
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");
440         fprintf(fd, "   }\n");
441         fprintf(fd, "   z = qptr(from);\n");
442         fprintf(fd, "   switch (((Q0 *)z)->_t) {\n");
443
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);
447
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",
453                                 buf, i);
454                         } else
455                         fprintf(fd, "\tprintf(\"%%d,\", %scontents[slot].fld%d);\n\t\t",
456                                 buf, i);
457                 }
458                 fprintf(fd, "   printf(\"],\");\n\t\t");
459                 fprintf(fd, "}\n\t\t");
460                 fprintf(fd, "break;\n");
461         }
462         fprintf(fd, "   }\n");
463         fprintf(fd, "   printf(\"\\n\");\n}\n");
464 }
465
466 void
467 c_var(FILE *fd, char *pref, Symbol *sp)
468 {       char buf[256];
469         int i;
470
471         switch (sp->type) {
472         case STRUCT:
473                 /* c_struct(fd, pref, sp); */
474                 fprintf(fd, "\t\tprintf(\"\t(struct %s)\\n\");\n",
475                         sp->name);
476                 sprintf(buf, "%s%s.", pref, sp->name);
477                 c_struct(fd, buf, sp);
478                 break;
479         case BIT:   case BYTE:
480         case SHORT: case INT:
481         case UNSIGNED:
482                 sputtype(buf, sp->type);
483                 if (sp->nel == 1)
484                 {       fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
485                                 buf, sp->name, pref, sp->name);
486                 } else
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");
494                 }
495                 break;
496         case CHAN:
497                 if (sp->nel == 1)
498                 {  fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ",
499                         sp->name);
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);
503                 } else
504                 for (i = 0; i < sp->nel; i++)
505                 {  fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
506                         sp->name, i);
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",
510                         pref, sp->name, i);
511                 }
512                 break;
513         }
514 }
515
516 int
517 c_splurge_any(ProcList *p)
518 {       Ordered *walk;
519         Symbol *sp;
520
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)
525         {       sp = walk->entry;
526                 if (!sp->context
527                 ||  sp->type == 0
528                 ||  strcmp(sp->context->name, p->n->name) != 0
529                 ||  sp->owner || (sp->hidden&1)
530                 || (sp->type == MTYPE && ismtype(sp->name)))
531                         continue;
532
533                 return 1;
534         }
535         return 0;
536 }
537
538 void
539 c_splurge(FILE *fd, ProcList *p)
540 {       Ordered *walk;
541         Symbol *sp;
542         char pref[64];
543
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)
548         {       sp = walk->entry;
549                 if (!sp->context
550                 ||  sp->type == 0
551                 ||  strcmp(sp->context->name, p->n->name) != 0
552                 ||  sp->owner || (sp->hidden&1)
553                 || (sp->type == MTYPE && ismtype(sp->name)))
554                         continue;
555
556                 sprintf(pref, "((P%d *)pptr(pid))->", p->tn);
557                 c_var(fd, pref, sp);
558         }
559 }
560
561 void
562 c_wrapper(FILE *fd)     /* allow pan.c to print out global sv entries */
563 {       Ordered *walk;
564         ProcList *p;
565         Symbol *sp;
566         Lextok *n;
567         extern Lextok *Mtype;
568         int j;
569
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)
573         {       sp = walk->entry;
574                 if (sp->context || sp->owner || (sp->hidden&1)
575                 || (sp->type == MTYPE && ismtype(sp->name)))
576                         continue;
577
578                 c_var(fd, "now.", sp);
579         }
580         fprintf(fd, "}\n");
581
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",
587                         p->n->name);
588                 if (c_splurge_any(p))
589                 {       fprintf(fd, "   \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
590                                 p->n->name);
591                         c_splurge(fd, p);
592                 } else
593                 {       fprintf(fd, "   \t/* none */\n");
594                 }
595                 fprintf(fd, "   \tbreak;\n");
596         }
597         fprintf(fd, "   }\n}\n");
598
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");
605         fprintf(fd, "   }\n");
606         fprintf(fd, "}\n");
607 }
608
609 static int
610 doglobal(char *pre, int dowhat)
611 {       Ordered *walk;
612         Symbol *sp;
613         int j, cnt = 0;
614
615         for (j = 0; j < 8; j++)
616         for (walk = all_names; walk; walk = walk->next)
617         {       sp = walk->entry;
618                 if (!sp->context
619                 &&  !sp->owner
620                 &&  sp->type == Types[j])
621                 {       if (Types[j] != MTYPE || !ismtype(sp->name))
622                         switch (dowhat) {
623                         case LOGV:
624                                 if (sp->type == CHAN
625                                 &&  verbose == 0)
626                                         break;
627                                 if (sp->hidden&1)
628                                         break;
629                                 do_var(tc, dowhat, "", sp,
630                                         pre, "\", now.", ");\n");
631                                 break;
632                         case INIV:
633                                 checktype(sp, (char *) 0);
634                                 cnt++; /* fall through */
635                         case PUTV:
636                                 do_var(tc, dowhat, (sp->hidden&1)?"":"now.", sp,
637                                 "", " = ", ";\n");
638                                 break;
639         }       }       }
640         return cnt;
641 }
642
643 static void
644 dohidden(void)
645 {       Ordered *walk;
646         Symbol *sp;
647         int j;
648
649         for (j = 0; j < 8; j++)
650         for (walk = all_names; walk; walk = walk->next)
651         {       sp = walk->entry;
652                 if ((sp->hidden&1)
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: */");
659                         typ2c(sp);
660         }       }
661         fprintf(th, "int _; /* a predefined write-only variable */\n\n");
662 }
663
664 void
665 do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
666         char *pre, char *sep, char *ter)
667 {       int i;
668
669         switch(dowhat) {
670         case PUTV:
671
672                 if (sp->hidden&1) break;
673
674                 typ2c(sp);
675                 break;
676         case LOGV:
677         case INIV:
678                 if (sp->type == STRUCT)
679                 {       /* struct may contain a chan */
680                         walk_struct(ofd, dowhat, s, sp, pre, sep, ter);
681                         break;
682                 }
683                 if (!sp->ini && dowhat != LOGV) /* it defaults to 0 */
684                         break;
685                 if (sp->nel == 1)
686                 {       fprintf(ofd, "\t\t%s%s%s%s",
687                                 pre, s, sp->name, sep);
688                         if (dowhat == LOGV)
689                                 fprintf(ofd, "%s%s", s, sp->name);
690                         else
691                                 do_init(ofd, sp);
692                         fprintf(ofd, "%s", ter);
693                 } else
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);
698                                         if (dowhat == LOGV)
699                                                 fprintf(ofd, "%s%s[%d]",
700                                                         s, sp->name, i);
701                                         else
702                                                 do_init(ofd, sp);
703                                         fprintf(ofd, "%s", ter);
704                                 }
705                         } else
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);
711                                 if (dowhat == LOGV)
712                                         fprintf(ofd, "%s%s[l_in]", s, sp->name);
713                                 else
714                                         putstmnt(ofd, sp->ini, 0);
715                                 fprintf(ofd, "%s", ter);
716                                 fprintf(ofd, "\t\t}\n");
717                                 fprintf(ofd, "\t}\n");
718                 }       }
719                 break;
720         }
721 }
722
723 static void
724 do_init(FILE *ofd, Symbol *sp)
725 {       int i; extern Queue *ltab[];
726
727         if (sp->ini
728         &&  sp->type == CHAN
729         && ((i = qmake(sp)) > 0))
730         {       if (sp->ini->ntyp == CHAN)
731                         fprintf(ofd, "addqueue(%d, %d)",
732                         i, ltab[i-1]->nslots == 0);
733                 else
734                         fprintf(ofd, "%d", i);
735         } else
736                 putstmnt(ofd, sp->ini, 0);
737 }
738
739 static int
740 blog(int n)     /* for small log2 without rounding problems */
741 {       int m=1, r=2;
742
743         while (r < n) { m++; r *= 2; }
744         return 1+m;
745 }
746
747 static void
748 put_ptype(char *s, int i, int m0, int m1)
749 {       int k;
750
751         if (strcmp(s, ":init:") == 0)
752                 fprintf(th, "#define Pinit      ((P%d *)this)\n", i);
753
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);
761
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));
766         LstSet = ZS;
767         nBits = 8 + blog(m1) + blog(m0);
768         k = dolocal(tc, "", PUTV, i, s);        /* includes pars */
769
770         c_add_loc(th, s);
771
772         fprintf(th, "} P%d;\n", i);
773         if ((!LstSet && k > 0) || has_state)
774                 fprintf(th, "#define Air%d      0\n", i);
775         else
776         {       fprintf(th, "#define Air%d      (sizeof(P%d) - ", i, i);
777                 if (k == 0)
778                 {       fprintf(th, "%d", (nBits+7)/8);
779                         goto done;
780                 }
781                 if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
782                 ||   LstSet->nel != 1)
783                 {       fprintf(th, "Offsetof(P%d, %s) - %d*sizeof(",
784                                 i, LstSet->name, LstSet->nel);
785                 }
786                 switch(LstSet->type) {
787                 case UNSIGNED:
788                         fprintf(th, "%d", (nBits+7)/8);
789                         break;
790                 case BIT:
791                         if (LstSet->nel == 1)
792                         {       fprintf(th, "%d", (nBits+7)/8);
793                                 break;
794                         }       /* else fall through */
795                 case MTYPE: case BYTE: case CHAN:
796                         fprintf(th, "uchar)"); break;
797                 case SHORT:
798                         fprintf(th, "short)"); break;
799                 case INT:
800                         fprintf(th, "int)"); break;
801                 default:
802                         fatal("cannot happen Air %s",
803                                 LstSet->name);
804                 }
805 done:           fprintf(th, ")\n");
806         }
807 }
808
809 static void
810 tc_predef_np(void)
811 {       int i = nrRdy;  /* 1+ highest proctype nr */
812
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);
816
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);
820
821         fprintf(tc, "\tcase %d: /* np_ */\n", i);
822         if (separate == 1)
823         {       fprintf(tc, "\t\tini_claim(%d, h);\n", i);
824         } else
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);
829         }
830         fprintf(tc, "\t\tbreak;\n");
831 }
832
833 static void
834 put_pinit(ProcList *P)
835 {       Lextok  *fp, *fpt, *t;
836         Element *e = P->s->frst;
837         Symbol  *s = P->n;
838         Lextok  *p = P->p;
839         int      i = P->tn;
840         int     ini, j, k;
841
842         if (i == claimnr
843         &&  separate == 1)
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");
847                 return;
848         }
849         if (i != claimnr
850         &&  separate == 2)
851                 return;
852
853         ini = huntele(e, e->status, -1)->seqno;
854         fprintf(th, "#define start%d    %d\n", i, ini);
855         if (i == claimnr)
856         fprintf(th, "#define start_claim        %d\n", ini);
857         if (i == eventmapnr)
858         fprintf(th, "#define start_event        %d\n", ini);
859
860         fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
861
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);
865
866         if (has_provided)
867         {       fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
868                 if (P->prov)
869                 {       fprintf(tt, "if (");
870                         putstmnt(tt, P->prov, 0);
871                         fprintf(tt, ")\n\t\t\t");
872                 }
873                 fprintf(tt, "return 1;\n");
874                 if (P->prov)
875                         fprintf(tt, "\t\tbreak;\n");
876         }
877
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)
883                 {       lineno = t->ln;
884                         Fname  = t->fn;
885                         fatal("array in parameter list, %s",
886                         t->sym->name);
887                 }
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))
891                         {       lineno = t->ln;
892                                 Fname  = t->fn;
893                                 fatal("hidden array in parameter %s",
894                                 t->sym->name);
895                         }
896                 } else
897                         fprintf(tc, "%s", t->sym->name);
898                 fprintf(tc, " = par%d;\n", j);
899         }
900         fprintf(tc, "\t\t/* locals: */\n");
901         k = dolocal(tc, "", INIV, i, s->name);
902         if (k > 0)
903         {       fprintf(tc, "#ifdef VAR_RANGES\n");
904                 (void) dolocal(tc, "logval(\"", LOGV, i, s->name);
905                 fprintf(tc, "#endif\n");
906         }
907
908         fprintf(tc, "#ifdef HAS_CODE\n");
909         fprintf(tc, "\t\tlocinit%d(h);\n", i);
910         fprintf(tc, "#endif\n");
911
912         dumpclaims(tc, i, s->name);
913         fprintf(tc, "\t break;\n");
914 }
915
916 Element *
917 huntstart(Element *f)
918 {       Element *e = f;
919         Element *elast = (Element *) 0;
920         int cnt = 0;
921
922         while (elast != e && cnt++ < 200)       /* new 4.0.8 */
923         {       elast = e;
924                 if (e->n)
925                 {       if (e->n->ntyp == '.' && e->nxt)
926                                 e = e->nxt;
927                         else if (e->n->ntyp == UNLESS)
928                                 e = e->sub->this->frst;
929         }       }
930
931         if (cnt >= 200 || !e)
932                 fatal("confusing control structure", (char *) 0);
933         return e;
934 }
935
936 Element *
937 huntele(Element *f, int o, int stopat)
938 {       Element *g, *e = f;
939         int cnt=0; /* a precaution against loops */
940
941         if (e)
942         for (cnt = 0; cnt < 200 && e->n; cnt++)
943         {
944                 if (e->seqno == stopat)
945                         break;
946
947                 switch (e->n->ntyp) {
948                 case GOTO:
949                         g = get_lab(e->n,1);
950                         cross_dsteps(e->n, g->n);
951                         break;
952                 case '.':
953                 case BREAK:
954                         if (!e->nxt)
955                                 return e;
956                         g = e->nxt;
957                         break;
958                 case UNLESS:
959                         g = huntele(e->sub->this->frst, o, stopat);
960                         break;
961                 case D_STEP:
962                 case ATOMIC:
963                 case NON_ATOMIC:
964                 default:
965                         return e;
966                 }
967                 if ((o & ATOM) && !(g->status & ATOM))
968                         return e;
969                 e = g;
970         }
971         if (cnt >= 200 || !e)
972                 fatal("confusing control structure", (char *) 0);
973         return e;
974 }
975
976 void
977 typ2c(Symbol *sp)
978 {       int wsbits = sizeof(long)*8; /* wordsize in bits */
979         switch (sp->type) {
980         case UNSIGNED:
981                 if (sp->hidden&1)
982                         fprintf(th, "\tuchar %s;", sp->name);
983                 else
984                         fprintf(th, "\tunsigned %s : %d",
985                                 sp->name, sp->nbits);
986                 LstSet = sp;
987                 if (nBits%wsbits > 0
988                 &&  wsbits - nBits%wsbits < sp->nbits)
989                 {       /* must padd to a word-boundary */
990                         nBits += wsbits - nBits%wsbits;
991                 }
992                 nBits += sp->nbits;
993                 break;
994         case BIT:
995                 if (sp->nel == 1 && !(sp->hidden&1))
996                 {       fprintf(th, "\tunsigned %s : 1", sp->name);
997                         LstSet = sp; 
998                         nBits++;
999                         break;
1000                 } /* else fall through */
1001                 if (!(sp->hidden&1) && (verbose&32))
1002                 printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
1003                         sp->name, sp->nel);
1004                 nBits += 8*sp->nel; /* mapped onto array of uchars */
1005         case MTYPE:
1006         case BYTE:
1007         case CHAN:      /* good for up to 255 channels */
1008                 fprintf(th, "\tuchar %s", sp->name);
1009                 LstSet = sp;
1010                 break;
1011         case SHORT:
1012                 fprintf(th, "\tshort %s", sp->name);
1013                 LstSet = sp;
1014                 break;
1015         case INT:
1016                 fprintf(th, "\tint %s", sp->name);
1017                 LstSet = sp;
1018                 break;
1019         case STRUCT:
1020                 if (!sp->Snm)
1021                         fatal("undeclared structure element %s", sp->name);
1022                 fprintf(th, "\tstruct %s %s",
1023                         sp->Snm->name,
1024                         sp->name);
1025                 LstSet = ZS;
1026                 break;
1027         case CODE_FRAG:
1028         case PREDEF:
1029                 return;
1030         default:
1031                 fatal("variable %s undeclared", sp->name);
1032         }
1033
1034         if (sp->nel != 1)
1035                 fprintf(th, "[%d]", sp->nel);
1036         fprintf(th, ";\n");
1037 }
1038
1039 static void
1040 ncases(FILE *fd, int p, int n, int m, char *c[])
1041 {       int i, j;
1042
1043         for (j = 0; c[j]; j++)
1044         for (i = n; i < m; i++)
1045         {       fprintf(fd, c[j], i, p, i);
1046                 fprintf(fd, "\n");
1047         }
1048 }
1049
1050 void
1051 qlen_type(int qmax)
1052 {
1053         fprintf(th, "\t");
1054         if (qmax < 256)
1055                 fprintf(th, "uchar");
1056         else if (qmax < 65535)
1057                 fprintf(th, "ushort");
1058         else
1059                 fprintf(th, "uint");
1060         fprintf(th, " Qlen;     /* q_size */\n");
1061 }
1062
1063 void
1064 genaddqueue(void)
1065 {       char buf0[256];
1066         int j, qmax = 0;
1067         Queue *q;
1068
1069         ntimes(tc, 0, 1, Addq0);
1070         if (has_io && !nqs)
1071                 fprintf(th, "#define NQS        1 /* nqs=%d, but has_io */\n", nqs);
1072         else
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);
1076
1077         for (q = qtab; q; q = q->nxt)
1078                 if (q->nslots > qmax)
1079                         qmax = q->nslots;
1080
1081         for (q = qtab; q; q = q->nxt)
1082         {       j = q->qid;
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");
1087
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");
1092
1093                 for (j = 0; j < q->nflds; j++)
1094                 {       switch (q->fld_width[j]) {
1095                         case BIT:
1096                                 if (q->nflds != 1)
1097                                 {       fprintf(th, "\t\tunsigned");
1098                                         fprintf(th, " fld%d : 1;\n", j);
1099                                         break;
1100                                 } /* else fall through: smaller struct */
1101                         case MTYPE:
1102                         case CHAN:
1103                         case BYTE:
1104                                 fprintf(th, "\t\tuchar fld%d;\n", j);
1105                                 break;
1106                         case SHORT:
1107                                 fprintf(th, "\t\tshort fld%d;\n", j);
1108                                 break;
1109                         case INT:
1110                                 fprintf(th, "\t\tint fld%d;\n", j);
1111                                 break;
1112                         default:
1113                                 fatal("bad channel spec", "");
1114                         }
1115                 }
1116                 fprintf(th, "   } contents[%d];\n", max(1, q->nslots));
1117                 fprintf(th, "} Q%d;\n", q->qid);
1118         }
1119
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");
1124
1125         ntimes(tc, 0, 1, Addq1);
1126
1127         if (has_random)
1128         {       fprintf(th, "int Q_has(int");
1129                 for (j = 0; j < Mpars; j++)
1130                         fprintf(th, ", int, int");
1131                 fprintf(th, ");\n");
1132
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);
1136                 fprintf(tc, ")\n");
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",
1149                                 j, j);
1150                         fprintf(tc, "                   continue;\n");
1151                 }
1152                 fprintf(tc, "           return i+1;\n");
1153                 fprintf(tc, "   }\n");
1154                 fprintf(tc, "   return 0;\n");
1155                 fprintf(tc, "}\n");
1156         }
1157
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);
1162         fprintf(tc, ")\n");
1163         ntimes(tc, 0, 1, Addq11);
1164
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");
1171
1172                 if (has_sorted)
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",
1179                                                 j, buf0, j);
1180                                 fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
1181                                 fprintf(tc, "goto found%d;\n\n", q->qid);
1182                         }
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 = ",
1190                                         buf0, j);
1191                                 fprintf(tc, "%scontents[k].fld%d;\n",
1192                                         buf0, j);
1193                         }
1194                         fprintf(tc, "\t\t}\n");
1195                         fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
1196                 }
1197
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");
1206         }
1207         ntimes(tc, 0, 1, Addq2);
1208
1209         for (q = qtab; q; q = q->nxt)
1210         fprintf(tc, "\tcase %d: return %d;\n", q->qid, (!q->nslots));
1211
1212         ntimes(tc, 0, 1, Addq3);
1213
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));
1217
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= */");
1223                 if (q->nflds == 1)
1224                 {       fprintf(tc, "if (fld == 0) r = %s", buf0);
1225                         fprintf(tc, "contents[slot].fld0;\n");
1226                 } else
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");
1232                 }
1233                 fprintf(tc, "\t\tif (done)\n");
1234                 if (q->nslots == 0)
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);
1238                 } else
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);
1247                         }
1248                         fprintf(tc, "\t\t       }\n");
1249                 }
1250
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");
1258         }
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",
1262                 q->qid, q->qid);
1263         ntimes(tc, 0, 1, R8b);
1264
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");
1270
1271         fprintf(th, "#define Addproc(x) addproc(x");
1272         for (j = 0; j < Npars; j++)
1273                 fprintf(th, ", 0");
1274         fprintf(th, ")\n");
1275 }