]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/spin/pangen1.c
spin: Update to most recent version. (thanks Ori_B)
[plan9front.git] / sys / src / cmd / spin / pangen1.c
1 /***** spin: pangen1.c *****/
2
3 /*
4  * This file is part of the public release of Spin. It is subject to the
5  * terms in the LICENSE file that is included in this source directory.
6  * Tool documentation is available at http://spinroot.com
7  */
8
9 #include "spin.h"
10 #include "y.tab.h"
11 #include "pangen1.h"
12 #include "pangen3.h"
13 #include "pangen6.h"
14 #include <assert.h>
15 #ifdef SOLARIS
16 #include <sys/int_limits.h>
17 #else
18 #include <stdint.h>
19 #endif
20
21 extern FILE     *tc, *th, *tt;
22 extern Label    *labtab;
23 extern Ordered  *all_names;
24 extern ProcList *rdy;
25 extern Queue    *qtab;
26 extern Symbol   *Fname;
27 extern int      lineno, verbose, Pid, separate, old_scope_rules, nclaims;
28 extern int      nrRdy, nqs, mst, Mpars, claimnr, eventmapnr;
29 extern short    has_sorted, has_random, has_provided, has_priority;
30 extern Queue    *ltab[];
31
32 int     Npars=0, u_sync=0, u_async=0, hastrack = 1;
33 short   has_io = 0;
34 short   has_state=0;    /* code contains c_state */
35
36 static Symbol   *LstSet=ZS;
37 static int      acceptors=0, progressors=0, nBits=0;
38 static int      Types[] = { UNSIGNED, BIT, BYTE, CHAN, MTYPE, SHORT, INT, STRUCT };
39
40 static int      doglobal(char *, int);
41 static void     dohidden(void);
42 static void     do_init(FILE *, Symbol *);
43 static void     end_labs(Symbol *, int);
44 static void     put_ptype(char *, int, int, int, enum btypes);
45 static void     tc_predef_np(void);
46 static void     put_pinit(ProcList *);
47 static void     multi_init(void);
48        void     walk_struct(FILE *, int, char *, Symbol *, char *, char *, char *);
49
50 static void
51 reverse_names(ProcList *p)
52 {
53         if (!p) return;
54         reverse_names(p->nxt);
55         fprintf(tc, "   \"%s\",\n", p->n->name);
56 }
57 static void
58 reverse_types(ProcList *p)
59 {
60         if (!p) return;
61         reverse_types(p->nxt);
62         fprintf(tc, "   %d,     /* %s */\n", p->b, p->n->name);
63 }
64
65 static int
66 blog(int n)     /* for small log2 without rounding problems */
67 {       int m=1, r=2;
68
69         while (r < n) { m++; r *= 2; }
70         return 1+m;
71 }
72
73 void
74 genheader(void)
75 {       ProcList *p; int i;
76
77         if (separate == 2)
78         {       putunames(th);
79                 goto here;
80         }
81         /* 5.2.3: gcc 3 no longer seems to compute sizeof at compile time */
82         fprintf(th, "#define WS         %d /* word size in bytes */\n", (int) sizeof(void *));
83         fprintf(th, "#define SYNC       %d\n", u_sync);
84         fprintf(th, "#define ASYNC      %d\n\n", u_async);
85         fprintf(th, "#ifndef NCORE\n");
86         fprintf(th, "   #ifdef DUAL_CORE\n");
87         fprintf(th, "           #define NCORE   2\n");
88         fprintf(th, "   #elif QUAD_CORE\n");
89         fprintf(th, "           #define NCORE   4\n");
90         fprintf(th, "   #else\n");
91         fprintf(th, "           #define NCORE   1\n");
92         fprintf(th, "   #endif\n");
93         fprintf(th, "#endif\n\n");
94
95         putunames(th);
96
97         fprintf(tc, "\nshort Air[] = { ");
98         for (p = rdy, i=0; p; p = p->nxt, i++)
99                 fprintf(tc, "%s (short) Air%d", (p!=rdy)?",":"", i);
100         fprintf(tc, ", (short) Air%d", i);      /* np_ */
101         if (nclaims > 1)
102         {       fprintf(tc, "\n#ifndef NOCLAIM\n");
103                 fprintf(tc, "   , (short) Air%d", i+1); /* Multi */
104                 fprintf(tc, "\n#endif\n\t");
105         }
106         fprintf(tc, " };\n");
107
108         fprintf(tc, "char *procname[] = {\n");
109                 reverse_names(rdy);
110         fprintf(tc, "   \":np_:\",\n");
111         fprintf(tc, "   0\n");
112         fprintf(tc, "};\n\n");
113
114         fprintf(tc, "enum btypes { NONE=%d, N_CLAIM=%d,", NONE, N_CLAIM);
115         fprintf(tc, " I_PROC=%d, A_PROC=%d,", I_PROC, A_PROC);
116         fprintf(tc, " P_PROC=%d, E_TRACE=%d, N_TRACE=%d };\n\n",
117                 P_PROC, E_TRACE, N_TRACE);
118
119         fprintf(tc, "int Btypes[] = {\n");
120                 reverse_types(rdy);
121         fprintf(tc, "   0       /* :np_: */\n");
122         fprintf(tc, "};\n\n");
123
124 here:
125         for (p = rdy; p; p = p->nxt)
126                 put_ptype(p->n->name, p->tn, mst, nrRdy+1, p->b);
127                 /* +1 for np_ */
128         put_ptype("np_", nrRdy, mst, nrRdy+1, 0);
129
130         if (nclaims > 1)
131         {       /* this is the structure that goes into the state-vector
132                  * instead of the actual never claims
133                  * this assumes that the claims do not have any local variables
134                  * this claim records the types and states of all subclaims in an array
135                  * NB: not sure if we need the first 3 fields in this structure
136                  *     it's here for now to avoid breaking some possible dependence
137                  * in the calculations above, we were already taking into account
138                  * that there is one never-claim, which will now be this one
139                  */
140
141                 i = blog(mst);
142                 fprintf(th, "\n");
143
144                 fprintf(th, "#ifndef NOCLAIM\n");
145                 fprintf(th, "   #undef VERI\n");
146                 fprintf(th, "   #define VERI    %d\n", nrRdy+1);
147                 fprintf(th, "   #define Pclaim  P%d\n\n", nrRdy+1);
148                 fprintf(th, "typedef struct P%d {\n", nrRdy+1);
149                 fprintf(th, "   unsigned _pid : 8; /* always zero */\n");
150                 fprintf(th, "   unsigned _t   : %d; /* active-claim type  */\n",
151                         blog(nrRdy+1));
152                 fprintf(th, "   unsigned _p   : %d; /* active-claim state */\n",
153                         i);
154                 fprintf(th, "   unsigned _n   : %d; /* active-claim index */\n",
155                         blog(nclaims));
156                 if (i <= UINT8_MAX)     /* in stdint.h = UCHAR_MAX from limits.h */
157                 {       fprintf(th, "   uchar c_cur[NCLAIMS]; /* claim-states */\n");
158                 } else if (i <= UINT16_MAX)     /* really USHRT_MAX from limits.h */
159                 {       fprintf(th, "   ushort c_cur[NCLAIMS]; /* claim-states */\n");
160                 } else  /* the most unlikely case */
161                 {       fprintf(th, "   uint c_cur[NCLAIMS]; /* claim-states */\n");
162                 }
163                 fprintf(th, "} P%d;\n", nrRdy+1);
164
165                 fprintf(tc, "#ifndef NOCLAIM\n");
166                 fprintf(tc, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n");
167                 fprintf(tc, "#endif\n");
168
169                 fprintf(th, "   #define Air%d   (0)\n\n", nrRdy+1);
170                 fprintf(th, "#endif\n");
171                 /*
172                  * find special states as:
173                  *      stopstate [ claimnr ][ curstate ] == 1
174                  *      accpstate [ claimnr ][ curstate ]
175                  *      progstate [ claimnr ][ curstate ]
176                  *      reached   [ claimnr ][ curstate ]
177                  *      visstate  [ claimnr ][ curstate ]
178                  *      loopstate [ claimnr ][ curstate ]
179                  *      mapstate  [ claimnr ][ curstate ]
180                  */
181         } else
182         {       fprintf(th, "#define Pclaim     P0\n");
183                 fprintf(th, "#ifndef NCLAIMS\n");
184                 fprintf(th, "   #define NCLAIMS 1\n");
185                 fprintf(th, "#endif\n");
186                 fprintf(tc, "uchar spin_c_typ[NCLAIMS]; /* claim-types */\n");
187         }
188
189         ntimes(th, 0, 1, Head0);
190
191         if (separate != 2)
192         {       extern void c_add_stack(FILE *);
193                 extern void c_stack_size(FILE *);
194
195                 ntimes(th, 0, 1, Header);
196                 fprintf(th, "#define StackSize  (");
197                         c_stack_size(th);
198                 fprintf(th, ")\n");
199
200                 c_add_stack(th);
201                 ntimes(th, 0, 1, Header0);
202         } else
203         {       fprintf(th, "extern char *emalloc(unsigned long);\n");
204         }
205         ntimes(th, 0, 1, Head1);
206
207         LstSet = ZS;
208         (void) doglobal("", PUTV);
209
210         hastrack = c_add_sv(th);
211
212         fprintf(th, "#ifdef TRIX\n");
213         fprintf(th, "   /* room for 512 proc+chan ptrs, + safety margin */\n");
214         fprintf(th, "   char *_ids_[MAXPROC+MAXQ+4];\n");
215         fprintf(th, "#else\n");
216         fprintf(th, "   uchar sv[VECTORSZ];\n");
217         fprintf(th, "#endif\n");
218
219         fprintf(th, "} State");
220 #ifdef SOLARIS
221         fprintf(th,"\n#ifdef GCC\n");
222         fprintf(th, "\t__attribute__ ((aligned(8)))");
223         fprintf(th, "\n#endif\n\t");
224 #endif
225         fprintf(th, ";\n\n");
226
227         fprintf(th, "#ifdef TRIX\n");
228         fprintf(th, "typedef struct TRIX_v6 {\n");
229         fprintf(th, "   uchar *body; /* aligned */\n");
230         fprintf(th, "#ifndef BFS\n");
231         fprintf(th, "   short modified;\n");
232         fprintf(th, "#endif\n");
233         fprintf(th, "   short psize;\n");
234         fprintf(th, "   short parent_pid;\n");
235         fprintf(th, "   struct TRIX_v6 *nxt;\n");
236         fprintf(th, "} TRIX_v6;\n");
237         fprintf(th, "#endif\n\n");
238
239         fprintf(th, "#define HAS_TRACK  %d\n", hastrack);
240         if (0 && hastrack)      /* not really a problem */
241         {       fprintf(th, "#ifdef BFS_PAR\n");
242                 fprintf(th, "   #error cannot use BFS_PAR on models with c_track stmnts\n");
243                 fprintf(th, "#endif\n");
244         }
245         if (separate != 2)
246                 dohidden();
247 }
248
249 void
250 genaddproc(void)
251 {       ProcList *p;
252         int i = 0;
253
254         if (separate == 2) goto shortcut;
255
256         ntimes(tc, nrRdy+1, nrRdy+2, R2); /* +1 for np_ -- was th */
257
258         fprintf(tc, "#ifdef TRIX\n");
259         fprintf(tc, "int what_p_size(int);\n");
260         fprintf(tc, "int what_q_size(int);\n\n");
261
262         /* the number of processes just changed by 1 (up or down) */
263         /* this means that the channel indices move up or down by one slot */
264         /* not all new channels may have a valid index yet, but we move */
265         /* all of them anyway, as if they existed */
266         ntimes(tc, 0, 1, R7a);
267         fprintf(tc, "#endif\n\n");
268
269         ntimes(tc, 0, 1, R7b);
270
271         fprintf(tc, "int\naddproc(int calling_pid, int priority, int n");
272         for (/* i = 0 */; i < Npars; i++)
273                 fprintf(tc, ", int par%d", i);
274
275         ntimes(tc, 0, 1, Addp0);
276         ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
277
278         if (nclaims > 1)
279         {       fprintf(tc, "#ifndef NOCLAIM\n");
280                 ntimes(tc, nrRdy+1, nrRdy+2, R5);
281                 fprintf(tc, "#endif\n");
282         }
283
284         ntimes(tc, 0, 1, Addp1);
285
286         if (has_provided)
287         {       fprintf(tt, "\nint\nprovided(int II, unsigned char ot, ");
288                 fprintf(tt, "int tt, Trans *t)\n");
289                 fprintf(tt, "{\n\tswitch(ot) {\n");
290         }
291 shortcut:
292         if (nclaims > 1)
293         {       multi_init();
294         }
295         tc_predef_np();
296         for (p = rdy; p; p = p->nxt)
297         {       Pid = p->tn;
298                 put_pinit(p);
299         }
300         if (separate == 2) return;
301
302         Pid = 0;
303         if (has_provided)
304         {       fprintf(tt, "\tdefault: return 1; /* e.g., a claim */\n");
305                 fprintf(tt, "\t}\n\treturn 0;\n}\n");
306         }
307
308         ntimes(tc, i, i+1, R6);
309         if (separate == 0)
310                 ntimes(tc, 1, nrRdy+1, R5); /* +1 for np_ */
311         else
312                 ntimes(tc, 1, nrRdy, R5);
313         ntimes(tc, 0, 1, R8a);
314 }
315
316 void
317 do_locinits(FILE *fd)
318 {       ProcList *p;
319
320         /* the locinit functions may refer to pptr or qptr */
321         fprintf(fd, "#if VECTORSZ>32000\n");
322         fprintf(fd, "   extern int \n");
323         fprintf(fd, "#else\n");
324         fprintf(fd, "   extern short \n");
325         fprintf(fd, "#endif\n");
326         fprintf(fd, "   *proc_offset, *q_offset;\n");
327
328         for (p = rdy; p; p = p->nxt)
329         {       c_add_locinit(fd, p->tn, p->n->name);
330         }
331 }
332
333 void
334 genother(void)
335 {       ProcList *p;
336
337         switch (separate) {
338         case 2:
339                 if (nclaims > 0)
340                 {       for (p = rdy; p; p = p->nxt)
341                         {       if (p->b == N_CLAIM)
342                                 {       ntimes(tc, p->tn, p->tn+1, R0); /* claims only */
343                                         fprintf(tc, "#ifdef HAS_CODE\n");
344                                         ntimes(tc, p->tn, p->tn+1, R00);
345                                         fprintf(tc, "#endif\n");
346                 }       }       }
347                 break;
348         case 1:
349                 ntimes(tc,     0,    1, Code0);
350                 for (p = rdy; p; p = p->nxt)
351                 {       if (p->b != N_CLAIM)
352                         {       ntimes(tc, p->tn, p->tn+1, R0); /* all except claims */
353                                 fprintf(tc, "#ifdef HAS_CODE\n");
354                                 ntimes(tc, p->tn, p->tn+1, R00);
355                                 fprintf(tc, "#endif\n");
356                 }       }
357                 break;
358         case 0:
359                 ntimes(tc,     0,    1, Code0);
360                 ntimes(tc,     0, nrRdy+1, R0); /* +1 for np_ */
361                 fprintf(tc, "#ifdef HAS_CODE\n");
362                 ntimes(tc,     0, nrRdy+1, R00); /* +1 for np_ */
363                 fprintf(tc, "#endif\n");
364                 break;
365         }
366         /* new place, make sure Maxbody is set to its final value here */
367         fprintf(tc, "\n");
368
369         if (separate != 2)
370         {       ntimes(tc, 1, u_sync+u_async+1, R3); /* nqs is still 0 */
371                 fprintf(tc, "\tMaxbody = max(Maxbody, sizeof(State)-VECTORSZ);\n");
372                 fprintf(tc, "\tif ((Maxbody %% WS) != 0)\n");
373                 fprintf(tc, "\t Maxbody += WS - (Maxbody %% WS);\n\n");
374         }
375
376         for (p = rdy; p; p = p->nxt)
377                 end_labs(p->n, p->tn);
378
379         switch (separate) {
380         case 2:
381                 if (nclaims > 0)
382                 {       for (p = rdy; p; p = p->nxt)
383                         {       if (p->b == N_CLAIM)
384                                 {       ntimes(tc, p->tn, p->tn+1, R0a); /* claims only */
385                 }       }       }
386                 return;
387         case 1:
388                 for (p = rdy; p; p = p->nxt)
389                 {       if (p->b != N_CLAIM)
390                         {       ntimes(tc, p->tn, p->tn+1, R0a); /* all except claims */
391                 }       }
392                 fprintf(tc, "   if (state_tables)\n");
393                 fprintf(tc, "           ini_claim(%d, 0);\n", claimnr); /* the default claim */
394                 if (acceptors == 0)
395                 {       acceptors = 1;  /* assume at least 1 acceptstate */
396                 }
397                 break;
398         case 0:
399                 ntimes(tc, 0, nrRdy, R0a);      /* all */
400                 break;
401         }
402
403         ntimes(th, acceptors,   acceptors+1,   Code1);
404         ntimes(th, progressors, progressors+1, Code3);
405
406         ntimes(tc, 0,     1, Code2a);   /* dfs, bfs */
407         ntimes(tc, 0,     1, Code2e);   /* multicore */
408         ntimes(tc, 0,     1, Code2c);   /* multicore */
409         ntimes(tc, 0,     1, Code2d);
410
411         fprintf(tc, "void\ndo_reach(void)\n{\n");
412         ntimes(tc, 0,     nrRdy, R4);
413         fprintf(tc, "}\n\n");
414
415         fprintf(tc, "void\niniglobals(int calling_pid)\n{\n");
416         if (doglobal("", INIV) > 0)
417         {       fprintf(tc, "#ifdef VAR_RANGES\n");
418                 (void) doglobal("logval(\"", LOGV);
419                 fprintf(tc, "#endif\n");
420         }
421         fprintf(tc, "}\n\n");
422 }
423
424 void
425 gensvmap(void)
426 {
427         ntimes(tc, 0, 1, SvMap);
428 }
429
430 static struct {
431         char *s,        *t;             int n,  m,      p;
432 } ln[] = {
433         {"end",         "stopstate",    3,      0,      0},
434         {"progress",    "progstate",    8,      0,      1},
435         {"accept",      "accpstate",    6,      1,      0},
436         {0,             0,              0,      0,      0},
437 };
438
439 static void
440 end_labs(Symbol *s, int i)
441 {       int oln = lineno;
442         Symbol *ofn = Fname;
443         Label *l;
444         int j; char foo[128];
445
446         if ((pid_is_claim(i) && separate == 1)
447         || (!pid_is_claim(i) && separate == 2))
448                 return;
449
450         for (l = labtab; l; l = l->nxt)
451         for (j = 0; ln[j].n; j++)
452         {       if (strncmp(l->s->name, ln[j].s, ln[j].n) == 0
453                 &&  strcmp(l->c->name, s->name) == 0)
454                 {       fprintf(tc, "\t%s[%d][%d] = 1;\n",
455                                 ln[j].t, i, l->e->seqno);
456                         acceptors   += ln[j].m;
457                         progressors += ln[j].p;
458                         if (l->e->status & D_ATOM)
459                         {       sprintf(foo, "%s label inside d_step",
460                                         ln[j].s);
461                                 goto complain;
462                         }
463                         if (j > 0 && (l->e->status & ATOM))
464                         {       sprintf(foo, "%s label inside atomic",
465                                         ln[j].s);
466                 complain:       lineno = l->e->n->ln;
467                                 Fname  = l->e->n->fn;
468                                 printf("spin: %3d:%s, warning, %s - is invisible\n",
469                                         lineno, Fname?Fname->name:"-", foo);
470         }       }       }       
471         /* visible states -- through remote refs: */
472         for (l = labtab; l; l = l->nxt)
473                 if (l->visible
474                 &&  strcmp(l->s->context->name, s->name) == 0)
475                 fprintf(tc, "\tvisstate[%d][%d] = 1;\n",
476                                 i, l->e->seqno);
477
478         lineno = oln;
479         Fname  = ofn;
480 }
481
482 void
483 ntimes(FILE *fd, int n, int m, const char *c[])
484 {
485         int i, j;
486         for (j = 0; c[j]; j++)
487         for (i = n; i < m; i++)
488         {       fprintf(fd, c[j], i, i, i, i, i, i);
489                 fprintf(fd, "\n");
490         }
491 }
492
493 void
494 prehint(Symbol *s)
495 {       Lextok *n;
496
497         printf("spin: warning, ");
498         if (!s) return;
499
500         n = (s->context != ZS)?s->context->ini:s->ini;
501         if (n)
502         printf("line %s:%d, ", n->fn->name, n->ln);
503 }
504
505 void
506 checktype(Symbol *sp, char *s)
507 {       char buf[128]; int i;
508
509         if (!s
510         || (sp->type != BYTE
511         &&  sp->type != SHORT
512         &&  sp->type != INT))
513                 return;
514
515         if (sp->hidden&16)      /* formal parameter */
516         {       ProcList *p; Lextok *f, *t;
517                 int posnr = 0;
518                 for (p = rdy; p; p = p->nxt)
519                         if (p->n->name
520                         &&  strcmp(s, p->n->name) == 0)
521                                 break;
522                 if (p)
523                 for (f = p->p; f; f = f->rgt) /* list of types */
524                 for (t = f->lft; t; t = t->rgt, posnr++)
525                         if (t->sym
526                         &&  strcmp(t->sym->name, sp->name) == 0)
527                         {       checkrun(sp, posnr);
528                                 return;
529                         }
530
531         } else if (!(sp->hidden&4))
532         {       if (!(verbose&32)) return;
533                 sputtype(buf, sp->type);
534                 i = (int) strlen(buf);
535                 while (i > 0 && buf[--i] == ' ') buf[i] = '\0';
536                 prehint(sp);
537                 if (sp->context)
538                         printf("proctype %s:", s);
539                 else
540                         printf("global");
541                 printf(" '%s %s' could be declared 'bit %s'\n",
542                         buf, sp->name, sp->name);
543         } else if (sp->type != BYTE && !(sp->hidden&8))
544         {       if (!(verbose&32)) return;
545                 sputtype(buf, sp->type);
546                 i = (int) strlen(buf);
547                 while (buf[--i] == ' ') buf[i] = '\0';
548                 prehint(sp);
549                 if (sp->context)
550                         printf("proctype %s:", s);
551                 else
552                         printf("global");
553                 printf(" '%s %s' could be declared 'byte %s'\n",
554                         buf, sp->name, sp->name);
555         }
556 }
557
558 static int
559 dolocal(FILE *ofd, char *pre, int dowhat, int p, char *s, enum btypes b)
560 {       int h, j, k=0; extern int nr_errs;
561         Ordered *walk;
562         Symbol *sp;
563         char buf[128], buf2[128], buf3[128];
564
565         if (dowhat == INIV)
566         {       /* initialize in order of declaration */
567                 for (walk = all_names; walk; walk = walk->next)
568                 {       sp = walk->entry;
569                         if (sp->context
570                         && !sp->owner
571                         &&  strcmp(s, sp->context->name) == 0)
572                         {       checktype(sp, s); /* fall through */
573                                 if (!(sp->hidden&16))
574                                 {       sprintf(buf, "((P%d *)pptr(h))->", p);
575                                         do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
576                                 }
577                                 k++;
578                 }       }
579         } else
580         {       for (j = 0; j < 8; j++)
581                 for (h = 0; h <= 1; h++)
582                 for (walk = all_names; walk; walk = walk->next)
583                 {       sp = walk->entry;
584                         if (sp->context
585                         && !sp->owner
586                         &&  sp->type == Types[j]
587                         &&  ((h == 0 && (sp->nel == 1 && sp->isarray == 0))
588                         ||   (h == 1 && (sp->nel  > 1 || sp->isarray == 1)))
589                         &&  strcmp(s, sp->context->name) == 0)
590                         {       switch (dowhat) {
591                                 case LOGV:
592                                         if (sp->type == CHAN
593                                         &&  verbose == 0)
594                                                 break;
595                                         sprintf(buf, "%s%s:", pre, s);
596                                         { sprintf(buf2, "\", ((P%d *)pptr(h))->", p);
597                                           sprintf(buf3, ");\n");
598                                         }
599                                         do_var(ofd, dowhat, "", sp, buf, buf2, buf3);
600                                         break;
601                                 case PUTV:
602                                         sprintf(buf, "((P%d *)pptr(h))->", p);
603                                         do_var(ofd, dowhat, buf, sp, "", " = ", ";\n");
604                                         k++;
605                                         break;
606                                 }
607                                 if (b == N_CLAIM)
608                                 {       printf("error: %s defines local %s\n",
609                                                 s, sp->name);
610                                         nr_errs++;
611         }       }       }       }
612
613         return k;
614 }
615
616 void
617 c_chandump(FILE *fd)
618 {       Queue *q;
619         char buf[256];
620         int i;
621
622         if (!qtab)
623         {       fprintf(fd, "void\nc_chandump(int unused)\n");
624                 fprintf(fd, "{\tunused++; /* avoid complaints */\n}\n");
625                 return;
626         }
627
628         fprintf(fd, "void\nc_chandump(int from)\n");
629         fprintf(fd, "{  uchar *z; int slot;\n");
630
631         fprintf(fd, "   from--;\n");
632         fprintf(fd, "   if (from >= (int) now._nr_qs || from < 0)\n");
633         fprintf(fd, "   {       printf(\"pan: bad qid %%d\\n\", from+1);\n");
634         fprintf(fd, "           return;\n");
635         fprintf(fd, "   }\n");
636         fprintf(fd, "   z = qptr(from);\n");
637         fprintf(fd, "   switch (((Q0 *)z)->_t) {\n");
638
639         for (q = qtab; q; q = q->nxt)
640         {       fprintf(fd, "   case %d:\n\t\t", q->qid);
641                 sprintf(buf, "((Q%d *)z)->", q->qid);
642
643                 fprintf(fd, "for (slot = 0; slot < %sQlen; slot++)\n\t\t", buf);
644                 fprintf(fd, "{  printf(\" [\");\n\t\t");
645                 for (i = 0; i < q->nflds; i++)
646                 {       if (q->fld_width[i] == MTYPE)
647                         {       fprintf(fd, "\tprintm(%scontents[slot].fld%d);\n\t\t",
648                                 buf, i);
649                         } else
650                         fprintf(fd, "\tprintf(\"%%d,\", %scontents[slot].fld%d);\n\t\t",
651                                 buf, i);
652                 }
653                 fprintf(fd, "   printf(\"],\");\n\t\t");
654                 fprintf(fd, "}\n\t\t");
655                 fprintf(fd, "break;\n");
656         }
657         fprintf(fd, "   }\n");
658         fprintf(fd, "   printf(\"\\n\");\n}\n");
659 }
660
661 void
662 c_var(FILE *fd, char *pref, Symbol *sp)
663 {       char *ptr, buf[256];
664         int i;
665
666         if (!sp)
667         {       fatal("cannot happen - c_var", 0);
668         }
669
670         ptr = sp->name;
671         if (!old_scope_rules)
672         {       while (*ptr == '_' || isdigit((int)*ptr))
673                 {       ptr++;
674         }       }
675
676         switch (sp->type) {
677         case STRUCT:
678                 /* c_struct(fd, pref, sp); */
679                 fprintf(fd, "\t\tprintf(\"\t(struct %s)\\n\");\n",
680                         sp->name);
681                 sprintf(buf, "%s%s.", pref, sp->name);
682                 c_struct(fd, buf, sp);
683                 break;
684         case MTYPE:
685         case BIT:   case BYTE:
686         case SHORT: case INT:
687         case UNSIGNED:
688                 sputtype(buf, sp->type);
689                 if (sp->nel == 1 && sp->isarray == 0)
690                 {
691                         if (sp->type == MTYPE && ismtype(sp->name))
692                         {       fprintf(fd, "\tprintf(\"\t%s %s:\t%d\\n\");\n",
693                                         buf, ptr, ismtype(sp->name));
694                         } else
695                         {       fprintf(fd, "\tprintf(\"\t%s %s:\t%%d\\n\", %s%s);\n",
696                                         buf, ptr, pref, sp->name);
697                         }
698                 } else
699                 {       fprintf(fd, "\t{\tint l_in;\n");
700                         fprintf(fd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n", sp->nel);
701                         fprintf(fd, "\t\t{\n");
702                         fprintf(fd, "\t\t\tprintf(\"\t%s %s[%%d]:\t%%d\\n\", l_in, %s%s[l_in]);\n",
703                                                 buf, ptr, pref, sp->name);
704                         fprintf(fd, "\t\t}\n");
705                         fprintf(fd, "\t}\n");
706                 }
707                 break;
708         case CHAN:
709                 if (sp->nel == 1 && sp->isarray == 0)
710                 {  fprintf(fd, "\tprintf(\"\tchan %s (=%%d):\tlen %%d:\\t\", ", ptr);
711                    fprintf(fd, "%s%s, q_len(%s%s));\n",
712                         pref, sp->name, pref, sp->name);
713                    fprintf(fd, "\tc_chandump(%s%s);\n", pref, sp->name);
714                 } else
715                 for (i = 0; i < sp->nel; i++)
716                 {  fprintf(fd, "\tprintf(\"\tchan %s[%d] (=%%d):\tlen %%d:\\t\", ",
717                         ptr, i);
718                    fprintf(fd, "%s%s[%d], q_len(%s%s[%d]));\n",
719                         pref, sp->name, i, pref, sp->name, i);
720                    fprintf(fd, "\tc_chandump(%s%s[%d]);\n",
721                         pref, sp->name, i);
722                 }
723                 break;
724         }
725 }
726
727 int
728 c_splurge_any(ProcList *p)
729 {       Ordered *walk;
730         Symbol *sp;
731
732         if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
733         for (walk = all_names; walk; walk = walk->next)
734         {       sp = walk->entry;
735                 if (!sp->context
736                 ||  sp->type == 0
737                 ||  strcmp(sp->context->name, p->n->name) != 0
738                 ||  sp->owner || (sp->hidden&1)
739                 || (sp->type == MTYPE && ismtype(sp->name)))
740                         continue;
741
742                 return 1;
743         }
744         return 0;
745 }
746
747 void
748 c_splurge(FILE *fd, ProcList *p)
749 {       Ordered *walk;
750         Symbol *sp;
751         char pref[64];
752
753         if (p->b != N_CLAIM && p->b != E_TRACE && p->b != N_TRACE)
754         for (walk = all_names; walk; walk = walk->next)
755         {       sp = walk->entry;
756                 if (!sp->context
757                 ||  sp->type == 0
758                 ||  strcmp(sp->context->name, p->n->name) != 0
759                 ||  sp->owner || (sp->hidden&1)
760                 || (sp->type == MTYPE && ismtype(sp->name)))
761                         continue;
762
763                 sprintf(pref, "((P%d *)pptr(pid))->", p->tn);
764                 c_var(fd, pref, sp);
765         }
766 }
767
768 void
769 c_wrapper(FILE *fd)     /* allow pan.c to print out global sv entries */
770 {       Ordered *walk;
771         ProcList *p;
772         Symbol *sp;
773         Lextok *n;
774         extern Lextok *Mtype;
775         int j;
776
777         fprintf(fd, "void\nc_globals(void)\n{\t/* int i; */\n");
778         fprintf(fd, "   printf(\"global vars:\\n\");\n");
779         for (walk = all_names; walk; walk = walk->next)
780         {       sp = walk->entry;
781                 if (sp->context || sp->owner || (sp->hidden&1))
782                         continue;
783                 c_var(fd, "now.", sp);
784         }
785         fprintf(fd, "}\n");
786
787         fprintf(fd, "void\nc_locals(int pid, int tp)\n{\t/* int i; */\n");
788         fprintf(fd, "   switch(tp) {\n");
789         for (p = rdy; p; p = p->nxt)
790         {       fprintf(fd, "   case %d:\n", p->tn);
791                 if (c_splurge_any(p))
792                 {       fprintf(fd, "   \tprintf(\"local vars proc %%d (%s):\\n\", pid);\n",
793                                 p->n->name);
794                         c_splurge(fd, p);
795                 } else
796                 {       fprintf(fd, "   \t/* none */\n");
797                 }
798                 fprintf(fd, "   \tbreak;\n");
799         }
800         fprintf(fd, "   }\n}\n");
801
802         fprintf(fd, "void\nprintm(int x)\n{\n");
803         fprintf(fd, "   switch (x) {\n");
804         for (n = Mtype, j = 1; n && j; n = n->rgt, j++)
805                 fprintf(fd, "\tcase %d: Printf(\"%s\"); break;\n",
806                         j, n->lft->sym->name);
807         fprintf(fd, "   default: Printf(\"%%d\", x);\n");
808         fprintf(fd, "   }\n");
809         fprintf(fd, "}\n");
810 }
811
812 static int
813 doglobal(char *pre, int dowhat)
814 {       Ordered *walk;
815         Symbol *sp;
816         int j, cnt = 0;
817
818         for (j = 0; j < 8; j++)
819         for (walk = all_names; walk; walk = walk->next)
820         {       sp = walk->entry;
821                 if (!sp->context
822                 &&  !sp->owner
823                 &&  sp->type == Types[j])
824                 {       if (Types[j] != MTYPE || !ismtype(sp->name))
825                         switch (dowhat) {
826                         case LOGV:
827                                 if (sp->type == CHAN
828                                 &&  verbose == 0)
829                                         break;
830                                 if (sp->hidden&1)
831                                         break;
832                                 do_var(tc, dowhat, "", sp,
833                                         pre, "\", now.", ");\n");
834                                 break;
835                         case INIV:
836                                 checktype(sp, (char *) 0);
837                                 cnt++; /* fall through */
838                         case PUTV:
839                                 do_var(tc, dowhat,
840                                         (sp->hidden&1)?"":"now.", sp,
841                                         "", " = ", ";\n");
842                                 break;
843         }       }       }
844         return cnt;
845 }
846
847 static void
848 dohidden(void)
849 {       Ordered *walk;
850         Symbol *sp;
851         int j;
852
853         for (j = 0; j < 8; j++)
854         for (walk = all_names; walk; walk = walk->next)
855         {       sp = walk->entry;
856                 if ((sp->hidden&1)
857                 &&  sp->type == Types[j])
858                 {       if (sp->context || sp->owner)
859                           fatal("cannot hide non-globals (%s)", sp->name);
860                         if (sp->type == CHAN)
861                           fatal("cannot hide channels (%s)", sp->name);
862                         fprintf(th, "/* hidden variable: */");
863                         typ2c(sp);
864         }       }
865 }
866
867 void
868 do_var(FILE *ofd, int dowhat, char *s, Symbol *sp,
869         char *pre, char *sep, char *ter)
870 {       int i;
871         char *ptr = sp?sp->name:"";
872
873         if (!sp)
874         {       fatal("cannot happen - do_var", 0);
875         }
876
877         switch(dowhat) {
878         case PUTV:
879                 if (sp->hidden&1) break;
880
881                 typ2c(sp);
882                 break;
883
884         case LOGV:
885                 if (!old_scope_rules)
886                 {       while (*ptr == '_' || isdigit((int)*ptr))
887                         {       ptr++;
888                 }       }
889                 /* fall thru */
890         case INIV:
891                 if (sp->type == STRUCT)
892                 {       /* struct may contain a chan */
893                         walk_struct(ofd, dowhat, s, sp, pre, sep, ter);
894                         break;
895                 }
896                 if (!sp->ini && dowhat != LOGV) /* it defaults to 0 */
897                         break;
898                 if (sp->nel == 1 && sp->isarray == 0)
899                 {       if (dowhat == LOGV)
900                         {       fprintf(ofd, "\t\t%s%s%s%s",
901                                         pre, s, ptr, sep);
902                                 fprintf(ofd, "%s%s", s, sp->name);
903                         } else
904                         {       fprintf(ofd, "\t\t%s%s%s%s",
905                                         pre, s, sp->name, sep);
906                                 do_init(ofd, sp);
907                         }
908                         fprintf(ofd, "%s", ter);
909                 } else
910                 {       if (sp->ini && sp->ini->ntyp == CHAN)
911                         {       for (i = 0; i < sp->nel; i++)
912                                 {       fprintf(ofd, "\t\t%s%s%s[%d]%s",
913                                                 pre, s, sp->name, i, sep);
914                                         if (dowhat == LOGV)
915                                                 fprintf(ofd, "%s%s[%d]",
916                                                         s, sp->name, i);
917                                         else
918                                                 do_init(ofd, sp);
919                                         fprintf(ofd, "%s", ter);
920                                 }
921                         } else if (sp->ini)
922                         {       if (dowhat != LOGV && sp->isarray && sp->ini->ntyp == ',')
923                                 {       Lextok *z, *y;
924                                         z = sp->ini;
925                                         for (i = 0; i < sp->nel; i++)
926                                         {       if (z && z->ntyp == ',')
927                                                 {       y = z->lft;
928                                                         z = z->rgt;
929                                                 } else
930                                                 {       y = z;
931                                                 }
932                                                 fprintf(ofd, "\t\t%s%s%s[%d]%s",
933                                                         pre, s, sp->name, i, sep);
934                                                 putstmnt(ofd, y, 0);
935                                                 fprintf(ofd, "%s", ter);
936                                         }
937                                 } else
938                                 {       fprintf(ofd, "\t{\tint l_in;\n");
939                                         fprintf(ofd, "\t\tfor (l_in = 0; l_in < %d; l_in++)\n",
940                                                 sp->nel);
941                                         fprintf(ofd, "\t\t{\n");
942                                         fprintf(ofd, "\t\t\t%s%s%s[l_in]%s",
943                                                 pre, s, sp->name, sep);
944                                         if (dowhat == LOGV)
945                                         {       fprintf(ofd, "%s%s[l_in]", s, sp->name);
946                                         } else
947                                         {       putstmnt(ofd, sp->ini, 0);
948                                         }
949                                         fprintf(ofd, "%s", ter);
950                                         fprintf(ofd, "\t\t}\n");
951                                         fprintf(ofd, "\t}\n");
952                 }       }       }
953                 break;
954         }
955 }
956
957 static void
958 do_init(FILE *ofd, Symbol *sp)
959 {       int i; 
960
961         if (sp->ini
962         &&  sp->type == CHAN
963         && ((i = qmake(sp)) > 0))
964         {       if (sp->ini->ntyp == CHAN)
965                 {       fprintf(ofd, "addqueue(calling_pid, %d, %d)",
966                                 i, ltab[i-1]->nslots == 0);
967                 } else
968                 {       fprintf(ofd, "%d", i);
969                 }
970         } else
971         {       putstmnt(ofd, sp->ini, 0);
972         }
973 }
974
975 static void
976 put_ptype(char *s, int i, int m0, int m1, enum btypes b)
977 {       int k;
978
979         if (b == I_PROC)
980         {       fprintf(th, "#define Pinit      ((P%d *)this)\n", i);
981         } else if (b == P_PROC || b == A_PROC)
982         {       fprintf(th, "#define P%s        ((P%d *)this)\n", s, i);
983         }
984
985         fprintf(th, "typedef struct P%d { /* %s */\n", i, s);
986         fprintf(th, "   unsigned _pid : 8;  /* 0..255 */\n");
987         fprintf(th, "   unsigned _t   : %d; /* proctype */\n", blog(m1));
988         fprintf(th, "   unsigned _p   : %d; /* state    */\n", blog(m0));
989         fprintf(th, "#ifdef HAS_PRIORITY\n");
990         fprintf(th, "   unsigned _priority : 8; /* 0..255 */\n");
991         fprintf(th, "#endif\n");
992         LstSet = ZS;
993         nBits = 8 + blog(m1) + blog(m0);
994         k = dolocal(tc, "", PUTV, i, s, b);     /* includes pars */
995         c_add_loc(th, s);
996
997         fprintf(th, "} P%d;\n", i);
998         if ((!LstSet && k > 0) || has_state)
999                 fprintf(th, "#define Air%d      0\n\n", i);
1000         else if (LstSet || k == 0)                      /* 5.0, added condition */
1001         {       fprintf(th, "#define Air%d      (sizeof(P%d) - ", i, i);
1002                 if (k == 0)
1003                 {       fprintf(th, "%d", (nBits+7)/8);
1004                         goto done;
1005                 }
1006                 if ((LstSet->type != BIT && LstSet->type != UNSIGNED)
1007                 ||   LstSet->nel != 1)
1008                 {       fprintf(th, "Offsetof(P%d, %s) - %d*sizeof(",
1009                                 i, LstSet->name, LstSet->nel);
1010                 }
1011                 switch(LstSet->type) {
1012                 case UNSIGNED:
1013                         fprintf(th, "%d", (nBits+7)/8);
1014                         break;
1015                 case BIT:
1016                         if (LstSet->nel == 1)
1017                         {       fprintf(th, "%d", (nBits+7)/8);
1018                                 break;
1019                         }       /* else fall through */
1020                 case MTYPE: case BYTE: case CHAN:
1021                         fprintf(th, "uchar)"); break;
1022                 case SHORT:
1023                         fprintf(th, "short)"); break;
1024                 case INT:
1025                         fprintf(th, "int)"); break;
1026                 default:
1027                         fatal("cannot happen Air %s",
1028                                 LstSet->name);
1029                 }
1030 done:           fprintf(th, ")\n\n");
1031         }
1032 }
1033
1034 static void
1035 tc_predef_np(void)
1036 {
1037         fprintf(th, "#define _NP_       %d\n", nrRdy);  /* 1+ highest proctype nr */
1038
1039         fprintf(th, "#define _nstates%d 3 /* np_ */\n", nrRdy);
1040         fprintf(th, "#define _endstate%d        2 /* np_ */\n\n", nrRdy);
1041         fprintf(th, "#define _start%d   0 /* np_ */\n", nrRdy);
1042
1043         fprintf(tc, "\tcase %d: /* np_ */\n", nrRdy);
1044         if (separate == 1)
1045         {       fprintf(tc, "\t\tini_claim(%d, h);\n", nrRdy);
1046         } else
1047         {       fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", nrRdy, nrRdy);
1048                 fprintf(tc, "\t\t((P%d *)pptr(h))->_p = 0;\n", nrRdy);
1049
1050                 fprintf(tc, "#ifdef HAS_PRIORITY\n");
1051                 fprintf(tc, "\t\t((P%d *)pptr(h))->_priority = priority;\n", nrRdy);
1052                 fprintf(tc, "#endif\n");
1053
1054                 fprintf(tc, "\t\treached%d[0] = 1;\n", nrRdy);
1055                 fprintf(tc, "\t\taccpstate[%d][1] = 1;\n", nrRdy);
1056         }
1057         fprintf(tc, "\t\tbreak;\n");
1058 }
1059
1060 static void
1061 multi_init(void)
1062 {       ProcList *p;
1063         Element *e;
1064         int i = nrRdy+1;
1065         int ini, j;
1066         int nrc = nclaims;
1067
1068         fprintf(tc, "#ifndef NOCLAIM\n");
1069         fprintf(tc, "\tcase %d: /* claim select */\n", i);
1070         for (p = rdy, j = 0; p; p = p->nxt, j++)
1071         {       if (p->b == N_CLAIM)
1072                 {       e = p->s->frst;
1073                         ini = huntele(e, e->status, -1)->seqno;
1074
1075                         fprintf(tc, "\t\tspin_c_typ[%d] = %d; /* %s */\n",
1076                                 j, p->tn, p->n->name);
1077                         fprintf(tc, "\t\t((P%d *)pptr(h))->c_cur[%d] = %d;\n",
1078                                 i, j, ini);
1079                         fprintf(tc, "\t\treached%d[%d]=1;\n", p->tn, ini);
1080
1081                         /* the default initial claim is first one in model */
1082                         if (--nrc == 0) 
1083                         { fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, p->tn);
1084                           fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini);
1085                           fprintf(tc, "\t\t((P%d *)pptr(h))->_n = %d; /* %s */\n",
1086                                 i, j, p->n->name);
1087                           fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", p->tn);
1088                           fprintf(tc, "#ifndef BFS\n");
1089                           fprintf(tc, "\t\tif (whichclaim == -1 && claimname == NULL)\n");
1090                           fprintf(tc, "\t\t\tprintf(\"0: Claim %s (%d), from state %d\\n\");\n",
1091                                 p->n->name, p->tn, ini);
1092                           fprintf(tc, "#endif\n");
1093                         }
1094         }       }
1095         fprintf(tc, "\t\tif (whichclaim != -1)\n");
1096         fprintf(tc, "\t\t{      select_claim(whichclaim);\n");
1097         fprintf(tc, "\t\t}\n");
1098         fprintf(tc, "\t\tbreak;\n\n");
1099         fprintf(tc, "#endif\n");
1100 }
1101
1102 static void
1103 put_pinit(ProcList *P)
1104 {       Lextok  *fp, *fpt, *t;
1105         Element *e = P->s->frst;
1106         Symbol  *s = P->n;
1107         Lextok  *p = P->p;
1108         int      i = P->tn;
1109         int     ini, j, k;
1110
1111         if (pid_is_claim(i)
1112         &&  separate == 1)
1113         {       fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
1114                 fprintf(tc, "\t\tini_claim(%d, h);\n", i);
1115                 fprintf(tc, "\t\tbreak;\n");
1116                 return;
1117         }
1118         if (!pid_is_claim(i)
1119         &&  separate == 2)
1120                 return;
1121
1122         ini = huntele(e, e->status, -1)->seqno;
1123         fprintf(th, "#define _start%d   %d\n", i, ini);
1124         if (i == eventmapnr)
1125         fprintf(th, "#define start_event        %d\n", ini);
1126
1127         fprintf(tc, "\tcase %d: /* %s */\n", i, s->name);
1128
1129         fprintf(tc, "\t\t((P%d *)pptr(h))->_t = %d;\n", i, i);
1130         fprintf(tc, "\t\t((P%d *)pptr(h))->_p = %d;\n", i, ini);
1131         fprintf(tc, "#ifdef HAS_PRIORITY\n");
1132
1133         fprintf(tc, "\t\t((P%d *)pptr(h))->_priority = priority; /* was: %d */\n",
1134                 i, (P->priority<1)? 1 : P->priority);
1135
1136         fprintf(tc, "#endif\n");
1137         fprintf(tc, "\t\treached%d[%d]=1;\n", i, ini);
1138         if (P->b == N_CLAIM)
1139         {       fprintf(tc, "\t\tsrc_claim = src_ln%d;\n", i);
1140         }
1141
1142         if (has_provided)
1143         {       fprintf(tt, "\tcase %d: /* %s */\n\t\t", i, s->name);
1144                 if (P->prov)
1145                 {       fprintf(tt, "if (");
1146                         putstmnt(tt, P->prov, 0);
1147                         fprintf(tt, ")\n\t\t\t");
1148                 }
1149                 fprintf(tt, "return 1;\n");
1150                 if (P->prov)
1151                         fprintf(tt, "\t\tbreak;\n");
1152         }
1153
1154         fprintf(tc, "\t\t/* params: */\n");
1155         for (fp  = p, j=0; fp; fp = fp->rgt)
1156         for (fpt = fp->lft; fpt; fpt = fpt->rgt, j++)
1157         {       t = (fpt->ntyp == ',') ? fpt->lft : fpt;
1158                 if (t->sym->nel > 1 || t->sym->isarray)
1159                 {       lineno = t->ln;
1160                         Fname  = t->fn;
1161                         fatal("array in parameter list, %s",
1162                         t->sym->name);
1163                 }
1164                 fprintf(tc, "\t\t((P%d *)pptr(h))->", i);
1165                 if (t->sym->type == STRUCT)
1166                 {       if (full_name(tc, t, t->sym, 1))
1167                         {       lineno = t->ln;
1168                                 Fname  = t->fn;
1169                                 fatal("hidden array in parameter %s",
1170                                 t->sym->name);
1171                         }
1172                 } else
1173                         fprintf(tc, "%s", t->sym->name);
1174                 fprintf(tc, " = par%d;\n", j);
1175         }
1176         fprintf(tc, "\t\t/* locals: */\n");
1177         k = dolocal(tc, "", INIV, i, s->name, P->b);
1178         if (k > 0)
1179         {       fprintf(tc, "#ifdef VAR_RANGES\n");
1180                 (void) dolocal(tc, "logval(\"", LOGV, i, s->name, P->b);
1181                 fprintf(tc, "#endif\n");
1182         }
1183
1184         fprintf(tc, "#ifdef HAS_CODE\n");
1185         fprintf(tc, "\t\tlocinit%d(h);\n", i);
1186         fprintf(tc, "#endif\n");
1187
1188         dumpclaims(tc, i, s->name);
1189         fprintf(tc, "\t break;\n");
1190 }
1191
1192 Element *
1193 huntstart(Element *f)
1194 {       Element *e = f;
1195         Element *elast = (Element *) 0;
1196         int cnt = 0;
1197
1198         while (elast != e && cnt++ < 200)       /* new 4.0.8 */
1199         {       elast = e;
1200                 if (e->n)
1201                 {       if (e->n->ntyp == '.' && e->nxt)
1202                                 e = e->nxt;
1203                         else if (e->n->ntyp == UNLESS)
1204                                 e = e->sub->this->frst;
1205         }       }
1206
1207         if (cnt >= 200 || !e)
1208         {       lineno = (f && f->n)?f->n->ln:lineno;
1209                 fatal("confusing control. structure", (char *) 0);
1210         }
1211         return e;
1212 }
1213
1214 Element *
1215 huntele(Element *f, unsigned int o, int stopat)
1216 {       Element *g, *e = f;
1217         int cnt=0; /* a precaution against loops */
1218
1219         if (e)
1220         for ( ; cnt < 500 && e->n; cnt++)
1221         {
1222                 if (e->seqno == stopat)
1223                         break;
1224
1225                 switch (e->n->ntyp) {
1226                 case GOTO:
1227                         g = get_lab(e->n,1);
1228                         if (e == g)
1229                         {       lineno = (f && f->n)?f->n->ln:lineno;
1230                                 fatal("infinite goto loop", (char *) 0);
1231                         }
1232                         cross_dsteps(e->n, g->n);
1233                         break;
1234                 case '.':
1235                 case BREAK:
1236                         if (!e->nxt)
1237                                 return e;
1238                         g = e->nxt;
1239                         break;
1240                 case UNLESS:
1241                         g = huntele(e->sub->this->frst, o, stopat);
1242                         if (!g)
1243                         {       fatal("unexpected error 1", (char *) 0);
1244                         }
1245                         break;
1246                 case D_STEP:
1247                 case ATOMIC:
1248                 case NON_ATOMIC:
1249                 default:
1250                         return e;
1251                 }
1252                 if ((o & ATOM) && !(g->status & ATOM))
1253                         return e;
1254                 e = g;
1255         }
1256         if (cnt >= 500 || !e)
1257         {       lineno = (f && f->n)?f->n->ln:lineno;
1258                 fatal("confusing control structure", (char *) 0);
1259         }
1260         return e;
1261 }
1262
1263 void
1264 typ2c(Symbol *sp)
1265 {       int wsbits = sizeof(long)*8; /* wordsize in bits */
1266         switch (sp->type) {
1267         case UNSIGNED:
1268                 if (sp->hidden&1)
1269                         fprintf(th, "\tuchar %s;", sp->name);
1270                 else
1271                         fprintf(th, "\tunsigned %s : %d",
1272                                 sp->name, sp->nbits);
1273                 LstSet = sp;
1274                 if (nBits%wsbits > 0
1275                 &&  wsbits - nBits%wsbits < sp->nbits)
1276                 {       /* must padd to a word-boundary */
1277                         nBits += wsbits - nBits%wsbits;
1278                 }
1279                 nBits += sp->nbits;
1280                 break;
1281         case BIT:
1282                 if (sp->nel == 1 && sp->isarray == 0 && !(sp->hidden&1))
1283                 {       fprintf(th, "\tunsigned %s : 1", sp->name);
1284                         LstSet = sp; 
1285                         nBits++;
1286                         break;
1287                 } /* else fall through */
1288                 if (!(sp->hidden&1) && (verbose&32))
1289                 printf("spin: warning: bit-array %s[%d] mapped to byte-array\n",
1290                         sp->name, sp->nel);
1291                 nBits += 8*sp->nel; /* mapped onto array of uchars */
1292         case MTYPE:
1293         case BYTE:
1294         case CHAN:      /* good for up to 255 channels */
1295                 fprintf(th, "\tuchar %s", sp->name);
1296                 LstSet = sp;
1297                 break;
1298         case SHORT:
1299                 fprintf(th, "\tshort %s", sp->name);
1300                 LstSet = sp;
1301                 break;
1302         case INT:
1303                 fprintf(th, "\tint %s", sp->name);
1304                 LstSet = sp;
1305                 break;
1306         case STRUCT:
1307                 if (!sp->Snm)
1308                         fatal("undeclared structure element %s", sp->name);
1309                 fprintf(th, "\tstruct %s %s",
1310                         sp->Snm->name,
1311                         sp->name);
1312                 LstSet = ZS;
1313                 break;
1314         case CODE_FRAG:
1315         case PREDEF:
1316                 return;
1317         default:
1318                 fatal("variable %s undeclared", sp->name);
1319         }
1320
1321         if (sp->nel > 1 || sp->isarray)
1322                 fprintf(th, "[%d]", sp->nel);
1323         fprintf(th, ";\n");
1324 }
1325
1326 static void
1327 ncases(FILE *fd, int p, int n, int m, const char *c[])
1328 {       int i, j;
1329
1330         for (j = 0; c[j]; j++)
1331         for (i = n; i < m; i++)
1332         {       fprintf(fd, c[j], i, p, i);
1333                 fprintf(fd, "\n");
1334         }
1335 }
1336
1337 void
1338 qlen_type(int qmax)
1339 {
1340         fprintf(th, "\t");
1341         if (qmax < 256)
1342                 fprintf(th, "uchar");
1343         else if (qmax < 65535)
1344                 fprintf(th, "ushort");
1345         else
1346                 fprintf(th, "uint");
1347         fprintf(th, " Qlen;     /* q_size */\n");
1348 }
1349
1350 void
1351 genaddqueue(void)
1352 {       char buf0[256];
1353         int j, qmax = 0;
1354         Queue *q;
1355
1356         ntimes(tc, 0, 1, Addq0);
1357
1358         if (has_io && !nqs)
1359                 fprintf(th, "#define NQS        1 /* nqs=%d, but has_io */\n", nqs);
1360         else
1361                 fprintf(th, "#define NQS        %d\n", nqs);
1362
1363         for (q = qtab; q; q = q->nxt)
1364                 if (q->nslots > qmax)
1365                         qmax = q->nslots;
1366
1367         for (q = qtab; q; q = q->nxt)
1368         {       j = q->qid;
1369                 fprintf(tc, "\tcase %d: j = sizeof(Q%d);", j, j);
1370                 fprintf(tc, " q_flds[%d] = %d;", j, q->nflds);
1371                 fprintf(tc, " q_max[%d] = %d;", j, max(1,q->nslots));
1372                 fprintf(tc, " break;\n");
1373
1374                 fprintf(th, "typedef struct Q%d {\n", j);
1375                 qlen_type(qmax);        /* 4.2.2 */
1376                 fprintf(th, "   uchar _t;       /* q_type */\n");
1377                 fprintf(th, "   struct {\n");
1378
1379                 for (j = 0; j < q->nflds; j++)
1380                 {       switch (q->fld_width[j]) {
1381                         case BIT:
1382                                 if (q->nflds != 1)
1383                                 {       fprintf(th, "\t\tunsigned");
1384                                         fprintf(th, " fld%d : 1;\n", j);
1385                                         break;
1386                                 } /* else fall through: smaller struct */
1387                         case MTYPE:
1388                         case CHAN:
1389                         case BYTE:
1390                                 fprintf(th, "\t\tuchar fld%d;\n", j);
1391                                 break;
1392                         case SHORT:
1393                                 fprintf(th, "\t\tshort fld%d;\n", j);
1394                                 break;
1395                         case INT:
1396                                 fprintf(th, "\t\tint fld%d;\n", j);
1397                                 break;
1398                         default:
1399                                 fatal("bad channel spec", "");
1400                         }
1401                 }
1402                 fprintf(th, "   } contents[%d];\n", max(1, q->nslots));
1403                 fprintf(th, "} Q%d;\n", q->qid);
1404         }
1405
1406         fprintf(th, "typedef struct Q0 {\t/* generic q */\n");
1407         qlen_type(qmax);        /* 4.2.2 */
1408         fprintf(th, "   uchar _t;\n");
1409         fprintf(th, "} Q0;\n");
1410
1411         ntimes(tc, 0, 1, Addq1);
1412
1413         fprintf(tc, "#ifdef TRIX\n");
1414         fprintf(tc, "int\nwhat_p_size(int t)\n{\tint j;\n");
1415         fprintf(tc, "   switch (t) {\n");
1416         ntimes(tc, 0, nrRdy+1, R5); /* +1 for np_ */
1417         fprintf(tc, "   default: Uerror(\"bad proctype\");\n");
1418         fprintf(tc, "   }\n     return j;\n}\n\n");
1419
1420         fprintf(tc, "int\nwhat_q_size(int t)\n{\tint j;\n");
1421         fprintf(tc, "   switch (t) {\n");
1422         for (j = 0; j < nqs+1; j++)
1423         {       fprintf(tc, "   case %d: j = sizeof(Q%d); break;\n", j, j);
1424         }
1425         fprintf(tc, "   default: Uerror(\"bad qtype\");\n");
1426         fprintf(tc, "   }\n     return j;\n}\n");
1427         fprintf(tc, "#endif\n\n");
1428
1429         if (has_random)
1430         {       fprintf(th, "int Q_has(int");
1431                 for (j = 0; j < Mpars; j++)
1432                         fprintf(th, ", int, int");
1433                 fprintf(th, ");\n");
1434
1435                 fprintf(tc, "int\nQ_has(int into");
1436                 for (j = 0; j < Mpars; j++)
1437                         fprintf(tc, ", int want%d, int fld%d", j, j);
1438                 fprintf(tc, ")\n");
1439                 fprintf(tc, "{  int i;\n\n");
1440                 fprintf(tc, "   if (!into--)\n");
1441                 fprintf(tc, "   uerror(\"ref to unknown chan ");
1442                 fprintf(tc, "(recv-poll)\");\n\n");
1443                 fprintf(tc, "   if (into >= now._nr_qs || into < 0)\n");
1444                 fprintf(tc, "           Uerror(\"qrecv bad queue#\");\n\n");
1445                 fprintf(tc, "   for (i = 0; i < ((Q0 *)qptr(into))->Qlen;");
1446                 fprintf(tc, " i++)\n");
1447                 fprintf(tc, "   {\n");
1448                 for (j = 0; j < Mpars; j++)
1449                 {       fprintf(tc, "           if (want%d && ", j);
1450                         fprintf(tc, "qrecv(into+1, i, %d, 0) != fld%d)\n",
1451                                 j, j);
1452                         fprintf(tc, "                   continue;\n");
1453                 }
1454                 fprintf(tc, "           return i+1;\n");
1455                 fprintf(tc, "   }\n");
1456                 fprintf(tc, "   return 0;\n");
1457                 fprintf(tc, "}\n");
1458         }
1459
1460         fprintf(tc, "#if NQS>0\n");
1461         fprintf(tc, "void\nqsend(int into, int sorted");
1462         for (j = 0; j < Mpars; j++)
1463                 fprintf(tc, ", int fld%d", j);
1464         fprintf(tc, ", int args_given)\n");
1465         ntimes(tc, 0, 1, Addq11);
1466
1467         for (q = qtab; q; q = q->nxt)
1468         {       sprintf(buf0, "((Q%d *)z)->", q->qid);
1469                 fprintf(tc, "\tcase %d:%s\n", q->qid,
1470                         (q->nslots)?"":" /* =rv= */");
1471                 if (q->nslots == 0)     /* reset handshake point */
1472                         fprintf(tc, "\t\t(trpt+2)->o_m = 0;\n");
1473
1474                 if (has_sorted)
1475                 {       fprintf(tc, "\t\tif (!sorted) goto append%d;\n", q->qid);
1476                         fprintf(tc, "\t\tfor (j = 0; j < %sQlen; j++)\n", buf0);
1477                         fprintf(tc, "\t\t{\t/* find insertion point */\n");
1478                         sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
1479                         for (j = 0; j < q->nflds; j++)
1480                         {       fprintf(tc, "\t\t\tif (fld%d > %s%d) continue;\n",
1481                                                 j, buf0, j);
1482                                 fprintf(tc, "\t\t\tif (fld%d < %s%d) ", j, buf0, j);
1483                                 fprintf(tc, "goto found%d;\n\n", q->qid);
1484                         }
1485                         fprintf(tc, "\t\t}\n");
1486                         fprintf(tc, "\tfound%d:\n", q->qid);
1487                         sprintf(buf0, "((Q%d *)z)->", q->qid);
1488                         fprintf(tc, "\t\tfor (k = %sQlen - 1; k >= j; k--)\n", buf0);
1489                         fprintf(tc, "\t\t{\t/* shift up */\n");
1490                         for (j = 0; j < q->nflds; j++)
1491                         {       fprintf(tc, "\t\t\t%scontents[k+1].fld%d = ",
1492                                         buf0, j);
1493                                 fprintf(tc, "%scontents[k].fld%d;\n",
1494                                         buf0, j);
1495                         }
1496                         fprintf(tc, "\t\t}\n");
1497                         fprintf(tc, "\tappend%d:\t/* insert in slot j */\n", q->qid);
1498                 }
1499
1500                 fprintf(tc, "#ifdef HAS_SORTED\n");
1501                 fprintf(tc, "\t\t(trpt+1)->ipt = j;\n");        /* ipt was bup.oval */
1502                 fprintf(tc, "#endif\n");
1503                 fprintf(tc, "\t\t%sQlen = %sQlen + 1;\n", buf0, buf0);
1504                 sprintf(buf0, "((Q%d *)z)->contents[j].fld", q->qid);
1505                 for (j = 0; j < q->nflds; j++)
1506                         fprintf(tc, "\t\t%s%d = fld%d;\n", buf0, j, j);
1507                 fprintf(tc, "\t\tif (args_given != %d)\n", q->nflds);
1508                 fprintf(tc, "\t\t{      if (args_given > %d)\n", q->nflds);
1509                 fprintf(tc, "\t\t               uerror(\"too many parameters in send stmnt\");\n");
1510                 fprintf(tc, "\t\t       else\n");
1511                 fprintf(tc, "\t\t               uerror(\"too few parameters in send stmnt\");\n");
1512                 fprintf(tc, "\t\t}\n");
1513                 fprintf(tc, "\t\tbreak;\n");
1514         }
1515         ntimes(tc, 0, 1, Addq2);
1516
1517         for (q = qtab; q; q = q->nxt)
1518         fprintf(tc, "\tcase %d: return %d;\n", q->qid, (!q->nslots));
1519
1520         ntimes(tc, 0, 1, Addq3);
1521
1522         for (q = qtab; q; q = q->nxt)
1523         fprintf(tc, "\tcase %d: return (q_sz(from) == %d);\n",
1524                         q->qid, max(1, q->nslots));
1525
1526         ntimes(tc, 0, 1, Addq4);
1527         for (q = qtab; q; q = q->nxt)
1528         {       sprintf(buf0, "((Q%d *)z)->", q->qid);
1529                 fprintf(tc, "   case %d:%s\n\t\t",
1530                         q->qid, (q->nslots)?"":" /* =rv= */");
1531                 if (q->nflds == 1)
1532                 {       fprintf(tc, "if (fld == 0) r = %s", buf0);
1533                         fprintf(tc, "contents[slot].fld0;\n");
1534                 } else
1535                 {       fprintf(tc, "switch (fld) {\n");
1536                         ncases(tc, q->qid, 0, q->nflds, R12);
1537                         fprintf(tc, "\t\tdefault: Uerror");
1538                         fprintf(tc, "(\"too many fields in recv\");\n");
1539                         fprintf(tc, "\t\t}\n");
1540                 }
1541                 fprintf(tc, "\t\tif (done)\n");
1542                 if (q->nslots == 0)
1543                 {       fprintf(tc, "\t\t{      j = %sQlen - 1;\n",  buf0);
1544                         fprintf(tc, "\t\t       %sQlen = 0;\n", buf0);
1545                         sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
1546                 } else
1547                 {       fprintf(tc, "\t\t{      j = %sQlen;\n",  buf0);
1548                         fprintf(tc, "\t\t       %sQlen = --j;\n", buf0);
1549                         fprintf(tc, "\t\t       for (k=slot; k<j; k++)\n");
1550                         fprintf(tc, "\t\t       {\n");
1551                         sprintf(buf0, "\t\t\t((Q%d *)z)->contents", q->qid);
1552                         for (j = 0; j < q->nflds; j++)
1553                         {       fprintf(tc, "\t%s[k].fld%d = \n", buf0, j);
1554                                 fprintf(tc, "\t\t%s[k+1].fld%d;\n", buf0, j);
1555                         }
1556                         fprintf(tc, "\t\t       }\n");
1557                 }
1558
1559                 for (j = 0; j < q->nflds; j++)
1560                         fprintf(tc, "%s[j].fld%d = 0;\n", buf0, j);
1561                 fprintf(tc, "\t\t\tif (fld+1 != %d)\n\t\t\t", q->nflds);
1562                 fprintf(tc, "\tuerror(\"missing pars in receive\");\n");
1563                 /* incompletely received msgs cannot be unrecv'ed */
1564                 fprintf(tc, "\t\t}\n");
1565                 fprintf(tc, "\t\tbreak;\n");
1566         }
1567         ntimes(tc, 0, 1, Addq5);
1568         for (q = qtab; q; q = q->nxt)
1569         fprintf(tc, "   case %d: j = sizeof(Q%d); break;\n",
1570                 q->qid, q->qid);
1571         ntimes(tc, 0, 1, R8b);
1572         ntimes(th, 0, 1, Proto);        /* function prototypes */
1573
1574         fprintf(th, "void qsend(int, int");
1575         for (j = 0; j < Mpars; j++)
1576                 fprintf(th, ", int");
1577         fprintf(th, ", int);\n\n");
1578
1579         fprintf(th, "#define Addproc(x,y)       addproc(256, y, x");
1580         /* 256 is param outside the range of valid pids */
1581         for (j = 0; j < Npars; j++)
1582                 fprintf(th, ", 0");
1583         fprintf(th, ")\n");
1584 }