]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/spin/pangen3.c
cc: use 7 octal digits for 21 bit runes
[plan9front.git] / sys / src / cmd / spin / pangen3.c
1 /***** spin: pangen3.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 <assert.h>
12
13 extern FILE     *th, *tc;
14 extern int      eventmapnr, old_priority_rules;
15
16 typedef struct SRC {
17         int ln, st;     /* linenr, statenr */
18         Symbol *fn;     /* filename */
19         struct SRC *nxt;
20 } SRC;
21
22 static int      col;
23 static Symbol   *lastfnm;
24 static Symbol   lastdef;
25 static int      lastfrom;
26 static SRC      *frst = (SRC *) 0;
27 static SRC      *skip = (SRC *) 0;
28
29 extern int      ltl_mode;
30
31 extern void     sr_mesg(FILE *, int, int);
32
33 static void
34 putnr(int n)
35 {
36         if (col++ == 8)
37         {       fprintf(tc, "\n\t");    /* was th */
38                 col = 1;
39         }
40         fprintf(tc, "%3d, ", n);        /* was th */
41 }
42
43 static void
44 putfnm(int j, Symbol *s)
45 {
46         if (lastfnm && lastfnm == s && j != -1)
47                 return;
48
49         if (lastfnm)
50                 fprintf(tc, "{ \"%s\", %d, %d },\n\t",  /* was th */
51                         lastfnm->name,
52                         lastfrom,
53                         j-1);
54         lastfnm = s;
55         lastfrom = j;
56 }
57
58 static void
59 putfnm_flush(int j)
60 {
61         if (lastfnm)
62                 fprintf(tc, "{ \"%s\", %d, %d }\n",     /* was th */
63                         lastfnm->name,
64                         lastfrom, j);
65 }
66
67 static SRC *
68 newsrc(int m, SRC *n)
69 {       SRC *tmp;
70         tmp = (SRC *) emalloc(sizeof(SRC));
71         tmp->st  = m;
72         tmp->nxt = n;
73         return tmp;
74 }
75
76 void
77 putskip(int m)  /* states that need not be reached */
78 {       SRC *tmp, *lst = (SRC *)0;
79         /* 6.4.0: now an ordered list */
80         for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
81         {       if (tmp->st == m)
82                 {       return;
83                 }
84                 if (tmp->st > m)        /* insert before */
85                 {       if (tmp == skip)
86                         {       tmp = newsrc(m, skip);
87                                 skip = tmp;
88                         } else
89                         {       assert(lst);
90                                 tmp = newsrc(m, lst->nxt);
91                                 lst->nxt = tmp;
92                         }
93                         return; 
94         }       }
95         /* insert at the end */
96         if (lst)
97         {       lst->nxt = newsrc(m, 0);
98         } else  /* empty list */
99         {       skip = newsrc(m, 0);
100         }
101 }
102
103 void
104 unskip(int m)   /* a state that needs to be reached after all */
105 {       SRC *tmp, *lst = (SRC *)0;
106
107         for (tmp = skip; tmp; lst = tmp, tmp = tmp->nxt)
108         {       if (tmp->st == m)
109                 {       if (tmp == skip)
110                                 skip = skip->nxt;
111                         else if (lst)   /* always true, but helps coverity */
112                                 lst->nxt = tmp->nxt;
113                         break;
114                 }
115                 if (tmp->st > m)
116                 {       break;  /* m is not in list */
117         }       }
118 }
119
120 void
121 putsrc(Element *e)      /* match states to source lines */
122 {       SRC *tmp, *lst = (SRC *)0;
123         int n, m;
124
125         if (!e || !e->n) return;
126
127         n = e->n->ln;
128         m = e->seqno;
129         /* 6.4.0: now an ordered list */
130         for (tmp = frst; tmp; lst = tmp, tmp = tmp->nxt)
131         {       if (tmp->st == m)
132                 {       if (tmp->ln != n || tmp->fn != e->n->fn)
133                         printf("putsrc mismatch seqno %d, line %d - %d, file %s\n", m, n,
134                                 tmp->ln, tmp->fn->name);
135                         return;
136                 }
137                 if (tmp->st > m) /* insert before */
138                 {       if (tmp == frst)
139                         {       tmp = newsrc(m, frst);
140                                 frst = tmp;
141                         } else
142                         {       assert(lst);
143                                 tmp = newsrc(m, lst->nxt);
144                                 lst->nxt = tmp;
145                         }
146                         tmp->ln = n;
147                         tmp->fn = e->n->fn;
148                         return;
149         }       }
150         /* insert at the end */
151         tmp = newsrc(m, lst?lst->nxt:0);
152         tmp->ln = n;
153         tmp->fn = e->n->fn;
154         if (lst)
155         {       lst->nxt = tmp;
156         } else
157         {       frst = tmp;
158         }
159 }
160
161 static void
162 dumpskip(int n, int m)
163 {       SRC *tmp, *lst;
164         FILE *tz = tc;  /* was th */
165         int j;
166
167         fprintf(tz, "uchar reached%d [] = {\n\t", m);
168         tmp = skip;
169         lst = (SRC *) 0;
170         for (j = 0, col = 0; j <= n; j++)
171         {       /* find j in the sorted list */
172                 for ( ; tmp; lst = tmp, tmp = tmp->nxt)
173                 {       if (tmp->st == j)
174                         {       putnr(1);
175                                 if (lst)
176                                         lst->nxt = tmp->nxt;
177                                 else
178                                         skip = tmp->nxt;
179                                 break;
180                         }
181                         if (tmp->st > j)
182                         {       putnr(0);
183                                 break;  /* j is not in the list */
184                 }       }
185
186                 if (!tmp)
187                 {       putnr(0);
188         }       }
189         fprintf(tz, "};\n");
190         fprintf(tz, "uchar *loopstate%d;\n", m);
191
192         if (m == eventmapnr)
193                 fprintf(th, "#define reached_event      reached%d\n", m);
194
195         skip = (SRC *) 0;
196 }
197
198 void
199 dumpsrc(int n, int m)
200 {       SRC *tmp, *lst;
201         int j;
202         static int did_claim = 0;
203         FILE *tz = tc;  /* was th */
204
205         fprintf(tz, "\nshort src_ln%d [] = {\n\t", m);
206         tmp = frst;
207         for (j = 0, col = 0; j <= n; j++)
208         {       for ( ; tmp; tmp = tmp->nxt)
209                 {       if (tmp->st == j)
210                         {       putnr(tmp->ln);
211                                 break;
212                         }
213                         if (tmp->st > j)
214                         {       putnr(0);
215                                 break;
216                 }       }
217                 if (!tmp)
218                 {       putnr(0);
219         }       }
220         fprintf(tz, "};\n");
221
222         lastfnm = (Symbol *) 0;
223         lastdef.name = "-";
224         fprintf(tz, "S_F_MAP src_file%d [] = {\n\t", m);
225         tmp = frst;
226         lst = (SRC *) 0;
227         for (j = 0, col = 0; j <= n; j++)
228         {       for ( ; tmp; lst = tmp, tmp = tmp->nxt)
229                 {       if (tmp->st == j)
230                         {       putfnm(j, tmp->fn);
231                                 if (lst)
232                                         lst->nxt = tmp->nxt;
233                                 else
234                                         frst = tmp->nxt;
235                                 break;
236                         }
237                         if (tmp->st > j)
238                         {       putfnm(j, &lastdef);
239                                 break;
240                 }       }
241                 if (!tmp)
242                 {       putfnm(j, &lastdef);
243         }       }
244         putfnm_flush(j);
245         fprintf(tz, "};\n");
246
247         if (pid_is_claim(m) && !did_claim)
248         {       fprintf(tz, "short *src_claim;\n");
249                 did_claim++;
250         }
251         if (m == eventmapnr)
252                 fprintf(th, "#define src_event  src_ln%d\n", m);
253
254         frst = (SRC *) 0;
255         dumpskip(n, m);
256 }
257
258 #define Cat0(x)         comwork(fd,now->lft,m); fprintf(fd, x); \
259                         comwork(fd,now->rgt,m)
260 #define Cat1(x)         fprintf(fd,"("); Cat0(x); fprintf(fd,")")
261 #define Cat2(x,y)       fprintf(fd,x); comwork(fd,y,m)
262 #define Cat3(x,y,z)     fprintf(fd,x); comwork(fd,y,m); fprintf(fd,z)
263
264 static int
265 symbolic(FILE *fd, Lextok *tv)
266 {       Lextok *n; extern Lextok *Mtype;
267         int cnt = 1;
268
269         if (tv->ismtyp)
270         for (n = Mtype; n; n = n->rgt, cnt++)
271                 if (cnt == tv->val)
272                 {       fprintf(fd, "%s", n->lft->sym->name);
273                         return 1;
274                 }
275         return 0;
276 }
277
278 static void
279 comwork(FILE *fd, Lextok *now, int m)
280 {       Lextok *v;
281         int i, j;
282
283         if (!now) { fprintf(fd, "0"); return; }
284         switch (now->ntyp) {
285         case CONST:     sr_mesg(fd, now->val, now->ismtyp); break;
286         case '!':       Cat3("!(", now->lft, ")"); break;
287         case UMIN:      Cat3("-(", now->lft, ")"); break;
288         case '~':       Cat3("~(", now->lft, ")"); break;
289
290         case '/':       Cat1("/");  break;
291         case '*':       Cat1("*");  break;
292         case '-':       Cat1("-");  break;
293         case '+':       Cat1("+");  break;
294         case '%':       Cat1("%%"); break;
295         case '&':       Cat1("&");  break;
296         case '^':       Cat1("^");  break;
297         case '|':       Cat1("|");  break;
298         case LE:        Cat1("<="); break;
299         case GE:        Cat1(">="); break;
300         case GT:        Cat1(">"); break;
301         case LT:        Cat1("<"); break;
302         case NE:        Cat1("!="); break;
303         case EQ:
304                         if (ltl_mode
305                         &&  now->lft->ntyp == 'p'
306                         &&  now->rgt->ntyp == 'q')      /* remote ref */
307                         {       Lextok *p = now->lft->lft;
308
309                                 fprintf(fd, "(");
310                                 fprintf(fd, "%s", p->sym->name);
311                                 if (p->lft)
312                                 {       fprintf(fd, "[");
313                                         putstmnt(fd, p->lft, 0); /* pid */
314                                         fprintf(fd, "]");
315                                 }
316                                 fprintf(fd, "@");
317                                 fprintf(fd, "%s", now->rgt->sym->name);
318                                 fprintf(fd, ")");
319                                 break;
320                         }
321                         Cat1("==");
322                         break;
323
324         case OR:        Cat1("||"); break;
325         case AND:       Cat1("&&"); break;
326         case LSHIFT:    Cat1("<<"); break;
327         case RSHIFT:    Cat1(">>"); break;
328
329         case RUN:       fprintf(fd, "run %s(", now->sym->name);
330                         for (v = now->lft; v; v = v->rgt)
331                                 if (v == now->lft)
332                                 {       comwork(fd, v->lft, m);
333                                 } else
334                                 {       Cat2(",", v->lft);
335                                 }
336                         fprintf(fd, ")");
337                         break;
338
339         case LEN:       putname(fd, "len(", now->lft, m, ")");
340                         break;
341         case FULL:      putname(fd, "full(", now->lft, m, ")");
342                         break;
343         case EMPTY:     putname(fd, "empty(", now->lft, m, ")");
344                         break;
345         case NFULL:     putname(fd, "nfull(", now->lft, m, ")");
346                         break;
347         case NEMPTY:    putname(fd, "nempty(", now->lft, m, ")");
348                         break;
349
350         case 's':       putname(fd, "", now->lft, m, now->val?"!!":"!");
351                         for (v = now->rgt, i=0; v; v = v->rgt, i++)
352                         {       if (v != now->rgt) fprintf(fd,",");
353                                 if (!symbolic(fd, v->lft))
354                                         comwork(fd,v->lft,m);
355                         }
356                         break;
357         case 'r':       putname(fd, "", now->lft, m, "?");
358                         switch (now->val) {
359                         case 0: break;
360                         case 1: fprintf(fd, "?");  break;
361                         case 2: fprintf(fd, "<");  break;
362                         case 3: fprintf(fd, "?<"); break;
363                         }
364                         for (v = now->rgt, i=0; v; v = v->rgt, i++)
365                         {       if (v != now->rgt) fprintf(fd,",");
366                                 if (!symbolic(fd, v->lft))
367                                         comwork(fd,v->lft,m);
368                         }
369                         if (now->val >= 2)
370                                 fprintf(fd, ">");
371                         break;
372         case 'R':       putname(fd, "", now->lft, m,  now->val?"??[":"?[");
373                         for (v = now->rgt, i=0; v; v = v->rgt, i++)
374                         {       if (v != now->rgt) fprintf(fd,",");
375                                 if (!symbolic(fd, v->lft))
376                                         comwork(fd,v->lft,m);
377                         }
378                         fprintf(fd, "]");
379                         break;
380
381         case ENABLED:   Cat3("enabled(", now->lft, ")");
382                         break;
383
384         case GET_P:     if (old_priority_rules)
385                         {       fprintf(fd, "1");
386                         } else
387                         {       Cat3("get_priority(", now->lft, ")");
388                         }
389                         break;
390
391         case SET_P:     if (!old_priority_rules)
392                         {       fprintf(fd, "set_priority(");
393                                 comwork(fd, now->lft->lft, m);
394                                 fprintf(fd, ", ");
395                                 comwork(fd, now->lft->rgt, m);
396                                 fprintf(fd, ")");
397                         }
398                         break;
399
400         case EVAL:      Cat3("eval(", now->lft, ")");
401                         break;
402
403         case NONPROGRESS:
404                         fprintf(fd, "np_");
405                         break;
406
407         case PC_VAL:    Cat3("pc_value(", now->lft, ")");
408                         break;
409
410         case 'c':       Cat3("(", now->lft, ")");
411                         break;
412
413         case '?':       if (now->lft)
414                         {       Cat3("( (", now->lft, ") -> ");
415                         }
416                         if (now->rgt)
417                         {       Cat3("(", now->rgt->lft, ") : ");
418                                 Cat3("(", now->rgt->rgt, ") )");
419                         }
420                         break;  
421
422         case ASGN:
423                         if (check_track(now) == STRUCT) { break; }
424                         comwork(fd,now->lft,m);
425                         fprintf(fd," = ");
426                         comwork(fd,now->rgt,m);
427                         break;
428
429         case PRINT:     {       char c, buf[1024];
430                                 strncpy(buf, now->sym->name, 510);
431                                 for (i = j = 0; i < 510; i++, j++)
432                                 {       c = now->sym->name[i];
433                                         buf[j] = c;
434                                         if (c == '\\') buf[++j] = c;
435                                         if (c == '\"') buf[j] = '\'';
436                                         if (c == '\0') break;
437                                 }
438                                 if (now->ntyp == PRINT)
439                                         fprintf(fd, "printf");
440                                 else
441                                         fprintf(fd, "annotate");
442                                 fprintf(fd, "(%s", buf);
443                         }
444                         for (v = now->lft; v; v = v->rgt)
445                         {       Cat2(",", v->lft);
446                         }
447                         fprintf(fd, ")");
448                         break;
449         case PRINTM:    fprintf(fd, "printm(");
450                         comwork(fd, now->lft, m);
451                         fprintf(fd, ")");
452                         break;
453         case NAME:
454                         putname(fd, "", now, m, "");
455                         break;
456
457         case   'p':
458                         if (ltl_mode)
459                         {       fprintf(fd, "%s", now->lft->sym->name); /* proctype */
460                                 if (now->lft->lft)
461                                 {       fprintf(fd, "[");
462                                         putstmnt(fd, now->lft->lft, 0); /* pid */
463                                         fprintf(fd, "]");
464                                 }
465                                 fprintf(fd, ":");       /* remote varref */
466                                 fprintf(fd, "%s", now->sym->name);      /* varname */
467                                 break;
468                         }
469                         putremote(fd, now, m);
470                         break;
471         case   'q':     fprintf(fd, "%s", now->sym->name);
472                         break;
473         case C_EXPR:    
474         case C_CODE:    fprintf(fd, "{%s}", now->sym->name);
475                         break;
476         case ASSERT:    Cat3("assert(", now->lft, ")");
477                         break;
478         case   '.':     fprintf(fd, ".(goto)"); break;
479         case  GOTO:     fprintf(fd, "goto %s", now->sym->name); break;
480         case BREAK:     fprintf(fd, "break"); break;
481         case  ELSE:     fprintf(fd, "else"); break;
482         case   '@':     fprintf(fd, "-end-"); break;
483
484         case D_STEP:    fprintf(fd, "D_STEP%d", now->ln); break;
485         case ATOMIC:    fprintf(fd, "ATOMIC"); break;
486         case NON_ATOMIC: fprintf(fd, "sub-sequence"); break;
487         case IF:        fprintf(fd, "IF"); break;
488         case DO:        fprintf(fd, "DO"); break;
489         case UNLESS:    fprintf(fd, "unless"); break;
490         case TIMEOUT:   fprintf(fd, "timeout"); break;
491         default:        if (isprint(now->ntyp))
492                                 fprintf(fd, "'%c'", now->ntyp);
493                         else
494                                 fprintf(fd, "%d", now->ntyp);
495                         break;
496         }
497 }
498
499 void
500 comment(FILE *fd, Lextok *now, int m)
501 {       extern short terse, nocast;
502
503         terse=nocast=1;
504         comwork(fd, now, m);
505         terse=nocast=0;
506 }