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