📄 pangen2.c
字号:
} else fprintf(tb, ";"); } else fprintf(tb, ";"); fprintf(tb, "\n\t\t"); if (multi_undo) { fprintf(tb, "ungrab_ints(trpt->bup.ovals, %d);\n\t\t", multi_undo); multi_undo = 0; } if (didcase) { fprintf(tb, "goto R999;\n"); bupcase = casenr; } if (!e->merge && !e->merge_start) new_case(e, casenr, bupcase, Pid);gotit: j = a; if (e->merge_start) j = e->merge_start; else if (e->merge) j = e->merge;haveit: fprintf(tt, "%ssettr(%d,%d,%d,%d,%d,\"", fromcache?"/* c */ ":"", e->Seqno, mark, j, casenr, bupcase); return (fromcache)?0:casenr;}static voidput_el(Element *e, int Tt0, int Tt1){ int a, casenr, Global_ref; Element *g = ZE; if (e->n->ntyp == GOTO) { g = get_lab(e->n, 1); g = huntele(g, e->status, -1); cross_dsteps(e->n, g->n); a = g->seqno; } else if (e->nxt) { g = huntele(e->nxt, e->status, -1); a = g->seqno; } else a = 0; if (g && (g->status&CHECK2 /* entering remotely ref'd state */ || e->status&CHECK2)) /* leaving remotely ref'd state */ e->status |= I_GLOB; /* don't remove dead edges in here, to preserve structure of fsm */ if (e->merge_start || e->merge) goto non_generic; /*** avoid duplicate or redundant cases in pan.m ***/ switch (e->n->ntyp) { case ELSE: casenr = 2; /* standard else */ putskip(e->seqno); goto generic_case; /* break; */ case '.': case GOTO: case BREAK: putskip(e->seqno); casenr = 1; /* standard goto */generic_case: fprintf(tt, "\ttrans[%d][%d]\t= ", Pid, e->seqno); fprintf(tt, "settr(%d,%d,%d,%d,0,\"", e->Seqno, e->status&ATOM, a, casenr); break;#ifndef PRINTF case PRINT: goto non_generic; case PRINTM: goto non_generic;#endif case 'c': if (e->n->lft->ntyp == CONST && e->n->lft->val == 1) /* skip or true */ { casenr = 1; putskip(e->seqno); goto generic_case; } goto non_generic; default:non_generic: casenr = case_cache(e, a); if (casenr < 0) return; /* unreachable state */ break; } /* tailend of settr(...); */ Global_ref = (e->status&I_GLOB)?1:has_global(e->n); comment(tt, e->n, e->seqno); fprintf(tt, "\", %d, ", Global_ref); if (Tt0 != 2) { fprintf(tt, "%d, %d);", Tt0, Tt1); } else { Tpe(e->n); /* sets EPT */ fprintf(tt, "%d, %d);", EPT[0], EPT[1]); } if ((e->merge_start && e->merge_start != a) || (e->merge && e->merge != a)) { fprintf(tt, " /* m: %d -> %d,%d */\n", a, e->merge_start, e->merge); fprintf(tt, " reached%d[%d] = 1;", Pid, a); /* Sheinman's example */ } fprintf(tt, "\n"); if (casenr > 2) tr_map(casenr, e); put_escp(e);}static voidnested_unless(Element *e, Element *g){ struct SeqList *y = e->esc, *z = g->esc; for ( ; y && z; y = y->nxt, z = z->nxt) if (z->this != y->this) break; if (!y && !z) return; if (g->n->ntyp != GOTO && g->n->ntyp != '.' && e->sub->nxt) { printf("error: (%s:%d) saw 'unless' on a guard:\n", (e->n)?e->n->fn->name:"-", (e->n)?e->n->ln:0); printf("=====>instead of\n"); printf(" do (or if)\n"); printf(" :: ...\n"); printf(" :: stmnt1 unless stmnt2\n"); printf(" od (of fi)\n"); printf("=====>use\n"); printf(" do (or if)\n"); printf(" :: ...\n"); printf(" :: stmnt1\n"); printf(" od (or fi) unless stmnt2\n"); printf("=====>or rewrite\n"); }}static voidput_seq(Sequence *s, int Tt0, int Tt1){ SeqList *h; Element *e, *g; int a, deadlink; if (0) printf("put_seq %d\n", s->frst->seqno); for (e = s->frst; e; e = e->nxt) { if (0) printf(" step %d\n", e->seqno); if (e->status & DONE) { if (0) printf(" done before\n"); goto checklast; } e->status |= DONE; if (e->n->ln) putsrc(e); if (e->n->ntyp == UNLESS) { if (0) printf(" an unless\n"); put_seq(e->sub->this, Tt0, Tt1); } else if (e->sub) { if (0) printf(" has sub\n"); fprintf(tt, "\tT = trans[%d][%d] = ", Pid, e->seqno); fprintf(tt, "settr(%d,%d,0,0,0,\"", e->Seqno, e->status&ATOM); comment(tt, e->n, e->seqno); if (e->status&CHECK2) e->status |= I_GLOB; fprintf(tt, "\", %d, %d, %d);", (e->status&I_GLOB)?1:0, Tt0, Tt1); blurb(tt, e); for (h = e->sub; h; h = h->nxt) { putskip(h->this->frst->seqno); g = huntstart(h->this->frst); if (g->esc) nested_unless(e, g); a = g->seqno; if (g->n->ntyp == 'c' && g->n->lft->ntyp == CONST && g->n->lft->val == 0 /* 0 or false */ && !g->esc) { fprintf(tt, "#if 0\n\t/* dead link: */\n"); deadlink = 1; if (verbose&32) printf("spin: line %3d %s, Warning: condition is always false\n", g->n->ln, g->n->fn?g->n->fn->name:""); } else deadlink = 0; if (0) printf(" settr %d %d\n", a, 0); if (h->nxt) fprintf(tt, "\tT = T->nxt\t= "); else fprintf(tt, "\t T->nxt\t= "); fprintf(tt, "settr(%d,%d,%d,0,0,\"", e->Seqno, e->status&ATOM, a); comment(tt, e->n, e->seqno); if (g->status&CHECK2) h->this->frst->status |= I_GLOB; fprintf(tt, "\", %d, %d, %d);", (h->this->frst->status&I_GLOB)?1:0, Tt0, Tt1); blurb(tt, e); if (deadlink) fprintf(tt, "#endif\n"); } for (h = e->sub; h; h = h->nxt) put_seq(h->this, Tt0, Tt1); } else { if (0) printf(" [non]atomic %d\n", e->n->ntyp); if (e->n->ntyp == ATOMIC || e->n->ntyp == D_STEP || e->n->ntyp == NON_ATOMIC) put_sub(e, Tt0, Tt1); else { if (0) printf(" put_el %d\n", e->seqno); put_el(e, Tt0, Tt1); } }checklast: if (e == s->last) break; } if (0) printf("put_seq done\n");}static voidpatch_atomic(Sequence *s) /* catch goto's that break the chain */{ Element *f, *g; SeqList *h; for (f = s->frst; f ; f = f->nxt) { if (f->n && f->n->ntyp == GOTO) { g = get_lab(f->n,1); cross_dsteps(f->n, g->n); if ((f->status & (ATOM|L_ATOM)) && !(g->status & (ATOM|L_ATOM))) { f->status &= ~ATOM; f->status |= L_ATOM; } /* bridge atomics */ if ((f->status & L_ATOM) && (g->status & (ATOM|L_ATOM))) { f->status &= ~L_ATOM; f->status |= ATOM; } } else for (h = f->sub; h; h = h->nxt) patch_atomic(h->this); if (f == s->extent) break; }}static voidmark_seq(Sequence *s){ Element *f; SeqList *h; for (f = s->frst; f; f = f->nxt) { f->status |= I_GLOB; if (f->n->ntyp == ATOMIC || f->n->ntyp == NON_ATOMIC || f->n->ntyp == D_STEP) mark_seq(f->n->sl->this); for (h = f->sub; h; h = h->nxt) mark_seq(h->this); if (f == s->last) return; }}static Element *find_target(Element *e){ Element *f; if (!e) return e; if (t_cyc++ > 32) { fatal("cycle of goto jumps", (char *) 0); } switch (e->n->ntyp) { case GOTO: f = get_lab(e->n,1); cross_dsteps(e->n, f->n); f = find_target(f); break; case BREAK: if (e->nxt) f = find_target(huntele(e->nxt, e->status, -1)); /* else fall through */ default: f = e; break; } return f;}Element *target(Element *e){ if (!e) return e; lineno = e->n->ln; Fname = e->n->fn; t_cyc = 0; return find_target(e);}static intscan_seq(Sequence *s){ Element *f, *g; SeqList *h; for (f = s->frst; f; f = f->nxt) { if ((f->status&CHECK2) || has_global(f->n)) return 1; if (f->n->ntyp == GOTO) /* may reach other atomic */ { g = target(f); if (g && !(f->status & L_ATOM) && !(g->status & (ATOM|L_ATOM))) { fprintf(tt, " /* goto mark-down, "); fprintf(tt, "line %d - %d */\n", f->n->ln, (g->n)?g->n->ln:0); return 1; /* assume worst case */ } } for (h = f->sub; h; h = h->nxt) if (scan_seq(h->this)) return 1; if (f == s->last) break; } return 0;}static intglob_args(Lextok *n){ int result = 0; Lextok *v; for (v = n->rgt; v; v = v->rgt) { if (v->lft->ntyp == CONST) continue; if (v->lft->ntyp == EVAL) result += has_global(v->lft->lft); else result += has_global(v->lft); } return result;}inthas_global(Lextok *n){ Lextok *v; extern int runsafe; if (!n) return 0; if (AllGlobal) return 1; /* global provided clause */ switch (n->ntyp) { case ATOMIC: case D_STEP: case NON_ATOMIC: return scan_seq(n->sl->this); case '.': case BREAK: case GOTO: case CONST: return 0; case ELSE: return n->val; /* true if combined with chan refs */ case 's': return glob_args(n)!=0 || ((n->sym->xu&(XS|XX)) != XS); case 'r': return glob_args(n)!=0 || ((n->sym->xu&(XR|XX)) != XR); case 'R': return glob_args(n)!=0 || (((n->sym->xu)&(XR|XS|XX)) != (XR|XS)); case NEMPTY: return ((n->sym->xu&(XR|XX)) != XR); case NFULL: return ((n->sym->xu&(XS|XX)) != XS); case FULL: return ((n->sym->xu&(XR|XX)) != XR); case EMPTY: return ((n->sym->xu&(XS|XX)) != XS); case LEN: return (((n->sym->xu)&(XR|XS|XX)) != (XR|XS)); case NAME: if (n->sym->context || (n->sym->hidden&64) || strcmp(n->sym->name, "_pid") == 0 || strcmp(n->sym->name, "_") == 0) return 0; return 1; case RUN: return 1-runsafe; case C_CODE: case C_EXPR: return glob_inline(n->sym->name); case ENABLED: case PC_VAL: case NONPROGRESS: case 'p': case 'q': case TIMEOUT: return 1; /* @ was 1 (global) since 2.8.5 in 3.0 it is considered local and conditionally safe, provided: II is the youngest process and nrprocs < MAXPROCS */ case '@': return 0; case '!': case UMIN: case '~': case ASSERT: return has_global(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': case ASGN: return has_global(n->lft) || has_global(n->rgt); case PRINT: for (v = n->lft; v; v = v->rgt) if (has_global(v->lft)) return 1; return 0; case PRINTM: return has_global(n->lft); } return 0;}static voidBailout(FILE *fd, char *str){ if (!GenCode) fprintf(fd, "continue%s", str); else if (IsGuard) fprintf(fd, "%s%s", NextLab[Level], str); else fprintf(fd, "Uerror(\"block in step seq\")%s", str);}#define cat0(x) putstmnt(fd,now->lft,m); fprintf(fd, x); \ putstmnt(fd,now->rgt,m)#define cat1(x) fprintf(fd,"("); cat0(x); fprintf(fd,")")#define cat2(x,y) fprintf(fd,x); putstmnt(fd,y,m)#define cat3(x,y,z) fprintf(fd,x); putstmnt(fd,y,m); fprintf(fd,z)voidputstmnt(FILE *fd, Lextok *now, int m){ Lextok *v; int i, j; if (!now) { fprintf(fd, "0"); return; } lineno = now->ln; Fname = now->fn; switch (now->ntyp) { case CONST: fprintf(fd, "%d", now->val); break; case '!': cat3(" !(", now->lft, ")"); break; case UMIN: cat3(" -(", now->lft, ")"); break; case '~': cat3(" ~(", now->lft, ")"); break; case '/': cat1("/"); break; case '*': cat1("*"); break; case '-': cat1("-"); break; case '+': cat1("+"); break; case '%': cat1("%%"); break; case '&': cat1("&"); break; case '^': cat1("^"); break; case '|': cat1("|"); break; case LT: cat1("<"); break; case GT: cat1(">"); break; case LE: cat1("<="); break; case GE: cat1(">="); break; case NE: cat1("!="); break; case EQ: cat1("=="); break; case OR: cat1("||"); break; case AND: cat1("&&"); break; case LSHIFT: cat1("<<"); break; case RSHIFT: cat1(">>"); break; case TIMEOUT: if (separate == 2) fprintf(fd, "((tau)&1)"); else fprintf(fd, "((trpt->tau)&1)"); if (GenCode) printf("spin: line %3d, warning: 'timeout' in d_step sequence\n", lineno); /* is okay as a guard */ break; case RUN: if (claimproc && strcmp(now->sym->name, claimproc) == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -