exec.c
来自「把fortran语言编的程序转为c语言编的程序, 运行环境linux」· C语言 代码 · 共 927 行 · 第 1/2 页
C
927 行
dclerr("already declared; cannot be a loop name", loopname); }#endif putwhile((expptr)spec->nextp); NOEXT("do while"); spec->nextp = 0; frchain(&spec); return; } if(np->vdovar) { errstr("nested loops with variable %s", np->fvarname); ctlstack->donamep = NULL; return; }/* Create a memory-resident version of the index variable */ dovarp = mkplace(np); if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) ) { err("bad type on do variable"); return; } ctlstack->donamep = np; np->vdovar = YES;/* Now dovarp points to the index to be used within the loop, dostgp points to the one which may need to be stored */ dotype = dovarp->vtype;/* Count the input specifications and type-check each one independently; this just eliminates non-numeric values from the specification */ for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp) { p = par[i++] = fixtype((tagptr)cp->datap); if( ! ONEOF(p->headblock.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 = (expptr) ICON(1); case 3: break; }/* Now all of the local specification fields are set, but their types are not yet consistent *//* Declare the loop initialization value, casting it properly and declaring a register if need be */ if (ISCONST (DOINIT) || !onetripflag)/* putx added 6-29-89 (mwm), not sure if fixtype is required, but I doubt it since mkconv is called just before */ doinit = putx (mkconv (dotype, DOINIT)); else { doinit = (expptr) mktmp(dotype, ENULL); puteq (cpexpr (doinit), DOINIT); } /* else *//* Declare the loop ending value, casting it to the type of the index variable */ if( ISCONST(DOLIMIT) ) ctlstack->domax = mkconv(dotype, DOLIMIT); else { ctlstack->domax = (expptr) mktmp0(dotype, ENULL); puteq (cpexpr (ctlstack -> domax), DOLIMIT); } /* else *//* Declare the loop increment value, casting it to the type of the index variable */ 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 = (expptr) mktmp0(dotype, ENULL); ctlstack->dostepsign = VARSTEP; puteq (cpexpr (ctlstack -> dostep), DOINCR); }/* All data is now properly typed and in the ctlstack, except for the initial value. Assignments of temps have been generated already */ switch (ctlstack -> dostepsign) { case VARSTEP: test = mkexpr (OPQUEST, mkexpr (OPLT, cpexpr (ctlstack -> dostep), ICON(0)), mkexpr (OPCOLON, mkexpr (OPGE, cpexpr((expptr)dovarp), cpexpr (ctlstack -> domax)), mkexpr (OPLE, cpexpr((expptr)dovarp), cpexpr (ctlstack -> domax)))); break; case POSSTEP: test = mkexpr (OPLE, cpexpr((expptr)dovarp), cpexpr (ctlstack -> domax)); break; case NEGSTEP: test = mkexpr (OPGE, cpexpr((expptr)dovarp), cpexpr (ctlstack -> domax)); break; default: erri ("exdo: bad dostepsign '%d'", ctlstack -> dostepsign); break; } /* switch (ctlstack -> dostepsign) */ if (onetripflag) test = mkexpr (OPOR, test, mkexpr (OPEQ, cpexpr((expptr)dovarp), cpexpr (doinit))); init = mkexpr (OPASSIGN, cpexpr((expptr)dovarp), doinit); inc = mkexpr (OPPLUSEQ, (expptr)dovarp, cpexpr (ctlstack -> dostep)); if (!onetripflag && ISCONST (ctlstack -> domax) && ISCONST (doinit) && ctlstack -> dostepsign != VARSTEP) { expptr tester; tester = mkexpr (OPMINUS, cpexpr (doinit), cpexpr (ctlstack -> domax)); if (incsign == conssgn (tester)) warn ("DO range never executed"); frexpr (tester); } /* if !onetripflag && */ p1_for (init, test, inc);} void#ifdef KR_headersexenddo(np) Namep np;#elseexenddo(Namep np)#endif{ Namep np1; int here; struct Ctlframe *cf; if( ctlstack < ctls ) goto misplaced; here = ctlstack->dolabel; if (ctlstack->ctltype != CTLDO || here >= 0 && (!thislabel || thislabel->labelno != here)) { misplaced: err("misplaced ENDDO"); return; } if (np != ctlstack->loopname) { if (np1 = ctlstack->loopname) errstr("expected \"enddo %s\"", np1->fvarname); else err("expected unnamed ENDDO"); for(cf = ctls; cf < ctlstack; cf++) if (cf->ctltype == CTLDO && cf->loopname == np) { here = cf->dolabel; break; } } enddo(here); } void#ifdef KR_headersenddo(here) int here;#elseenddo(int here)#endif{ register struct Ctlframe *q; Namep np; /* name of the current DO index */ Addrp ap; register int i; register expptr e;/* Many DO's can end at the same statement, so keep looping over all nested indicies */ while(here == dorange) { if(np = ctlstack->donamep) { p1for_end ();/* Now we're done with all of the tests, and the loop has terminated. Store the index value back in long-term memory */ if(ap = memversion(np)) puteq((expptr)ap, (expptr)mkplace(np)); for(i = 0 ; i < 4 ; ++i) ctlstack->ctlabels[i] = 0; deregister(ctlstack->donamep); ctlstack->donamep->vdovar = NO; /* ctlstack->dostep and ctlstack->domax can be zero */ /* with sufficiently bizarre (erroneous) syntax */ if (e = ctlstack->dostep) if (e->tag == TADDR && e->addrblock.istemp) frtemp((Addrp)e); else frexpr(e); if (e = ctlstack->domax) if (e->tag == TADDR && e->addrblock.istemp) frtemp((Addrp)e); else frexpr(e); } else if (ctlstack->dowhile) p1for_end ();/* Set dorange to the closing label of the next most enclosing DO loop */ popctl(); poplab(); dorange = 0; for(q = ctlstack ; q>=ctls ; --q) if(q->ctltype == CTLDO) { dorange = q->dolabel; break; } }} void#ifdef KR_headersexassign(vname, labelval) register Namep vname; struct Labelblock *labelval;#elseexassign(register Namep vname, struct Labelblock *labelval)#endif{ Addrp p; register Addrp q; char *fs; register chainp cp, cpprev; register ftnint k, stno; p = mkplace(vname); if( ! ONEOF(p->vtype, MSKINT|MSKADDR) ) { err("noninteger assign variable"); return; } /* If the label hasn't been defined, then we do things twice: * once for an executable stmt label, once for a format */ /* code for executable label... *//* Now store the assigned value in a list associated with this variable. This will be used later to generate a switch() statement in the C output */ fs = labelval->fmtstring; if (!labelval->labdefined || !fs) { if (vname -> vis_assigned == 0) { vname -> varxptr.assigned_values = CHNULL; vname -> vis_assigned = 1; } /* don't duplicate labels... */ stno = labelval->stateno; cpprev = 0; for(k = 0, cp = vname->varxptr.assigned_values; cp; cpprev = cp, cp = cp->nextp, k++) if ((ftnint)cp->datap == stno) break; if (!cp) { cp = mkchain((char *)stno, CHNULL); if (cpprev) cpprev->nextp = cp; else vname->varxptr.assigned_values = cp; labelval->labused = 1; } putout(mkexpr(OPASSIGN, (expptr)p, mkintcon(k))); } /* Code for FORMAT label... */ if (!labelval->labdefined || fs) { labelval->fmtlabused = 1; p = ALLOC(Addrblock); p->tag = TADDR; p->vtype = TYCHAR; p->vstg = STGAUTO; p->memoffset = ICON(0); fmtname(vname, p); q = ALLOC(Addrblock); q->tag = TADDR; q->vtype = TYCHAR; q->vstg = STGAUTO; q->ntempelt = 1; q->memoffset = ICON(0); q->uname_tag = UNAM_IDENT; sprintf(q->user.ident, "fmt_%ld", labelval->stateno); putout(mkexpr(OPASSIGN, (expptr)p, (expptr)q)); }} /* exassign */ void#ifdef KR_headersexarif(expr, neglab, zerlab, poslab) expptr expr; struct Labelblock *neglab; struct Labelblock *zerlab; struct Labelblock *poslab;#elseexarif(expptr expr, struct Labelblock *neglab, struct Labelblock *zerlab, struct Labelblock *poslab)#endif{ register int lm, lz, lp; lm = neglab->stateno; lz = zerlab->stateno; lp = poslab->stateno; expr = fixtype(expr); if( ! ONEOF(expr->headblock.vtype, MSKINT|MSKREAL) ) { err("invalid type of arithmetic if expression"); frexpr(expr); } else { if (lm == lz && lz == lp) exgoto (neglab); else if(lm == lz) exar2(OPLE, expr, neglab, poslab); else if(lm == lp) exar2(OPNE, expr, neglab, zerlab); else if(lz == lp) exar2(OPGE, expr, zerlab, neglab); else { expptr t; if (!addressable (expr)) { t = (expptr) mktmp(expr -> headblock.vtype, ENULL); expr = mkexpr (OPASSIGN, cpexpr (t), expr); } else t = (expptr) cpexpr (expr); p1_if(putx(fixtype(mkexpr (OPLT, expr, ICON (0))))); exgoto(neglab); p1_elif (mkexpr (OPEQ, t, ICON (0))); exgoto(zerlab); p1_else (); exgoto(poslab); p1else_end (); } /* else */ }}/* exar2 -- Do arithmetic IF for only 2 distinct labels; if !(e.op.0) goto l2 else goto l1. If this seems backwards, that's because it is, in order to make the 1 pass algorithm work. */ LOCAL void#ifdef KR_headersexar2(op, e, l1, l2) int op; expptr e; struct Labelblock *l1; struct Labelblock *l2;#elseexar2(int op, expptr e, struct Labelblock *l1, struct Labelblock *l2)#endif{ expptr comp; comp = mkexpr (op, e, ICON (0)); p1_if(putx(fixtype(comp))); exgoto(l1); p1_else (); exgoto(l2); p1else_end ();}/* exreturn -- return the value in p from a SUBROUTINE call -- used to implement the alternate return mechanism */ void#ifdef KR_headersexreturn(p) register expptr p;#elseexreturn(register expptr p)#endif{ 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 || proctype == TYSUBR) { if (p == ENULL) p = ICON (0); p = mkconv (TYLONG, fixtype (p)); p1_subr_ret (p); } /* if p || proctype == TYSUBR */ else p1_subr_ret((expptr)retslot);} void#ifdef KR_headersexasgoto(labvar) Namep labvar;#elseexasgoto(Namep labvar)#endif{ register Addrp p; p = mkplace(labvar); if( ! ISINT(p->vtype) ) err("assigned goto variable must be integer"); else { p1_asgoto (p); } /* else */}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?