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