📄 exec.c
字号:
#include "defs"/* Logical IF codes*/exif(p)expptr p;{pushctl(CTLIF);ctlstack->elselabel = newlabel();putif(p, ctlstack->elselabel);}exelif(p)expptr p;{if(ctlstack->ctltype == CTLIF) { if(ctlstack->endlabel == 0) ctlstack->endlabel = newlabel(); putgoto(ctlstack->endlabel); putlabel(ctlstack->elselabel); ctlstack->elselabel = newlabel(); putif(p, ctlstack->elselabel); }else execerr("elseif out of place", 0);}exelse(){if(ctlstack->ctltype==CTLIF) { if(ctlstack->endlabel == 0) ctlstack->endlabel = newlabel(); putgoto( ctlstack->endlabel ); putlabel(ctlstack->elselabel); ctlstack->ctltype = CTLELSE; }else execerr("else out of place", 0);}exendif(){if(ctlstack->ctltype == CTLIF) { putlabel(ctlstack->elselabel); if(ctlstack->endlabel) putlabel(ctlstack->endlabel); popctl(); }else if(ctlstack->ctltype == CTLELSE) { putlabel(ctlstack->endlabel); popctl(); }else execerr("endif out of place", 0);}LOCAL pushctl(code)int code;{register int i;if(++ctlstack >= lastctl) fatal("nesting too deep");ctlstack->ctltype = code;for(i = 0 ; i < 4 ; ++i) ctlstack->ctlabels[i] = 0;++blklevel;}LOCAL popctl(){if( ctlstack-- < ctls ) fatal("control stack empty");--blklevel;}LOCAL poplab(){register struct labelblock *lp;for(lp = labeltab ; lp < highlabtab ; ++lp) if(lp->labdefined) { /* mark all labels in inner blocks unreachable */ if(lp->blklevel > blklevel) lp->labinacc = YES; } else if(lp->blklevel > blklevel) { /* move all labels referred to in inner blocks out a level */ lp->blklevel = blklevel; }}/* BRANCHING CODE*/exgoto(lab)struct labelblock *lab;{putgoto(lab->labelno);}exequals(lp, rp)register struct primblock *lp;register expptr rp;{if(lp->tag != TPRIM) { err("assignment to a non-variable"); frexpr(lp); frexpr(rp); }else if(lp->namep->vclass!=CLVAR && lp->argsp) { if(parstate >= INEXEC) err("statement function amid executables"); else mkstfunct(lp, rp); }else { if(parstate < INDATA) enddcl(); puteq(mklhs(lp), rp); }}mkstfunct(lp, rp)struct primblock *lp;expptr rp;{register struct primblock *p;register struct nameblock *np;chainp args;np = lp->namep;if(np->vclass == CLUNKNOWN) np->vclass = CLPROC;else { dclerr("redeclaration of statement function", np); return; }np->vprocclass = PSTFUNCT;np->vstg = STGSTFUNCT;impldcl(np);args = (lp->argsp ? lp->argsp->listp : NULL);np->vardesc.vstfdesc = mkchain(args , rp );for( ; args ; args = args->nextp) if( (p = args->datap)->tag!=TPRIM || p->argsp || p->fcharp || p->lcharp) err("non-variable argument in statement function definition"); else { vardcl(args->datap = p->namep); free(p); }}excall(name, args, nstars, labels)struct hashentry *name;struct listblock *args;int nstars;struct labelblock *labels[ ];{register expptr p;settype(name, TYSUBR, NULL);p = mkfunct( mkprim(name, args, NULL, NULL) );p->vtype = p->leftp->vtype = TYINT;if(nstars > 0) putcmgo(p, nstars, labels);else putexpr(p);}exstop(stop, p)int stop;register expptr p;{char *q;int n;struct constblock *mkstrcon();if(p) { if( ! ISCONST(p) ) { execerr("pause/stop argument must be constant", 0); frexpr(p); p = mkstrcon(0, 0); } else if( ISINT(p->vtype) ) { q = convic(p->const.ci); n = strlen(q); if(n > 0) { p->const.ccp = copyn(n, q); p->vtype = TYCHAR; p->vleng = ICON(n); } else p = mkstrcon(0, 0); } else if(p->vtype != TYCHAR) { execerr("pause/stop argument must be integer or string", 0); p = mkstrcon(0, 0); } }else p = mkstrcon(0, 0);putexpr( call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p) );}/* DO LOOP CODE */#define DOINIT par[0]#define DOLIMIT par[1]#define DOINCR par[2]#define VARSTEP 0#define POSSTEP 1#define NEGSTEP 2exdo(range, spec)int range;chainp spec;{register expptr p, q;expptr *q1;register struct nameblock *np;chainp cp;register int i;int dotype, incsign;struct addrblock *dovarp, *dostgp;expptr par[3];pushctl(CTLDO);dorange = ctlstack->dolabel = range;np = spec->datap;ctlstack->donamep = NULL;if(np->vdovar) { err1("nested loops with variable %s", varstr(VL,np->varname)); ctlstack->donamep = NULL; return; }dovarp = mklhs( mkprim(np, 0,0,0) );if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) ) { err("bad type on do variable"); return; }ctlstack->donamep = np;np->vdovar = YES;if( enregister(np) ) { /* stgp points to a storage version, varp to a register version */ dostgp = dovarp; dovarp = mklhs( mkprim(np, 0,0,0) ); }else dostgp = NULL;dotype = dovarp->vtype;for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp) { p = par[i++] = fixtype(cp->datap); if( ! ONEOF(p->vtype, MSKINT|MSKREAL) ) { err("bad type on DO parameter"); return; } }frchain(&spec);switch(i) { case 0: case 1: err("too few DO parameters"); return; default: err("too many DO parameters"); return; case 2: DOINCR = ICON(1); case 3: break; }ctlstack->endlabel = newlabel();ctlstack->dobodylabel = newlabel();if( ISCONST(DOLIMIT) ) ctlstack->domax = mkconv(dotype, DOLIMIT);else ctlstack->domax = mktemp(dotype, NULL);if( ISCONST(DOINCR) ) { ctlstack->dostep = mkconv(dotype, DOINCR); if( (incsign = conssgn(ctlstack->dostep)) == 0) err("zero DO increment"); ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP); }else { ctlstack->dostep = mktemp(dotype, NULL); ctlstack->dostepsign = VARSTEP; ctlstack->doposlabel = newlabel(); ctlstack->doneglabel = newlabel(); }if( ISCONST(ctlstack->domax) && ISCONST(DOINIT) && ctlstack->dostepsign!=VARSTEP) { puteq(cpexpr(dovarp), cpexpr(DOINIT)); if( onetripflag ) frexpr(DOINIT); else { q = mkexpr(OPPLUS, ICON(1), mkexpr(OPMINUS, cpexpr(ctlstack->domax), cpexpr(DOINIT)) ); if(incsign != conssgn(q)) { warn("DO range never executed"); putgoto(ctlstack->endlabel); } frexpr(q); } }else if(ctlstack->dostepsign!=VARSTEP && !onetripflag) { if( ISCONST(ctlstack->domax) ) q = cpexpr(ctlstack->domax); else q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT); q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT); q = mkexpr( (ctlstack->dostepsign==POSSTEP ? OPLE : OPGE), q1, q); putif(q, ctlstack->endlabel); }else { if(! ISCONST(ctlstack->domax) ) puteq( cpexpr(ctlstack->domax), DOLIMIT); q = DOINIT; if( ! onetripflag ) q = mkexpr(OPMINUS, q, mkexpr(OPASSIGN, cpexpr(ctlstack->dostep), DOINCR) ); puteq( cpexpr(dovarp), q); if(onetripflag && ctlstack->dostepsign==VARSTEP) puteq( cpexpr(ctlstack->dostep), DOINCR); }if(ctlstack->dostepsign == VARSTEP) { if(onetripflag) putgoto(ctlstack->dobodylabel); else putif( mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)), ctlstack->doneglabel ); putlabel(ctlstack->doposlabel); putif( mkexpr(OPLE, mkexpr(OPPLUSEQ, cpexpr(dovarp), cpexpr(ctlstack->dostep)), cpexpr(ctlstack->domax) ), ctlstack->endlabel); }putlabel(ctlstack->dobodylabel);if(dostgp) puteq(dostgp, cpexpr(dovarp));frexpr(dovarp);}enddo(here)int here;{register struct ctlframe *q;register expptr t;struct nameblock *np;struct addrblock *ap;register int i;while(here == dorange) { if(np = ctlstack->donamep) { t = mkexpr(OPPLUSEQ, mklhs(mkprim(ctlstack->donamep, 0,0,0)), cpexpr(ctlstack->dostep) ); if(ctlstack->dostepsign == VARSTEP) { putif( mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)), ctlstack->doposlabel); putlabel(ctlstack->doneglabel); putif( mkexpr(OPLT, t, ctlstack->domax), ctlstack->dobodylabel); } else putif( mkexpr( (ctlstack->dostepsign==POSSTEP ? OPGT : OPLT), t, ctlstack->domax), ctlstack->dobodylabel); putlabel(ctlstack->endlabel); if(ap = memversion(np)) puteq(ap, mklhs( mkprim(np,0,0,0)) ); for(i = 0 ; i < 4 ; ++i) ctlstack->ctlabels[i] = 0; deregister(ctlstack->donamep); ctlstack->donamep->vdovar = NO; frexpr(ctlstack->dostep); } popctl(); poplab(); dorange = 0; for(q = ctlstack ; q>=ctls ; --q) if(q->ctltype == CTLDO) { dorange = q->dolabel; break; } }}exassign(vname, labelval)struct nameblock *vname;struct labelblock *labelval;{struct addrblock *p;struct constblock *mkaddcon();p = mklhs(mkprim(vname,0,0,0));if( ! ONEOF(p->vtype, MSKINT|MSKADDR) ) err("noninteger assign variable");else puteq(p, mkaddcon(labelval->labelno) );}exarif(expr, neglab, zerlab, poslab)expptr expr;struct labelblock *neglab, *zerlab, *poslab;{register int lm, lz, lp;lm = neglab->labelno;lz = zerlab->labelno;lp = poslab->labelno;expr = fixtype(expr);if( ! ONEOF(expr->vtype, MSKINT|MSKREAL) ) { err("invalid type of arithmetic if expression"); frexpr(expr); }else { if(lm == lz) exar2(OPLE, expr, lm, lp); else if(lm == lp) exar2(OPNE, expr, lm, lz); else if(lz == lp) exar2(OPGE, expr, lz, lm); else prarif(expr, lm, lz, lp); }}LOCAL exar2(op, e, l1, l2)int op;expptr e;int l1, l2;{putif( mkexpr(op, e, ICON(0)), l2);putgoto(l1);}exreturn(p)register expptr p;{if(procclass != CLPROC) warn("RETURN statement in main or block data");if(p && (proctype!=TYSUBR || procclass!=CLPROC) ) { err("alternate return in nonsubroutine"); p = 0; }if(p) { putforce(TYINT, p); putgoto(retlabel); }else putgoto(proctype==TYSUBR ? ret0label : retlabel);}exasgoto(labvar)struct hashentry *labvar;{register struct addrblock *p;p = mklhs( mkprim(labvar,0,0,0) );if( ! ISINT(p->vtype) ) err("assigned goto variable must be integer");else putbranch(p);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -