]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/spin/pangen4.c
kbdfs: simplfy
[plan9front.git] / sys / src / cmd / spin / pangen4.c
1 /***** spin: pangen4.c *****/
2
3 /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
4 /* All Rights Reserved.  This software is for educational purposes only.  */
5 /* No guarantee whatsoever is expressed or implied by the distribution of */
6 /* this code.  Permission is given to distribute this code provided that  */
7 /* this introductory message is not removed and no monies are exchanged.  */
8 /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9 /*             http://spinroot.com/                                       */
10 /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11
12 #include "spin.h"
13 #include "y.tab.h"
14
15 extern FILE     *tc, *tb;
16 extern Queue    *qtab;
17 extern Symbol   *Fname;
18 extern int      lineno, m_loss, Pid, eventmapnr, multi_oval;
19 extern short    nocast, has_provided, has_sorted;
20 extern char     *R13[], *R14[], *R15[];
21
22 static void     check_proc(Lextok *, int);
23
24 void
25 undostmnt(Lextok *now, int m)
26 {       Lextok *v;
27         int i, j;
28
29         if (!now)
30         {       fprintf(tb, "0");
31                 return;
32         }
33         lineno = now->ln;
34         Fname  = now->fn;
35         switch (now->ntyp) {
36         case CONST:     case '!':       case UMIN:
37         case '~':       case '/':       case '*':
38         case '-':       case '+':       case '%':
39         case LT:        case GT:        case '&':
40         case '|':       case LE:        case GE:
41         case NE:        case EQ:        case OR:
42         case AND:       case LSHIFT:    case RSHIFT:
43         case TIMEOUT:   case LEN:       case NAME:
44         case FULL:      case EMPTY:     case 'R':
45         case NFULL:     case NEMPTY:    case ENABLED:
46         case '?':       case PC_VAL:    case '^':
47         case C_EXPR:
48         case NONPROGRESS:
49                 putstmnt(tb, now, m);
50                 break;
51
52         case RUN:
53                 fprintf(tb, "delproc(0, now._nr_pr-1)");
54                 break;
55
56         case 's':
57                 if (Pid == eventmapnr) break;
58
59                 if (m_loss)
60                         fprintf(tb, "if (_m == 2) ");
61                 putname(tb, "_m = unsend(", now->lft, m, ")");
62                 break;
63
64         case 'r':
65                 if (Pid == eventmapnr) break;
66
67                 for (v = now->rgt, i=j=0; v; v = v->rgt, i++)
68                         if (v->lft->ntyp != CONST
69                         &&  v->lft->ntyp != EVAL)
70                                 j++;
71                 if (j == 0 && now->val >= 2)
72                         break;  /* poll without side-effect */
73
74                 {       int ii = 0, jj;
75
76                         for (v = now->rgt; v; v = v->rgt)
77                                 if ((v->lft->ntyp != CONST
78                                 &&   v->lft->ntyp != EVAL))
79                                         ii++;   /* nr of things bupped */
80                         if (now->val == 1)
81                         {       ii++;
82                                 jj = multi_oval - ii - 1;
83                                 fprintf(tb, "XX = trpt->bup.oval");
84                                 if (multi_oval > 0)
85                                 {       fprintf(tb, "s[%d]", jj);
86                                         jj++;
87                                 }
88                                 fprintf(tb, ";\n\t\t");
89                         } else
90                         {       fprintf(tb, "XX = 1;\n\t\t");
91                                 jj = multi_oval - ii - 1;
92                         }
93
94                         if (now->val < 2)       /* not for channel poll */
95                         for (v = now->rgt, i = 0; v; v = v->rgt, i++)
96                         {       switch(v->lft->ntyp) {
97                                 case CONST:
98                                 case EVAL:
99                                         fprintf(tb, "unrecv");
100                                         putname(tb, "(", now->lft, m, ", XX-1, ");
101                                         fprintf(tb, "%d, ", i);
102                                         if (v->lft->ntyp == EVAL)
103                                                 undostmnt(v->lft->lft, m);
104                                         else
105                                                 undostmnt(v->lft, m);
106                                         fprintf(tb, ", %d);\n\t\t", (i==0)?1:0);
107                                         break;
108                                 default:
109                                         fprintf(tb, "unrecv");
110                                         putname(tb, "(", now->lft, m, ", XX-1, ");
111                                         fprintf(tb, "%d, ", i);
112                                         if (v->lft->sym
113                                         && !strcmp(v->lft->sym->name, "_"))
114                                         {       fprintf(tb, "trpt->bup.oval");
115                                                 if (multi_oval > 0)
116                                                         fprintf(tb, "s[%d]", jj);
117                                         } else
118                                                 putstmnt(tb, v->lft, m);
119
120                                         fprintf(tb, ", %d);\n\t\t", (i==0)?1:0);
121                                         if (multi_oval > 0)
122                                                 jj++;
123                                         break;
124                         }       }
125                         jj = multi_oval - ii - 1;
126
127                         if (now->val == 1 && multi_oval > 0)
128                                 jj++;   /* new 3.4.0 */
129
130                         for (v = now->rgt, i = 0; v; v = v->rgt, i++)
131                         {       switch(v->lft->ntyp) {
132                                 case CONST:
133                                 case EVAL:
134                                         break;
135                                 default:
136                                         if (!v->lft->sym
137                                         ||  strcmp(v->lft->sym->name, "_") != 0)
138                                         {       nocast=1; putstmnt(tb,v->lft,m);
139                                                 nocast=0; fprintf(tb, " = trpt->bup.oval");
140                                                 if (multi_oval > 0)
141                                                         fprintf(tb, "s[%d]", jj);
142                                                 fprintf(tb, ";\n\t\t");
143                                         }
144                                         if (multi_oval > 0)
145                                                 jj++;
146                                         break;
147                         }       }
148                         multi_oval -= ii;
149                 }
150                 break;
151
152         case '@':
153                 fprintf(tb, "p_restor(II);\n\t\t");
154                 break;
155
156         case ASGN:
157                 nocast=1; putstmnt(tb,now->lft,m);
158                 nocast=0; fprintf(tb, " = trpt->bup.oval");
159                 if (multi_oval > 0)
160                 {       multi_oval--;
161                         fprintf(tb, "s[%d]", multi_oval-1);
162                 }
163                 check_proc(now->rgt, m);
164                 break;
165
166         case 'c':
167                 check_proc(now->lft, m);
168                 break;
169
170         case '.':
171         case GOTO:
172         case ELSE:
173         case BREAK:
174                 break;
175
176         case C_CODE:
177                 fprintf(tb, "sv_restor();\n");
178                 break;
179
180         case ASSERT:
181         case PRINT:
182                 check_proc(now, m);
183                 break;
184         case PRINTM:
185                 break;
186
187         default:
188                 printf("spin: bad node type %d (.b)\n", now->ntyp);
189                 alldone(1);
190         }
191 }
192
193 int
194 any_undo(Lextok *now)
195 {       /* is there anything to undo on a return move? */
196         if (!now) return 1;
197         switch (now->ntyp) {
198         case 'c':       return any_oper(now->lft, RUN);
199         case ASSERT:
200         case PRINT:     return any_oper(now, RUN);
201
202         case PRINTM:
203         case   '.':
204         case  GOTO:
205         case  ELSE:
206         case BREAK:     return 0;
207         default:        return 1;
208         }
209 }
210
211 int
212 any_oper(Lextok *now, int oper)
213 {       /* check if an expression contains oper operator */
214         if (!now) return 0;
215         if (now->ntyp == oper)
216                 return 1;
217         return (any_oper(now->lft, oper) || any_oper(now->rgt, oper));
218 }
219
220 static void
221 check_proc(Lextok *now, int m)
222 {
223         if (!now)
224                 return;
225         if (now->ntyp == '@' || now->ntyp == RUN)
226         {       fprintf(tb, ";\n\t\t");
227                 undostmnt(now, m);
228         }
229         check_proc(now->lft, m);
230         check_proc(now->rgt, m);
231 }
232
233 void
234 genunio(void)
235 {       char buf1[256];
236         Queue *q; int i;
237
238         ntimes(tc, 0, 1, R13);
239         for (q = qtab; q; q = q->nxt)
240         {       fprintf(tc, "\tcase %d:\n", q->qid);
241
242                 if (has_sorted)
243                 {       sprintf(buf1, "((Q%d *)z)->contents", q->qid);
244                         fprintf(tc, "#ifdef HAS_SORTED\n");
245                         fprintf(tc, "\t\tj = trpt->ipt;\n");    /* ipt was bup.oval */
246                         fprintf(tc, "#endif\n");
247                         fprintf(tc, "\t\tfor (k = j; k < ((Q%d *)z)->Qlen; k++)\n",
248                                 q->qid);
249                         fprintf(tc, "\t\t{\n");
250                         for (i = 0; i < q->nflds; i++)
251                         fprintf(tc, "\t\t\t%s[k].fld%d = %s[k+1].fld%d;\n",
252                                 buf1, i, buf1, i);
253                         fprintf(tc, "\t\t}\n");
254                         fprintf(tc, "\t\tj = ((Q0 *)z)->Qlen;\n");
255                 }
256
257                 sprintf(buf1, "((Q%d *)z)->contents[j].fld", q->qid);
258                 for (i = 0; i < q->nflds; i++)
259                         fprintf(tc, "\t\t%s%d = 0;\n", buf1, i);
260                 if (q->nslots==0)
261                 {       /* check if rendezvous succeeded, 1 level down */
262                         fprintf(tc, "\t\t_m = (trpt+1)->o_m;\n");
263                         fprintf(tc, "\t\tif (_m) (trpt-1)->o_pm |= 1;\n");
264                         fprintf(tc, "\t\tUnBlock;\n");
265                 } else
266                         fprintf(tc, "\t\t_m = trpt->o_m;\n");
267
268                 fprintf(tc, "\t\tbreak;\n");
269         }
270         ntimes(tc, 0, 1, R14);
271         for (q = qtab; q; q = q->nxt)
272         {       sprintf(buf1, "((Q%d *)z)->contents", q->qid);
273                 fprintf(tc, "   case %d:\n", q->qid);
274                 if (q->nslots == 0)
275                         fprintf(tc, "\t\tif (strt) boq = from+1;\n");
276                 else if (q->nslots > 1) /* shift */
277                 {       fprintf(tc, "\t\tif (strt && slot<%d)\n",
278                                                         q->nslots-1);
279                         fprintf(tc, "\t\t{\tfor (j--; j>=slot; j--)\n");
280                         fprintf(tc, "\t\t\t{");
281                         for (i = 0; i < q->nflds; i++)
282                         {       fprintf(tc, "\t%s[j+1].fld%d =\n\t\t\t",
283                                                         buf1, i);
284                                 fprintf(tc, "\t%s[j].fld%d;\n\t\t\t",
285                                                         buf1, i);
286                         }
287                         fprintf(tc, "}\n\t\t}\n");
288                 }
289                 strcat(buf1, "[slot].fld");
290                 fprintf(tc, "\t\tif (strt) {\n");
291                 for (i = 0; i < q->nflds; i++)
292                         fprintf(tc, "\t\t\t%s%d = 0;\n", buf1, i);
293                 fprintf(tc, "\t\t}\n");
294                 if (q->nflds == 1)      /* set */
295                         fprintf(tc, "\t\tif (fld == 0) %s0 = fldvar;\n",
296                                                         buf1);
297                 else
298                 {       fprintf(tc, "\t\tswitch (fld) {\n");
299                         for (i = 0; i < q->nflds; i++)
300                         {       fprintf(tc, "\t\tcase %d:\t%s", i, buf1);
301                                 fprintf(tc, "%d = fldvar; break;\n", i);
302                         }
303                         fprintf(tc, "\t\t}\n");
304                 }
305                 fprintf(tc, "\t\tbreak;\n");
306         }
307         ntimes(tc, 0, 1, R15);
308 }
309
310 int
311 proper_enabler(Lextok *n)
312 {
313         if (!n) return 1;
314         switch (n->ntyp) {
315         case NEMPTY:    case FULL:
316         case NFULL:     case EMPTY:
317         case LEN:       case 'R':
318         case NAME:
319                 has_provided = 1;
320                 if (strcmp(n->sym->name, "_pid") == 0)
321                         return 1;
322                 return (!(n->sym->context));
323
324         case CONST:     case TIMEOUT:
325                 has_provided = 1;
326                 return 1;
327
328         case ENABLED:   case PC_VAL:
329                 return proper_enabler(n->lft);
330
331         case '!': case UMIN: case '~':
332                 return proper_enabler(n->lft);
333
334         case '/': case '*': case '-': case '+':
335         case '%': case LT:  case GT: case '&': case '^':
336         case '|': case LE:  case GE:  case NE: case '?':
337         case EQ:  case OR:  case AND: case LSHIFT:
338         case RSHIFT: case 'c':
339                 return proper_enabler(n->lft) && proper_enabler(n->rgt);
340         default:
341                 break;
342         }
343         return 0;
344 }