|
|
1.1 ! root 1: #include "defs" ! 2: ! 3: /* Logical IF codes ! 4: */ ! 5: ! 6: ! 7: exif(p) ! 8: expptr p; ! 9: { ! 10: pushctl(CTLIF); ! 11: ctlstack->elselabel = newlabel(); ! 12: putif(p, ctlstack->elselabel); ! 13: } ! 14: ! 15: ! 16: ! 17: exelif(p) ! 18: expptr p; ! 19: { ! 20: if(ctlstack->ctltype == CTLIF) ! 21: { ! 22: if(ctlstack->endlabel == 0) ! 23: ctlstack->endlabel = newlabel(); ! 24: putgoto(ctlstack->endlabel); ! 25: putlabel(ctlstack->elselabel); ! 26: ctlstack->elselabel = newlabel(); ! 27: putif(p, ctlstack->elselabel); ! 28: } ! 29: ! 30: else execerr("elseif out of place", 0); ! 31: } ! 32: ! 33: ! 34: ! 35: ! 36: ! 37: exelse() ! 38: { ! 39: if(ctlstack->ctltype==CTLIF) ! 40: { ! 41: if(ctlstack->endlabel == 0) ! 42: ctlstack->endlabel = newlabel(); ! 43: putgoto( ctlstack->endlabel ); ! 44: putlabel(ctlstack->elselabel); ! 45: ctlstack->ctltype = CTLELSE; ! 46: } ! 47: ! 48: else execerr("else out of place", 0); ! 49: } ! 50: ! 51: ! 52: exendif() ! 53: { ! 54: if(ctlstack->ctltype == CTLIF) ! 55: { ! 56: putlabel(ctlstack->elselabel); ! 57: if(ctlstack->endlabel) ! 58: putlabel(ctlstack->endlabel); ! 59: popctl(); ! 60: } ! 61: else if(ctlstack->ctltype == CTLELSE) ! 62: { ! 63: putlabel(ctlstack->endlabel); ! 64: popctl(); ! 65: } ! 66: ! 67: else ! 68: execerr("endif out of place", 0); ! 69: } ! 70: ! 71: ! 72: ! 73: LOCAL pushctl(code) ! 74: int code; ! 75: { ! 76: register int i; ! 77: ! 78: if(++ctlstack >= lastctl) ! 79: many("loops or if-then-elses", 'c'); ! 80: ctlstack->ctltype = code; ! 81: for(i = 0 ; i < 4 ; ++i) ! 82: ctlstack->ctlabels[i] = 0; ! 83: ++blklevel; ! 84: } ! 85: ! 86: ! 87: LOCAL popctl() ! 88: { ! 89: if( ctlstack-- < ctls ) ! 90: fatal("control stack empty"); ! 91: --blklevel; ! 92: } ! 93: ! 94: ! 95: ! 96: LOCAL poplab() ! 97: { ! 98: register struct Labelblock *lp; ! 99: ! 100: for(lp = labeltab ; lp < highlabtab ; ++lp) ! 101: if(lp->labdefined) ! 102: { ! 103: /* mark all labels in inner blocks unreachable */ ! 104: if(lp->blklevel > blklevel) ! 105: lp->labinacc = YES; ! 106: } ! 107: else if(lp->blklevel > blklevel) ! 108: { ! 109: /* move all labels referred to in inner blocks out a level */ ! 110: lp->blklevel = blklevel; ! 111: } ! 112: } ! 113: ! 114: ! 115: ! 116: /* BRANCHING CODE ! 117: */ ! 118: ! 119: exgoto(lab) ! 120: struct Labelblock *lab; ! 121: { ! 122: putgoto(lab->labelno); ! 123: } ! 124: ! 125: ! 126: ! 127: ! 128: ! 129: ! 130: ! 131: exequals(lp, rp) ! 132: register struct Primblock *lp; ! 133: register expptr rp; ! 134: { ! 135: if(lp->tag != TPRIM) ! 136: { ! 137: err("assignment to a non-variable"); ! 138: frexpr(lp); ! 139: frexpr(rp); ! 140: } ! 141: else if(lp->namep->vclass!=CLVAR && lp->argsp) ! 142: { ! 143: if(parstate >= INEXEC) ! 144: err("statement function amid executables"); ! 145: else ! 146: mkstfunct(lp, rp); ! 147: } ! 148: else ! 149: { ! 150: if(parstate < INDATA) ! 151: enddcl(); ! 152: puteq(mklhs(lp), rp); ! 153: } ! 154: } ! 155: ! 156: ! 157: ! 158: mkstfunct(lp, rp) ! 159: struct Primblock *lp; ! 160: expptr rp; ! 161: { ! 162: register struct Primblock *p; ! 163: register struct Nameblock *np; ! 164: chainp args; ! 165: ! 166: np = lp->namep; ! 167: if(np->vclass == CLUNKNOWN) ! 168: np->vclass = CLPROC; ! 169: else ! 170: { ! 171: dclerr("redeclaration of statement function", np); ! 172: return; ! 173: } ! 174: np->vprocclass = PSTFUNCT; ! 175: np->vstg = STGSTFUNCT; ! 176: impldcl(np); ! 177: args = (lp->argsp ? lp->argsp->listp : NULL); ! 178: np->vardesc.vstfdesc = mkchain(args , rp ); ! 179: ! 180: for( ; args ; args = args->nextp) ! 181: if( (p = args->datap)->tag!=TPRIM || ! 182: p->argsp || p->fcharp || p->lcharp) ! 183: err("non-variable argument in statement function definition"); ! 184: else ! 185: { ! 186: vardcl(args->datap = p->namep); ! 187: free(p); ! 188: } ! 189: } ! 190: ! 191: ! 192: ! 193: excall(name, args, nstars, labels) ! 194: struct Hashentry *name; ! 195: struct Listblock *args; ! 196: int nstars; ! 197: struct Labelblock *labels[ ]; ! 198: { ! 199: register expptr p; ! 200: ! 201: settype(name, TYSUBR, NULL); ! 202: p = mkfunct( mkprim(name, args, NULL, NULL) ); ! 203: p->exprblock.vtype = p->exprblock.leftp->headblock.vtype = TYINT; ! 204: if(nstars > 0) ! 205: putcmgo(p, nstars, labels); ! 206: else putexpr(p); ! 207: } ! 208: ! 209: ! 210: ! 211: exstop(stop, p) ! 212: int stop; ! 213: register expptr p; ! 214: { ! 215: char *q; ! 216: int n; ! 217: struct Constblock *mkstrcon(); ! 218: ! 219: if(p) ! 220: { ! 221: if( ! ISCONST(p) ) ! 222: { ! 223: execerr("pause/stop argument must be constant", 0); ! 224: frexpr(p); ! 225: p = mkstrcon(0, 0); ! 226: } ! 227: else if( ISINT(p->constblock.vtype) ) ! 228: { ! 229: q = convic(p->constblock.const.ci); ! 230: n = strlen(q); ! 231: if(n > 0) ! 232: { ! 233: p->constblock.const.ccp = copyn(n, q); ! 234: p->constblock.vtype = TYCHAR; ! 235: p->constblock.vleng = ICON(n); ! 236: } ! 237: else ! 238: p = mkstrcon(0, 0); ! 239: } ! 240: else if(p->constblock.vtype != TYCHAR) ! 241: { ! 242: execerr("pause/stop argument must be integer or string", 0); ! 243: p = mkstrcon(0, 0); ! 244: } ! 245: } ! 246: else p = mkstrcon(0, 0); ! 247: ! 248: putexpr( call1(TYSUBR, (stop ? "s_stop" : "s_paus"), p) ); ! 249: } ! 250: ! 251: /* DO LOOP CODE */ ! 252: ! 253: #define DOINIT par[0] ! 254: #define DOLIMIT par[1] ! 255: #define DOINCR par[2] ! 256: ! 257: #define VARSTEP 0 ! 258: #define POSSTEP 1 ! 259: #define NEGSTEP 2 ! 260: ! 261: ! 262: exdo(range, spec) ! 263: int range; ! 264: chainp spec; ! 265: { ! 266: register expptr p, q; ! 267: expptr *q1; ! 268: register struct Nameblock *np; ! 269: chainp cp; ! 270: register int i; ! 271: int dotype, incsign; ! 272: struct Addrblock *dovarp, *dostgp; ! 273: expptr par[3]; ! 274: ! 275: pushctl(CTLDO); ! 276: dorange = ctlstack->dolabel = range; ! 277: np = spec->datap; ! 278: ctlstack->donamep = NULL; ! 279: if(np->vdovar) ! 280: { ! 281: errstr("nested loops with variable %s", varstr(VL,np->varname)); ! 282: ctlstack->donamep = NULL; ! 283: return; ! 284: } ! 285: ! 286: dovarp = mklhs( mkprim(np, 0,0,0) ); ! 287: if( ! ONEOF(dovarp->vtype, MSKINT|MSKREAL) ) ! 288: { ! 289: err("bad type on do variable"); ! 290: return; ! 291: } ! 292: ctlstack->donamep = np; ! 293: ! 294: np->vdovar = YES; ! 295: if( enregister(np) ) ! 296: { ! 297: /* stgp points to a storage version, varp to a register version */ ! 298: dostgp = dovarp; ! 299: dovarp = mklhs( mkprim(np, 0,0,0) ); ! 300: } ! 301: else ! 302: dostgp = NULL; ! 303: dotype = dovarp->vtype; ! 304: ! 305: for(i=0 , cp = spec->nextp ; cp!=NULL && i<3 ; cp = cp->nextp) ! 306: { ! 307: p = par[i++] = fixtype(cp->datap); ! 308: if( ! ONEOF(p->headblock.vtype, MSKINT|MSKREAL) ) ! 309: { ! 310: err("bad type on DO parameter"); ! 311: return; ! 312: } ! 313: } ! 314: ! 315: frchain(&spec); ! 316: switch(i) ! 317: { ! 318: case 0: ! 319: case 1: ! 320: err("too few DO parameters"); ! 321: return; ! 322: ! 323: default: ! 324: err("too many DO parameters"); ! 325: return; ! 326: ! 327: case 2: ! 328: DOINCR = ICON(1); ! 329: ! 330: case 3: ! 331: break; ! 332: } ! 333: ! 334: ctlstack->endlabel = newlabel(); ! 335: ctlstack->dobodylabel = newlabel(); ! 336: ! 337: if( ISCONST(DOLIMIT) ) ! 338: ctlstack->domax = mkconv(dotype, DOLIMIT); ! 339: else ! 340: ctlstack->domax = mktemp(dotype, NULL); ! 341: ! 342: if( ISCONST(DOINCR) ) ! 343: { ! 344: ctlstack->dostep = mkconv(dotype, DOINCR); ! 345: if( (incsign = conssgn(ctlstack->dostep)) == 0) ! 346: err("zero DO increment"); ! 347: ctlstack->dostepsign = (incsign > 0 ? POSSTEP : NEGSTEP); ! 348: } ! 349: else ! 350: { ! 351: ctlstack->dostep = mktemp(dotype, NULL); ! 352: ctlstack->dostepsign = VARSTEP; ! 353: ctlstack->doposlabel = newlabel(); ! 354: ctlstack->doneglabel = newlabel(); ! 355: } ! 356: ! 357: if( ISCONST(ctlstack->domax) && ISCONST(DOINIT) && ctlstack->dostepsign!=VARSTEP) ! 358: { ! 359: puteq(cpexpr(dovarp), cpexpr(DOINIT)); ! 360: if( onetripflag ) ! 361: frexpr(DOINIT); ! 362: else ! 363: { ! 364: q = mkexpr(OPPLUS, ICON(1), ! 365: mkexpr(OPMINUS, cpexpr(ctlstack->domax), cpexpr(DOINIT)) ); ! 366: if(incsign != conssgn(q)) ! 367: { ! 368: warn("DO range never executed"); ! 369: putgoto(ctlstack->endlabel); ! 370: } ! 371: frexpr(q); ! 372: } ! 373: } ! 374: else if(ctlstack->dostepsign!=VARSTEP && !onetripflag) ! 375: { ! 376: if( ISCONST(ctlstack->domax) ) ! 377: q = cpexpr(ctlstack->domax); ! 378: else ! 379: q = mkexpr(OPASSIGN, cpexpr(ctlstack->domax), DOLIMIT); ! 380: ! 381: q1 = mkexpr(OPASSIGN, cpexpr(dovarp), DOINIT); ! 382: q = mkexpr( (ctlstack->dostepsign==POSSTEP ? OPLE : OPGE), q1, q); ! 383: putif(q, ctlstack->endlabel); ! 384: } ! 385: else ! 386: { ! 387: if(! ISCONST(ctlstack->domax) ) ! 388: puteq( cpexpr(ctlstack->domax), DOLIMIT); ! 389: q = DOINIT; ! 390: if( ! onetripflag ) ! 391: q = mkexpr(OPMINUS, q, ! 392: mkexpr(OPASSIGN, cpexpr(ctlstack->dostep), DOINCR) ); ! 393: puteq( cpexpr(dovarp), q); ! 394: if(onetripflag && ctlstack->dostepsign==VARSTEP) ! 395: puteq( cpexpr(ctlstack->dostep), DOINCR); ! 396: } ! 397: ! 398: if(ctlstack->dostepsign == VARSTEP) ! 399: { ! 400: if(onetripflag) ! 401: putgoto(ctlstack->dobodylabel); ! 402: else ! 403: putif( mkexpr(OPGE, cpexpr(ctlstack->dostep), ICON(0)), ! 404: ctlstack->doneglabel ); ! 405: putlabel(ctlstack->doposlabel); ! 406: putif( mkexpr(OPLE, ! 407: mkexpr(OPPLUSEQ, cpexpr(dovarp), cpexpr(ctlstack->dostep)), ! 408: cpexpr(ctlstack->domax) ), ! 409: ctlstack->endlabel); ! 410: } ! 411: putlabel(ctlstack->dobodylabel); ! 412: if(dostgp) ! 413: puteq(dostgp, cpexpr(dovarp)); ! 414: frexpr(dovarp); ! 415: } ! 416: ! 417: ! 418: ! 419: enddo(here) ! 420: int here; ! 421: { ! 422: register struct Ctlframe *q; ! 423: register expptr t; ! 424: struct Nameblock *np; ! 425: struct Addrblock *ap; ! 426: register int i; ! 427: ! 428: while(here == dorange) ! 429: { ! 430: if(np = ctlstack->donamep) ! 431: { ! 432: t = mkexpr(OPPLUSEQ, mklhs(mkprim(ctlstack->donamep, 0,0,0)), ! 433: cpexpr(ctlstack->dostep) ); ! 434: ! 435: if(ctlstack->dostepsign == VARSTEP) ! 436: { ! 437: putif( mkexpr(OPLE, cpexpr(ctlstack->dostep), ICON(0)), ctlstack->doposlabel); ! 438: putlabel(ctlstack->doneglabel); ! 439: putif( mkexpr(OPLT, t, ctlstack->domax), ctlstack->dobodylabel); ! 440: } ! 441: else ! 442: putif( mkexpr( (ctlstack->dostepsign==POSSTEP ? OPGT : OPLT), ! 443: t, ctlstack->domax), ! 444: ctlstack->dobodylabel); ! 445: putlabel(ctlstack->endlabel); ! 446: if(ap = memversion(np)) ! 447: puteq(ap, mklhs( mkprim(np,0,0,0)) ); ! 448: for(i = 0 ; i < 4 ; ++i) ! 449: ctlstack->ctlabels[i] = 0; ! 450: deregister(ctlstack->donamep); ! 451: ctlstack->donamep->vdovar = NO; ! 452: frexpr(ctlstack->dostep); ! 453: } ! 454: ! 455: popctl(); ! 456: poplab(); ! 457: dorange = 0; ! 458: for(q = ctlstack ; q>=ctls ; --q) ! 459: if(q->ctltype == CTLDO) ! 460: { ! 461: dorange = q->dolabel; ! 462: break; ! 463: } ! 464: } ! 465: } ! 466: ! 467: exassign(vname, labelval) ! 468: struct Nameblock *vname; ! 469: struct Labelblock *labelval; ! 470: { ! 471: struct Addrblock *p; ! 472: struct Constblock *mkaddcon(); ! 473: ! 474: p = mklhs(mkprim(vname,0,0,0)); ! 475: if( ! ONEOF(p->vtype, MSKINT|MSKADDR) ) ! 476: err("noninteger assign variable"); ! 477: else ! 478: puteq(p, mkaddcon(labelval->labelno) ); ! 479: } ! 480: ! 481: ! 482: ! 483: exarif(expr, neglab, zerlab, poslab) ! 484: expptr expr; ! 485: struct Labelblock *neglab, *zerlab, *poslab; ! 486: { ! 487: register int lm, lz, lp; ! 488: ! 489: lm = neglab->labelno; ! 490: lz = zerlab->labelno; ! 491: lp = poslab->labelno; ! 492: expr = fixtype(expr); ! 493: ! 494: if( ! ONEOF(expr->headblock.vtype, MSKINT|MSKREAL) ) ! 495: { ! 496: err("invalid type of arithmetic if expression"); ! 497: frexpr(expr); ! 498: } ! 499: else ! 500: { ! 501: if(lm == lz) ! 502: exar2(OPLE, expr, lm, lp); ! 503: else if(lm == lp) ! 504: exar2(OPNE, expr, lm, lz); ! 505: else if(lz == lp) ! 506: exar2(OPGE, expr, lz, lm); ! 507: else ! 508: prarif(expr, lm, lz, lp); ! 509: } ! 510: } ! 511: ! 512: ! 513: ! 514: LOCAL exar2(op, e, l1, l2) ! 515: int op; ! 516: expptr e; ! 517: int l1, l2; ! 518: { ! 519: putif( mkexpr(op, e, ICON(0)), l2); ! 520: putgoto(l1); ! 521: } ! 522: ! 523: ! 524: exreturn(p) ! 525: register expptr p; ! 526: { ! 527: if(procclass != CLPROC) ! 528: warn("RETURN statement in main or block data"); ! 529: if(p && (proctype!=TYSUBR || procclass!=CLPROC) ) ! 530: { ! 531: err("alternate return in nonsubroutine"); ! 532: p = 0; ! 533: } ! 534: ! 535: if(p) ! 536: { ! 537: putforce(TYINT, p); ! 538: putgoto(retlabel); ! 539: } ! 540: else ! 541: putgoto(proctype==TYSUBR ? ret0label : retlabel); ! 542: } ! 543: ! 544: ! 545: ! 546: exasgoto(labvar) ! 547: struct Hashentry *labvar; ! 548: { ! 549: register struct Addrblock *p; ! 550: ! 551: p = mklhs( mkprim(labvar,0,0,0) ); ! 552: if( ! ISINT(p->vtype) ) ! 553: err("assigned goto variable must be integer"); ! 554: else ! 555: putbranch(p); ! 556: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.