123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- /***** spin: pangen4.c *****/
- /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
- /* All Rights Reserved. This software is for educational purposes only. */
- /* No guarantee whatsoever is expressed or implied by the distribution of */
- /* this code. Permission is given to distribute this code provided that */
- /* this introductory message is not removed and no monies are exchanged. */
- /* Software written by Gerard J. Holzmann. For tool documentation see: */
- /* http://spinroot.com/ */
- /* Send all bug-reports and/or questions to: bugs@spinroot.com */
- #include "spin.h"
- #include "y.tab.h"
- extern FILE *tc, *tb;
- extern Queue *qtab;
- extern Symbol *Fname;
- extern int lineno, m_loss, Pid, eventmapnr, multi_oval;
- extern short nocast, has_provided, has_sorted;
- extern char *R13[], *R14[], *R15[];
- static void check_proc(Lextok *, int);
- void
- undostmnt(Lextok *now, int m)
- { Lextok *v;
- int i, j;
- if (!now)
- { fprintf(tb, "0");
- return;
- }
- lineno = now->ln;
- Fname = now->fn;
- switch (now->ntyp) {
- case CONST: case '!': case UMIN:
- case '~': case '/': case '*':
- case '-': case '+': case '%':
- case LT: case GT: case '&':
- case '|': case LE: case GE:
- case NE: case EQ: case OR:
- case AND: case LSHIFT: case RSHIFT:
- case TIMEOUT: case LEN: case NAME:
- case FULL: case EMPTY: case 'R':
- case NFULL: case NEMPTY: case ENABLED:
- case '?': case PC_VAL: case '^':
- case C_EXPR:
- case NONPROGRESS:
- putstmnt(tb, now, m);
- break;
- case RUN:
- fprintf(tb, "delproc(0, now._nr_pr-1)");
- break;
- case 's':
- if (Pid == eventmapnr) break;
- if (m_loss)
- fprintf(tb, "if (_m == 2) ");
- putname(tb, "_m = unsend(", now->lft, m, ")");
- break;
- case 'r':
- if (Pid == eventmapnr) break;
- for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
- if (v->lft->ntyp != CONST
- && v->lft->ntyp != EVAL)
- j++;
- if (j == 0 && now->val >= 2)
- break; /* poll without side-effect */
- { int ii = 0, jj;
- for (v = now->rgt; v; v = v->rgt)
- if ((v->lft->ntyp != CONST
- && v->lft->ntyp != EVAL))
- ii++; /* nr of things bupped */
- if (now->val == 1)
- { ii++;
- jj = multi_oval - ii - 1;
- fprintf(tb, "XX = trpt->bup.oval");
- if (multi_oval > 0)
- { fprintf(tb, "s[%d]", jj);
- jj++;
- }
- fprintf(tb, ";\n\t\t");
- } else
- { fprintf(tb, "XX = 1;\n\t\t");
- jj = multi_oval - ii - 1;
- }
- if (now->val < 2) /* not for channel poll */
- for (v = now->rgt, i = 0; v; v = v->rgt, i++)
- { switch(v->lft->ntyp) {
- case CONST:
- case EVAL:
- fprintf(tb, "unrecv");
- putname(tb, "(", now->lft, m, ", XX-1, ");
- fprintf(tb, "%d, ", i);
- if (v->lft->ntyp == EVAL)
- undostmnt(v->lft->lft, m);
- else
- undostmnt(v->lft, m);
- fprintf(tb, ", %d);\n\t\t", (i==0)?1:0);
- break;
- default:
- fprintf(tb, "unrecv");
- putname(tb, "(", now->lft, m, ", XX-1, ");
- fprintf(tb, "%d, ", i);
- if (v->lft->sym
- && !strcmp(v->lft->sym->name, "_"))
- { fprintf(tb, "trpt->bup.oval");
- if (multi_oval > 0)
- fprintf(tb, "s[%d]", jj);
- } else
- putstmnt(tb, v->lft, m);
- fprintf(tb, ", %d);\n\t\t", (i==0)?1:0);
- if (multi_oval > 0)
- jj++;
- break;
- } }
- jj = multi_oval - ii - 1;
- if (now->val == 1 && multi_oval > 0)
- jj++; /* new 3.4.0 */
- for (v = now->rgt, i = 0; v; v = v->rgt, i++)
- { switch(v->lft->ntyp) {
- case CONST:
- case EVAL:
- break;
- default:
- if (!v->lft->sym
- || strcmp(v->lft->sym->name, "_") != 0)
- { nocast=1; putstmnt(tb,v->lft,m);
- nocast=0; fprintf(tb, " = trpt->bup.oval");
- if (multi_oval > 0)
- fprintf(tb, "s[%d]", jj);
- fprintf(tb, ";\n\t\t");
- }
- if (multi_oval > 0)
- jj++;
- break;
- } }
- multi_oval -= ii;
- }
- break;
- case '@':
- fprintf(tb, "p_restor(II);\n\t\t");
- break;
- case ASGN:
- nocast=1; putstmnt(tb,now->lft,m);
- nocast=0; fprintf(tb, " = trpt->bup.oval");
- if (multi_oval > 0)
- { multi_oval--;
- fprintf(tb, "s[%d]", multi_oval-1);
- }
- check_proc(now->rgt, m);
- break;
- case 'c':
- check_proc(now->lft, m);
- break;
- case '.':
- case GOTO:
- case ELSE:
- case BREAK:
- break;
- case C_CODE:
- fprintf(tb, "sv_restor();\n");
- break;
- case ASSERT:
- case PRINT:
- check_proc(now, m);
- break;
- case PRINTM:
- break;
- default:
- printf("spin: bad node type %d (.b)\n", now->ntyp);
- alldone(1);
- }
- }
- int
- any_undo(Lextok *now)
- { /* is there anything to undo on a return move? */
- if (!now) return 1;
- switch (now->ntyp) {
- case 'c': return any_oper(now->lft, RUN);
- case ASSERT:
- case PRINT: return any_oper(now, RUN);
- case PRINTM:
- case '.':
- case GOTO:
- case ELSE:
- case BREAK: return 0;
- default: return 1;
- }
- }
- int
- any_oper(Lextok *now, int oper)
- { /* check if an expression contains oper operator */
- if (!now) return 0;
- if (now->ntyp == oper)
- return 1;
- return (any_oper(now->lft, oper) || any_oper(now->rgt, oper));
- }
- static void
- check_proc(Lextok *now, int m)
- {
- if (!now)
- return;
- if (now->ntyp == '@' || now->ntyp == RUN)
- { fprintf(tb, ";\n\t\t");
- undostmnt(now, m);
- }
- check_proc(now->lft, m);
- check_proc(now->rgt, m);
- }
- void
- genunio(void)
- { char buf1[256];
- Queue *q; int i;
- ntimes(tc, 0, 1, R13);
- for (q = qtab; q; q = q->nxt)
- { fprintf(tc, "\tcase %d:\n", q->qid);
- if (has_sorted)
- { sprintf(buf1, "((Q%d *)z)->contents", q->qid);
- fprintf(tc, "#ifdef HAS_SORTED\n");
- fprintf(tc, "\t\tj = trpt->ipt;\n"); /* ipt was bup.oval */
- fprintf(tc, "#endif\n");
- fprintf(tc, "\t\tfor (k = j; k < ((Q%d *)z)->Qlen; k++)\n",
- q->qid);
- fprintf(tc, "\t\t{\n");
- for (i = 0; i < q->nflds; i++)
- fprintf(tc, "\t\t\t%s[k].fld%d = %s[k+1].fld%d;\n",
- buf1, i, buf1, i);
- fprintf(tc, "\t\t}\n");
- fprintf(tc, "\t\tj = ((Q0 *)z)->Qlen;\n");
- }
- sprintf(buf1, "((Q%d *)z)->contents[j].fld", q->qid);
- for (i = 0; i < q->nflds; i++)
- fprintf(tc, "\t\t%s%d = 0;\n", buf1, i);
- if (q->nslots==0)
- { /* check if rendezvous succeeded, 1 level down */
- fprintf(tc, "\t\t_m = (trpt+1)->o_m;\n");
- fprintf(tc, "\t\tif (_m) (trpt-1)->o_pm |= 1;\n");
- fprintf(tc, "\t\tUnBlock;\n");
- } else
- fprintf(tc, "\t\t_m = trpt->o_m;\n");
- fprintf(tc, "\t\tbreak;\n");
- }
- ntimes(tc, 0, 1, R14);
- for (q = qtab; q; q = q->nxt)
- { sprintf(buf1, "((Q%d *)z)->contents", q->qid);
- fprintf(tc, " case %d:\n", q->qid);
- if (q->nslots == 0)
- fprintf(tc, "\t\tif (strt) boq = from+1;\n");
- else if (q->nslots > 1) /* shift */
- { fprintf(tc, "\t\tif (strt && slot<%d)\n",
- q->nslots-1);
- fprintf(tc, "\t\t{\tfor (j--; j>=slot; j--)\n");
- fprintf(tc, "\t\t\t{");
- for (i = 0; i < q->nflds; i++)
- { fprintf(tc, "\t%s[j+1].fld%d =\n\t\t\t",
- buf1, i);
- fprintf(tc, "\t%s[j].fld%d;\n\t\t\t",
- buf1, i);
- }
- fprintf(tc, "}\n\t\t}\n");
- }
- strcat(buf1, "[slot].fld");
- fprintf(tc, "\t\tif (strt) {\n");
- for (i = 0; i < q->nflds; i++)
- fprintf(tc, "\t\t\t%s%d = 0;\n", buf1, i);
- fprintf(tc, "\t\t}\n");
- if (q->nflds == 1) /* set */
- fprintf(tc, "\t\tif (fld == 0) %s0 = fldvar;\n",
- buf1);
- else
- { fprintf(tc, "\t\tswitch (fld) {\n");
- for (i = 0; i < q->nflds; i++)
- { fprintf(tc, "\t\tcase %d:\t%s", i, buf1);
- fprintf(tc, "%d = fldvar; break;\n", i);
- }
- fprintf(tc, "\t\t}\n");
- }
- fprintf(tc, "\t\tbreak;\n");
- }
- ntimes(tc, 0, 1, R15);
- }
- int
- proper_enabler(Lextok *n)
- {
- if (!n) return 1;
- switch (n->ntyp) {
- case NEMPTY: case FULL:
- case NFULL: case EMPTY:
- case LEN: case 'R':
- case NAME:
- has_provided = 1;
- if (strcmp(n->sym->name, "_pid") == 0)
- return 1;
- return (!(n->sym->context));
- case CONST: case TIMEOUT:
- has_provided = 1;
- return 1;
- case ENABLED: case PC_VAL:
- return proper_enabler(n->lft);
- case '!': case UMIN: case '~':
- return proper_enabler(n->lft);
- case '/': case '*': case '-': case '+':
- case '%': case LT: case GT: case '&': case '^':
- case '|': case LE: case GE: case NE: case '?':
- case EQ: case OR: case AND: case LSHIFT:
- case RSHIFT: case 'c':
- return proper_enabler(n->lft) && proper_enabler(n->rgt);
- default:
- break;
- }
- return 0;
- }
|