move everything out of trunk
[lttv.git] / verif / Spin / Src5.1.6 / pangen5.c
1 /***** spin: pangen5.c *****/
2
3 /* Copyright (c) 1999-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 typedef struct BuildStack {
16 FSM_trans *t;
17 struct BuildStack *nxt;
18 } BuildStack;
19
20 extern ProcList *rdy;
21 extern int verbose, eventmapnr, claimnr, rvopt, export_ast, u_sync;
22 extern Element *Al_El;
23
24 static FSM_state *fsm_free;
25 static FSM_trans *trans_free;
26 static BuildStack *bs, *bf;
27 static int max_st_id;
28 static int cur_st_id;
29 int o_max;
30 FSM_state *fsm;
31 FSM_state **fsm_tbl;
32 FSM_use *use_free;
33
34 static void ana_seq(Sequence *);
35 static void ana_stmnt(FSM_trans *, Lextok *, int);
36
37 extern void AST_slice(void);
38 extern void AST_store(ProcList *, int);
39 extern int has_global(Lextok *);
40 extern void exit(int);
41
42 static void
43 fsm_table(void)
44 { FSM_state *f;
45 max_st_id += 2;
46 /* fprintf(stderr, "omax %d, max=%d\n", o_max, max_st_id); */
47 if (o_max < max_st_id)
48 { o_max = max_st_id;
49 fsm_tbl = (FSM_state **) emalloc(max_st_id * sizeof(FSM_state *));
50 } else
51 memset((char *)fsm_tbl, 0, max_st_id * sizeof(FSM_state *));
52 cur_st_id = max_st_id;
53 max_st_id = 0;
54
55 for (f = fsm; f; f = f->nxt)
56 fsm_tbl[f->from] = f;
57 }
58
59 static int
60 FSM_DFS(int from, FSM_use *u)
61 { FSM_state *f;
62 FSM_trans *t;
63 FSM_use *v;
64 int n;
65
66 if (from == 0)
67 return 1;
68
69 f = fsm_tbl[from];
70
71 if (!f)
72 { printf("cannot find state %d\n", from);
73 fatal("fsm_dfs: cannot happen\n", (char *) 0);
74 }
75
76 if (f->seen)
77 return 1;
78 f->seen = 1;
79
80 for (t = f->t; t; t = t->nxt)
81 {
82 for (n = 0; n < 2; n++)
83 for (v = t->Val[n]; v; v = v->nxt)
84 if (u->var == v->var)
85 return n; /* a read or write */
86
87 if (!FSM_DFS(t->to, u))
88 return 0;
89 }
90 return 1;
91 }
92
93 static void
94 new_dfs(void)
95 { int i;
96
97 for (i = 0; i < cur_st_id; i++)
98 if (fsm_tbl[i])
99 fsm_tbl[i]->seen = 0;
100 }
101
102 static int
103 good_dead(Element *e, FSM_use *u)
104 {
105 switch (u->special) {
106 case 2: /* ok if it's a receive */
107 if (e->n->ntyp == ASGN
108 && e->n->rgt->ntyp == CONST
109 && e->n->rgt->val == 0)
110 return 0;
111 break;
112 case 1: /* must be able to use oval */
113 if (e->n->ntyp != 'c'
114 && e->n->ntyp != 'r')
115 return 0; /* can't really happen */
116 break;
117 }
118 return 1;
119 }
120
121 #if 0
122 static int howdeep = 0;
123 #endif
124
125 static int
126 eligible(FSM_trans *v)
127 { Element *el = ZE;
128 Lextok *lt = ZN;
129
130 if (v) el = v->step;
131 if (el) lt = v->step->n;
132
133 if (!lt /* dead end */
134 || v->nxt /* has alternatives */
135 || el->esc /* has an escape */
136 || (el->status&CHECK2) /* remotely referenced */
137 || lt->ntyp == ATOMIC
138 || lt->ntyp == NON_ATOMIC /* used for inlines -- should be able to handle this */
139 || lt->ntyp == IF
140 || lt->ntyp == C_CODE
141 || lt->ntyp == C_EXPR
142 || has_lab(el, 0) /* any label at all */
143
144 || lt->ntyp == DO
145 || lt->ntyp == UNLESS
146 || lt->ntyp == D_STEP
147 || lt->ntyp == ELSE
148 || lt->ntyp == '@'
149 || lt->ntyp == 'c'
150 || lt->ntyp == 'r'
151 || lt->ntyp == 's')
152 return 0;
153
154 if (!(el->status&(2|4))) /* not atomic */
155 { int unsafe = (el->status&I_GLOB)?1:has_global(el->n);
156 if (unsafe)
157 return 0;
158 }
159
160 return 1;
161 }
162
163 static int
164 canfill_in(FSM_trans *v)
165 { Element *el = v->step;
166 Lextok *lt = v->step->n;
167
168 if (!lt /* dead end */
169 || v->nxt /* has alternatives */
170 || el->esc /* has an escape */
171 || (el->status&CHECK2)) /* remotely referenced */
172 return 0;
173
174 if (!(el->status&(2|4)) /* not atomic */
175 && ((el->status&I_GLOB)
176 || has_global(el->n))) /* and not safe */
177 return 0;
178
179 return 1;
180 }
181
182 static int
183 pushbuild(FSM_trans *v)
184 { BuildStack *b;
185
186 for (b = bs; b; b = b->nxt)
187 if (b->t == v)
188 return 0;
189 if (bf)
190 { b = bf;
191 bf = bf->nxt;
192 } else
193 b = (BuildStack *) emalloc(sizeof(BuildStack));
194 b->t = v;
195 b->nxt = bs;
196 bs = b;
197 return 1;
198 }
199
200 static void
201 popbuild(void)
202 { BuildStack *f;
203 if (!bs)
204 fatal("cannot happen, popbuild", (char *) 0);
205 f = bs;
206 bs = bs->nxt;
207 f->nxt = bf;
208 bf = f; /* freelist */
209 }
210
211 static int
212 build_step(FSM_trans *v)
213 { FSM_state *f;
214 Element *el;
215 #if 0
216 Lextok *lt = ZN;
217 #endif
218 int st;
219 int r;
220
221 if (!v) return -1;
222
223 el = v->step;
224 st = v->to;
225
226 if (!el) return -1;
227
228 if (v->step->merge)
229 return v->step->merge; /* already done */
230
231 if (!eligible(v)) /* non-blocking */
232 return -1;
233
234 if (!pushbuild(v)) /* cycle detected */
235 return -1; /* break cycle */
236
237 f = fsm_tbl[st];
238 #if 0
239 lt = v->step->n;
240 if (verbose&32)
241 { if (++howdeep == 1)
242 printf("spin: %s, line %3d, merge:\n",
243 lt->fn->name,
244 lt->ln);
245 printf("\t[%d] <seqno %d>\t", howdeep, el->seqno);
246 comment(stdout, lt, 0);
247 printf(";\n");
248 }
249 #endif
250 r = build_step(f->t);
251 v->step->merge = (r == -1) ? st : r;
252 #if 0
253 if (verbose&32)
254 { printf(" merge value: %d (st=%d,r=%d, line %d)\n",
255 v->step->merge, st, r, el->n->ln);
256 howdeep--;
257 }
258 #endif
259 popbuild();
260
261 return v->step->merge;
262 }
263
264 static void
265 FSM_MERGER(/* char *pname */ void) /* find candidates for safely merging steps */
266 { FSM_state *f, *g;
267 FSM_trans *t;
268 Lextok *lt;
269
270 for (f = fsm; f; f = f->nxt) /* all states */
271 for (t = f->t; t; t = t->nxt) /* all edges */
272 { if (!t->step) continue; /* happens with 'unless' */
273
274 t->step->merge_in = f->in; /* ?? */
275
276 if (t->step->merge)
277 continue;
278 lt = t->step->n;
279
280 if (lt->ntyp == 'c'
281 || lt->ntyp == 'r'
282 || lt->ntyp == 's') /* blocking stmnts */
283 continue; /* handled in 2nd scan */
284
285 if (!eligible(t))
286 continue;
287
288 g = fsm_tbl[t->to];
289 if (!g || !eligible(g->t))
290 {
291 #define SINGLES
292 #ifdef SINGLES
293 t->step->merge_single = t->to;
294 #if 0
295 if ((verbose&32))
296 { printf("spin: %s, line %3d, merge_single:\n\t<seqno %d>\t",
297 t->step->n->fn->name,
298 t->step->n->ln,
299 t->step->seqno);
300 comment(stdout, t->step->n, 0);
301 printf(";\n");
302 }
303 #endif
304 #endif
305 /* t is an isolated eligible step:
306 *
307 * a merge_start can connect to a proper
308 * merge chain or to a merge_single
309 * a merge chain can be preceded by
310 * a merge_start, but not by a merge_single
311 */
312
313 continue;
314 }
315
316 (void) build_step(t);
317 }
318
319 /* 2nd scan -- find possible merge_starts */
320
321 for (f = fsm; f; f = f->nxt) /* all states */
322 for (t = f->t; t; t = t->nxt) /* all edges */
323 { if (!t->step || t->step->merge)
324 continue;
325
326 lt = t->step->n;
327 #if 0
328 4.1.3:
329 an rv send operation inside an atomic, *loses* atomicity
330 when executed
331 and should therefore never be merged with a subsequent
332 statement within the atomic sequence
333 the same is not true for non-rv send operations
334 #endif
335
336 if (lt->ntyp == 'c' /* potentially blocking stmnts */
337 || lt->ntyp == 'r'
338 || (lt->ntyp == 's' && u_sync == 0)) /* added !u_sync in 4.1.3 */
339 { if (!canfill_in(t)) /* atomic, non-global, etc. */
340 continue;
341
342 g = fsm_tbl[t->to];
343 if (!g || !g->t || !g->t->step)
344 continue;
345 if (g->t->step->merge)
346 t->step->merge_start = g->t->step->merge;
347 #ifdef SINGLES
348 else if (g->t->step->merge_single)
349 t->step->merge_start = g->t->step->merge_single;
350 #endif
351 #if 0
352 if ((verbose&32)
353 && t->step->merge_start)
354 { printf("spin: %s, line %3d, merge_START:\n\t<seqno %d>\t",
355 lt->fn->name,
356 lt->ln,
357 t->step->seqno);
358 comment(stdout, lt, 0);
359 printf(";\n");
360 }
361 #endif
362 }
363 }
364 }
365
366 static void
367 FSM_ANA(void)
368 { FSM_state *f;
369 FSM_trans *t;
370 FSM_use *u, *v, *w;
371 int n;
372
373 for (f = fsm; f; f = f->nxt) /* all states */
374 for (t = f->t; t; t = t->nxt) /* all edges */
375 for (n = 0; n < 2; n++) /* reads and writes */
376 for (u = t->Val[n]; u; u = u->nxt)
377 { if (!u->var->context /* global */
378 || u->var->type == CHAN
379 || u->var->type == STRUCT)
380 continue;
381 new_dfs();
382 if (FSM_DFS(t->to, u)) /* cannot hit read before hitting write */
383 u->special = n+1; /* means, reset to 0 after use */
384 }
385
386 if (!export_ast)
387 for (f = fsm; f; f = f->nxt)
388 for (t = f->t; t; t = t->nxt)
389 for (n = 0; n < 2; n++)
390 for (u = t->Val[n], w = (FSM_use *) 0; u; )
391 { if (u->special)
392 { v = u->nxt;
393 if (!w) /* remove from list */
394 t->Val[n] = v;
395 else
396 w->nxt = v;
397 #if q
398 if (verbose&32)
399 { printf("%s : %3d: %d -> %d \t",
400 t->step->n->fn->name,
401 t->step->n->ln,
402 f->from,
403 t->to);
404 comment(stdout, t->step->n, 0);
405 printf("\t%c%d: %s\n", n==0?'R':'L',
406 u->special, u->var->name);
407 }
408 #endif
409 if (good_dead(t->step, u))
410 { u->nxt = t->step->dead; /* insert into dead */
411 t->step->dead = u;
412 }
413 u = v;
414 } else
415 { w = u;
416 u = u->nxt;
417 } }
418 }
419
420 void
421 rel_use(FSM_use *u)
422 {
423 if (!u) return;
424 rel_use(u->nxt);
425 u->var = (Symbol *) 0;
426 u->special = 0;
427 u->nxt = use_free;
428 use_free = u;
429 }
430
431 static void
432 rel_trans(FSM_trans *t)
433 {
434 if (!t) return;
435 rel_trans(t->nxt);
436 rel_use(t->Val[0]);
437 rel_use(t->Val[1]);
438 t->Val[0] = t->Val[1] = (FSM_use *) 0;
439 t->nxt = trans_free;
440 trans_free = t;
441 }
442
443 static void
444 rel_state(FSM_state *f)
445 {
446 if (!f) return;
447 rel_state(f->nxt);
448 rel_trans(f->t);
449 f->t = (FSM_trans *) 0;
450 f->nxt = fsm_free;
451 fsm_free = f;
452 }
453
454 static void
455 FSM_DEL(void)
456 {
457 rel_state(fsm);
458 fsm = (FSM_state *) 0;
459 }
460
461 static FSM_state *
462 mkstate(int s)
463 { FSM_state *f;
464
465 /* fsm_tbl isn't allocated yet */
466 for (f = fsm; f; f = f->nxt)
467 if (f->from == s)
468 break;
469 if (!f)
470 { if (fsm_free)
471 { f = fsm_free;
472 memset(f, 0, sizeof(FSM_state));
473 fsm_free = fsm_free->nxt;
474 } else
475 f = (FSM_state *) emalloc(sizeof(FSM_state));
476 f->from = s;
477 f->t = (FSM_trans *) 0;
478 f->nxt = fsm;
479 fsm = f;
480 if (s > max_st_id)
481 max_st_id = s;
482 }
483 return f;
484 }
485
486 static FSM_trans *
487 get_trans(int to)
488 { FSM_trans *t;
489
490 if (trans_free)
491 { t = trans_free;
492 memset(t, 0, sizeof(FSM_trans));
493 trans_free = trans_free->nxt;
494 } else
495 t = (FSM_trans *) emalloc(sizeof(FSM_trans));
496
497 t->to = to;
498 return t;
499 }
500
501 static void
502 FSM_EDGE(int from, int to, Element *e)
503 { FSM_state *f;
504 FSM_trans *t;
505
506 f = mkstate(from); /* find it or else make it */
507 t = get_trans(to);
508
509 t->step = e;
510 t->nxt = f->t;
511 f->t = t;
512
513 f = mkstate(to);
514 f->in++;
515
516 if (export_ast)
517 { t = get_trans(from);
518 t->step = e;
519 t->nxt = f->p; /* from is a predecessor of to */
520 f->p = t;
521 }
522
523 if (t->step)
524 ana_stmnt(t, t->step->n, 0);
525 }
526
527 #define LVAL 1
528 #define RVAL 0
529
530 static void
531 ana_var(FSM_trans *t, Lextok *now, int usage)
532 { FSM_use *u, *v;
533
534 if (!t || !now || !now->sym)
535 return;
536
537 if (now->sym->name[0] == '_'
538 && (strcmp(now->sym->name, "_") == 0
539 || strcmp(now->sym->name, "_pid") == 0
540 || strcmp(now->sym->name, "_last") == 0))
541 return;
542
543 v = t->Val[usage];
544 for (u = v; u; u = u->nxt)
545 if (u->var == now->sym)
546 return; /* it's already there */
547
548 if (!now->lft)
549 { /* not for array vars -- it's hard to tell statically
550 if the index would, at runtime, evaluate to the
551 same values at lval and rval references
552 */
553 if (use_free)
554 { u = use_free;
555 use_free = use_free->nxt;
556 } else
557 u = (FSM_use *) emalloc(sizeof(FSM_use));
558
559 u->var = now->sym;
560 u->nxt = t->Val[usage];
561 t->Val[usage] = u;
562 } else
563 ana_stmnt(t, now->lft, RVAL); /* index */
564
565 if (now->sym->type == STRUCT
566 && now->rgt
567 && now->rgt->lft)
568 ana_var(t, now->rgt->lft, usage);
569 }
570
571 static void
572 ana_stmnt(FSM_trans *t, Lextok *now, int usage)
573 { Lextok *v;
574
575 if (!t || !now) return;
576
577 switch (now->ntyp) {
578 case '.':
579 case BREAK:
580 case GOTO:
581 case CONST:
582 case TIMEOUT:
583 case NONPROGRESS:
584 case ELSE:
585 case '@':
586 case 'q':
587 case IF:
588 case DO:
589 case ATOMIC:
590 case NON_ATOMIC:
591 case D_STEP:
592 case C_CODE:
593 case C_EXPR:
594 break;
595
596 case '!':
597 case UMIN:
598 case '~':
599 case ENABLED:
600 case PC_VAL:
601 case LEN:
602 case FULL:
603 case EMPTY:
604 case NFULL:
605 case NEMPTY:
606 case ASSERT:
607 case 'c':
608 ana_stmnt(t, now->lft, RVAL);
609 break;
610
611 case '/':
612 case '*':
613 case '-':
614 case '+':
615 case '%':
616 case '&':
617 case '^':
618 case '|':
619 case LT:
620 case GT:
621 case LE:
622 case GE:
623 case NE:
624 case EQ:
625 case OR:
626 case AND:
627 case LSHIFT:
628 case RSHIFT:
629 ana_stmnt(t, now->lft, RVAL);
630 ana_stmnt(t, now->rgt, RVAL);
631 break;
632
633 case ASGN:
634 ana_stmnt(t, now->lft, LVAL);
635 ana_stmnt(t, now->rgt, RVAL);
636 break;
637
638 case PRINT:
639 case RUN:
640 for (v = now->lft; v; v = v->rgt)
641 ana_stmnt(t, v->lft, RVAL);
642 break;
643
644 case PRINTM:
645 if (now->lft && !now->lft->ismtyp)
646 ana_stmnt(t, now->lft, RVAL);
647 break;
648
649 case 's':
650 ana_stmnt(t, now->lft, RVAL);
651 for (v = now->rgt; v; v = v->rgt)
652 ana_stmnt(t, v->lft, RVAL);
653 break;
654
655 case 'R':
656 case 'r':
657 ana_stmnt(t, now->lft, RVAL);
658 for (v = now->rgt; v; v = v->rgt)
659 { if (v->lft->ntyp == EVAL)
660 ana_stmnt(t, v->lft->lft, RVAL);
661 else
662 if (v->lft->ntyp != CONST
663 && now->ntyp != 'R') /* was v->lft->ntyp */
664 ana_stmnt(t, v->lft, LVAL);
665 }
666 break;
667
668 case '?':
669 ana_stmnt(t, now->lft, RVAL);
670 if (now->rgt)
671 { ana_stmnt(t, now->rgt->lft, RVAL);
672 ana_stmnt(t, now->rgt->rgt, RVAL);
673 }
674 break;
675
676 case NAME:
677 ana_var(t, now, usage);
678 break;
679
680 case 'p': /* remote ref */
681 ana_stmnt(t, now->lft->lft, RVAL); /* process id */
682 ana_var(t, now, RVAL);
683 ana_var(t, now->rgt, RVAL);
684 break;
685
686 default:
687 printf("spin: bad node type %d line %d (ana_stmnt)\n", now->ntyp, now->ln);
688 fatal("aborting", (char *) 0);
689 }
690 }
691
692 void
693 ana_src(int dataflow, int merger) /* called from main.c and guided.c */
694 { ProcList *p;
695 Element *e;
696 #if 0
697 int counter = 1;
698 #endif
699 for (p = rdy; p; p = p->nxt)
700 { if (p->tn == eventmapnr
701 || p->tn == claimnr)
702 continue;
703
704 ana_seq(p->s);
705 fsm_table();
706
707 e = p->s->frst;
708 #if 0
709 if (dataflow || merger)
710 { printf("spin: %d, optimizing '%s'",
711 counter++, p->n->name);
712 fflush(stdout);
713 }
714 #endif
715 if (dataflow)
716 { FSM_ANA();
717 }
718 if (merger)
719 { FSM_MERGER(/* p->n->name */);
720 huntele(e, e->status, -1)->merge_in = 1; /* start-state */
721 #if 0
722 printf("\n");
723 #endif
724 }
725 if (export_ast)
726 AST_store(p, huntele(e, e->status, -1)->seqno);
727
728 FSM_DEL();
729 }
730 for (e = Al_El; e; e = e->Nxt)
731 {
732 if (!(e->status&DONE) && (verbose&32))
733 { printf("unreachable code: ");
734 printf("%s, line %3d: ",
735 e->n->fn->name, e->n->ln);
736 comment(stdout, e->n, 0);
737 printf("\n");
738 }
739 e->status &= ~DONE;
740 }
741 if (export_ast)
742 { AST_slice();
743 exit(0);
744 }
745 }
746
747 void
748 spit_recvs(FILE *f1, FILE *f2) /* called from pangen2.c */
749 { Element *e;
750 Sequence *s;
751 extern int Unique;
752
753 fprintf(f1, "unsigned char Is_Recv[%d];\n", Unique);
754
755 fprintf(f2, "void\nset_recvs(void)\n{\n");
756 for (e = Al_El; e; e = e->Nxt)
757 { if (!e->n) continue;
758
759 switch (e->n->ntyp) {
760 case 'r':
761 markit: fprintf(f2, "\tIs_Recv[%d] = 1;\n", e->Seqno);
762 break;
763 case D_STEP:
764 s = e->n->sl->this;
765 switch (s->frst->n->ntyp) {
766 case DO:
767 fatal("unexpected: do at start of d_step", (char *) 0);
768 case IF: /* conservative: fall through */
769 case 'r': goto markit;
770 }
771 break;
772 }
773 }
774 fprintf(f2, "}\n");
775
776 if (rvopt)
777 {
778 fprintf(f2, "int\nno_recvs(int me)\n{\n");
779 fprintf(f2, " int h; uchar ot; short tt;\n");
780 fprintf(f2, " Trans *t;\n");
781 fprintf(f2, " for (h = BASE; h < (int) now._nr_pr; h++)\n");
782 fprintf(f2, " { if (h == me) continue;\n");
783 fprintf(f2, " tt = (short) ((P0 *)pptr(h))->_p;\n");
784 fprintf(f2, " ot = (uchar) ((P0 *)pptr(h))->_t;\n");
785 fprintf(f2, " for (t = trans[ot][tt]; t; t = t->nxt)\n");
786 fprintf(f2, " if (Is_Recv[t->t_id]) return 0;\n");
787 fprintf(f2, " }\n");
788 fprintf(f2, " return 1;\n");
789 fprintf(f2, "}\n");
790 }
791 }
792
793 static void
794 ana_seq(Sequence *s)
795 { SeqList *h;
796 Sequence *t;
797 Element *e, *g;
798 int From, To;
799
800 for (e = s->frst; e; e = e->nxt)
801 { if (e->status & DONE)
802 goto checklast;
803
804 e->status |= DONE;
805
806 From = e->seqno;
807
808 if (e->n->ntyp == UNLESS)
809 ana_seq(e->sub->this);
810 else if (e->sub)
811 { for (h = e->sub; h; h = h->nxt)
812 { g = huntstart(h->this->frst);
813 To = g->seqno;
814
815 if (g->n->ntyp != 'c'
816 || g->n->lft->ntyp != CONST
817 || g->n->lft->val != 0
818 || g->esc)
819 FSM_EDGE(From, To, e);
820 /* else it's a dead link */
821 }
822 for (h = e->sub; h; h = h->nxt)
823 ana_seq(h->this);
824 } else if (e->n->ntyp == ATOMIC
825 || e->n->ntyp == D_STEP
826 || e->n->ntyp == NON_ATOMIC)
827 {
828 t = e->n->sl->this;
829 g = huntstart(t->frst);
830 t->last->nxt = e->nxt;
831 To = g->seqno;
832 FSM_EDGE(From, To, e);
833
834 ana_seq(t);
835 } else
836 { if (e->n->ntyp == GOTO)
837 { g = get_lab(e->n, 1);
838 g = huntele(g, e->status, -1);
839 To = g->seqno;
840 } else if (e->nxt)
841 { g = huntele(e->nxt, e->status, -1);
842 To = g->seqno;
843 } else
844 To = 0;
845
846 FSM_EDGE(From, To, e);
847
848 if (e->esc
849 && e->n->ntyp != GOTO
850 && e->n->ntyp != '.')
851 for (h = e->esc; h; h = h->nxt)
852 { g = huntstart(h->this->frst);
853 To = g->seqno;
854 FSM_EDGE(From, To, ZE);
855 ana_seq(h->this);
856 }
857 }
858
859 checklast: if (e == s->last)
860 break;
861 }
862 }
This page took 0.046158 seconds and 4 git commands to generate.