|
|
1.1 ! root 1: #include "defs" ! 2: ! 3: /* little routines to create constant blocks */ ! 4: ! 5: Constp mkconst(t) ! 6: register int t; ! 7: { ! 8: register Constp p; ! 9: ! 10: p = ALLOC(Constblock); ! 11: p->tag = TCONST; ! 12: p->vtype = t; ! 13: return(p); ! 14: } ! 15: ! 16: ! 17: expptr mklogcon(l) ! 18: register int l; ! 19: { ! 20: register Constp p; ! 21: ! 22: p = mkconst(TYLOGICAL); ! 23: p->const.ci = l; ! 24: return( (expptr) p ); ! 25: } ! 26: ! 27: ! 28: ! 29: expptr mkintcon(l) ! 30: ftnint l; ! 31: { ! 32: register Constp p; ! 33: ! 34: p = mkconst(TYLONG); ! 35: p->const.ci = l; ! 36: #ifdef MAXSHORT ! 37: if(l >= -MAXSHORT && l <= MAXSHORT) ! 38: p->vtype = TYSHORT; ! 39: #endif ! 40: return( (expptr) p ); ! 41: } ! 42: ! 43: ! 44: ! 45: expptr mkaddcon(l) ! 46: register int l; ! 47: { ! 48: register Constp p; ! 49: ! 50: p = mkconst(TYADDR); ! 51: p->const.ci = l; ! 52: return( (expptr) p ); ! 53: } ! 54: ! 55: ! 56: ! 57: expptr mkrealcon(t, d) ! 58: register int t; ! 59: double d; ! 60: { ! 61: register Constp p; ! 62: ! 63: p = mkconst(t); ! 64: p->const.cd[0] = d; ! 65: return( (expptr) p ); ! 66: } ! 67: ! 68: ! 69: expptr mkbitcon(shift, leng, s) ! 70: int shift; ! 71: int leng; ! 72: char *s; ! 73: { ! 74: register Constp p; ! 75: ! 76: p = mkconst(TYUNKNOWN); ! 77: p->const.ci = 0; ! 78: while(--leng >= 0) ! 79: if(*s != ' ') ! 80: p->const.ci = (p->const.ci << shift) | hextoi(*s++); ! 81: return( (expptr) p ); ! 82: } ! 83: ! 84: ! 85: ! 86: ! 87: ! 88: expptr mkstrcon(l,v) ! 89: int l; ! 90: register char *v; ! 91: { ! 92: register Constp p; ! 93: register char *s; ! 94: ! 95: p = mkconst(TYCHAR); ! 96: p->vleng = ICON(l); ! 97: p->const.ccp = s = (char *) ckalloc(l); ! 98: while(--l >= 0) ! 99: *s++ = *v++; ! 100: return( (expptr) p ); ! 101: } ! 102: ! 103: ! 104: expptr mkcxcon(realp,imagp) ! 105: register expptr realp, imagp; ! 106: { ! 107: int rtype, itype; ! 108: register Constp p; ! 109: expptr errnode(); ! 110: ! 111: rtype = realp->headblock.vtype; ! 112: itype = imagp->headblock.vtype; ! 113: ! 114: if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) ) ! 115: { ! 116: p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX); ! 117: if( ISINT(rtype) ) ! 118: p->const.cd[0] = realp->constblock.const.ci; ! 119: else p->const.cd[0] = realp->constblock.const.cd[0]; ! 120: if( ISINT(itype) ) ! 121: p->const.cd[1] = imagp->constblock.const.ci; ! 122: else p->const.cd[1] = imagp->constblock.const.cd[0]; ! 123: } ! 124: else ! 125: { ! 126: err("invalid complex constant"); ! 127: p = (Constp)errnode(); ! 128: } ! 129: ! 130: frexpr(realp); ! 131: frexpr(imagp); ! 132: return( (expptr) p ); ! 133: } ! 134: ! 135: ! 136: expptr errnode() ! 137: { ! 138: struct Errorblock *p; ! 139: p = ALLOC(Errorblock); ! 140: p->tag = TERROR; ! 141: p->vtype = TYERROR; ! 142: return( (expptr) p ); ! 143: } ! 144: ! 145: ! 146: ! 147: ! 148: ! 149: expptr mkconv(t, p) ! 150: register int t; ! 151: register expptr p; ! 152: { ! 153: register expptr q; ! 154: register int pt; ! 155: expptr opconv(); ! 156: ! 157: if(t==TYUNKNOWN || t==TYERROR) ! 158: badtype("mkconv", t); ! 159: pt = p->headblock.vtype; ! 160: if(t == pt) ! 161: return(p); ! 162: ! 163: else if( ISCONST(p) && pt!=TYADDR) ! 164: { ! 165: q = (expptr) mkconst(t); ! 166: consconv(t, &(q->constblock.const), ! 167: p->constblock.vtype, &(p->constblock.const) ); ! 168: frexpr(p); ! 169: } ! 170: #if TARGET == PDP11 ! 171: else if(ISINT(t) && pt==TYCHAR) ! 172: { ! 173: q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255)); ! 174: if(t == TYLONG) ! 175: q = opconv(q, TYLONG); ! 176: } ! 177: #endif ! 178: else ! 179: q = opconv(p, t); ! 180: ! 181: if(t == TYCHAR) ! 182: q->constblock.vleng = ICON(1); ! 183: return(q); ! 184: } ! 185: ! 186: ! 187: ! 188: expptr opconv(p, t) ! 189: expptr p; ! 190: int t; ! 191: { ! 192: register expptr q; ! 193: ! 194: q = mkexpr(OPCONV, p, PNULL); ! 195: q->headblock.vtype = t; ! 196: return(q); ! 197: } ! 198: ! 199: ! 200: ! 201: expptr addrof(p) ! 202: expptr p; ! 203: { ! 204: return( mkexpr(OPADDR, p, PNULL) ); ! 205: } ! 206: ! 207: ! 208: ! 209: tagptr cpexpr(p) ! 210: register tagptr p; ! 211: { ! 212: register tagptr e; ! 213: int tag; ! 214: register chainp ep, pp; ! 215: tagptr cpblock(); ! 216: ! 217: static int blksize[ ] = ! 218: { 0, ! 219: sizeof(struct Nameblock), ! 220: sizeof(struct Constblock), ! 221: sizeof(struct Exprblock), ! 222: sizeof(struct Addrblock), ! 223: sizeof(struct Primblock), ! 224: sizeof(struct Listblock), ! 225: sizeof(struct Errorblock) ! 226: }; ! 227: ! 228: if(p == NULL) ! 229: return(NULL); ! 230: ! 231: if( (tag = p->tag) == TNAME) ! 232: return(p); ! 233: ! 234: e = cpblock( blksize[p->tag] , p); ! 235: ! 236: switch(tag) ! 237: { ! 238: case TCONST: ! 239: if(e->constblock.vtype == TYCHAR) ! 240: { ! 241: e->constblock.const.ccp = ! 242: copyn(1+strlen(e->constblock.const.ccp), ! 243: e->constblock.const.ccp); ! 244: e->constblock.vleng = ! 245: (expptr) cpexpr(e->constblock.vleng); ! 246: } ! 247: case TERROR: ! 248: break; ! 249: ! 250: case TEXPR: ! 251: e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp); ! 252: e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp); ! 253: break; ! 254: ! 255: case TLIST: ! 256: if(pp = p->listblock.listp) ! 257: { ! 258: ep = e->listblock.listp = ! 259: mkchain( cpexpr(pp->datap), CHNULL); ! 260: for(pp = pp->nextp ; pp ; pp = pp->nextp) ! 261: ep = ep->nextp = ! 262: mkchain( cpexpr(pp->datap), CHNULL); ! 263: } ! 264: break; ! 265: ! 266: case TADDR: ! 267: e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng); ! 268: e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset); ! 269: e->addrblock.istemp = NO; ! 270: break; ! 271: ! 272: case TPRIM: ! 273: e->primblock.argsp = (struct Listblock *) ! 274: cpexpr(e->primblock.argsp); ! 275: e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp); ! 276: e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp); ! 277: break; ! 278: ! 279: default: ! 280: badtag("cpexpr", tag); ! 281: } ! 282: ! 283: return(e); ! 284: } ! 285: ! 286: frexpr(p) ! 287: register tagptr p; ! 288: { ! 289: register chainp q; ! 290: ! 291: if(p == NULL) ! 292: return; ! 293: ! 294: switch(p->tag) ! 295: { ! 296: case TCONST: ! 297: if( ISCHAR(p) ) ! 298: { ! 299: free( (charptr) (p->constblock.const.ccp) ); ! 300: frexpr(p->constblock.vleng); ! 301: } ! 302: break; ! 303: ! 304: case TADDR: ! 305: if(p->addrblock.istemp) ! 306: { ! 307: frtemp(p); ! 308: return; ! 309: } ! 310: frexpr(p->addrblock.vleng); ! 311: frexpr(p->addrblock.memoffset); ! 312: break; ! 313: ! 314: case TERROR: ! 315: break; ! 316: ! 317: case TNAME: ! 318: return; ! 319: ! 320: case TPRIM: ! 321: frexpr(p->primblock.argsp); ! 322: frexpr(p->primblock.fcharp); ! 323: frexpr(p->primblock.lcharp); ! 324: break; ! 325: ! 326: case TEXPR: ! 327: frexpr(p->exprblock.leftp); ! 328: if(p->exprblock.rightp) ! 329: frexpr(p->exprblock.rightp); ! 330: break; ! 331: ! 332: case TLIST: ! 333: for(q = p->listblock.listp ; q ; q = q->nextp) ! 334: frexpr(q->datap); ! 335: frchain( &(p->listblock.listp) ); ! 336: break; ! 337: ! 338: default: ! 339: badtag("frexpr", p->tag); ! 340: } ! 341: ! 342: free( (charptr) p ); ! 343: } ! 344: ! 345: /* fix up types in expression; replace subtrees and convert ! 346: names to address blocks */ ! 347: ! 348: expptr fixtype(p) ! 349: register tagptr p; ! 350: { ! 351: ! 352: if(p == 0) ! 353: return(0); ! 354: ! 355: switch(p->tag) ! 356: { ! 357: case TCONST: ! 358: if(ONEOF(p->constblock.vtype,MSKINT|MSKLOGICAL|MSKADDR) ) ! 359: return( (expptr) p); ! 360: #if TARGET == VAX ! 361: if(ONEOF(p->constblock.vtype,MSKREAL) && ! 362: p->constblock.const.cd[0]==0) ! 363: return( (expptr) p); ! 364: #endif ! 365: return( (expptr) putconst(p) ); ! 366: ! 367: case TADDR: ! 368: p->addrblock.memoffset = fixtype(p->addrblock.memoffset); ! 369: return( (expptr) p); ! 370: ! 371: case TERROR: ! 372: return( (expptr) p); ! 373: ! 374: default: ! 375: badtag("fixtype", p->tag); ! 376: ! 377: case TEXPR: ! 378: return( fixexpr(p) ); ! 379: ! 380: case TLIST: ! 381: return( (expptr) p ); ! 382: ! 383: case TPRIM: ! 384: if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR) ! 385: { ! 386: if(p->primblock.namep->vtype == TYSUBR) ! 387: { ! 388: err("function invocation of subroutine"); ! 389: return( errnode() ); ! 390: } ! 391: else ! 392: return( mkfunct(p) ); ! 393: } ! 394: else return( mklhs(p) ); ! 395: } ! 396: } ! 397: ! 398: ! 399: ! 400: ! 401: ! 402: /* special case tree transformations and cleanups of expression trees */ ! 403: ! 404: expptr fixexpr(p) ! 405: register Exprp p; ! 406: { ! 407: expptr lp; ! 408: register expptr rp; ! 409: register expptr q; ! 410: int opcode, ltype, rtype, ptype, mtype; ! 411: expptr mkpower(); ! 412: ! 413: if( ISERROR(p) ) ! 414: return( (expptr) p ); ! 415: else if(p->tag != TEXPR) ! 416: badtag("fixexpr", p->tag); ! 417: opcode = p->opcode; ! 418: lp = p->leftp = fixtype(p->leftp); ! 419: ltype = lp->headblock.vtype; ! 420: if(opcode==OPASSIGN && lp->tag!=TADDR) ! 421: { ! 422: err("left side of assignment must be variable"); ! 423: frexpr(p); ! 424: return( errnode() ); ! 425: } ! 426: ! 427: if(p->rightp) ! 428: { ! 429: rp = p->rightp = fixtype(p->rightp); ! 430: rtype = rp->headblock.vtype; ! 431: } ! 432: else ! 433: { ! 434: rp = NULL; ! 435: rtype = 0; ! 436: } ! 437: ! 438: if(ltype==TYERROR || rtype==TYERROR) ! 439: { ! 440: frexpr(p); ! 441: return( errnode() ); ! 442: } ! 443: ! 444: /* force folding if possible */ ! 445: if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) ) ! 446: { ! 447: q = mkexpr(opcode, lp, rp); ! 448: if( ISCONST(q) ) ! 449: return(q); ! 450: free( (charptr) q ); /* constants did not fold */ ! 451: } ! 452: ! 453: if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR) ! 454: { ! 455: frexpr(p); ! 456: return( errnode() ); ! 457: } ! 458: ! 459: switch(opcode) ! 460: { ! 461: case OPCONCAT: ! 462: if(p->vleng == NULL) ! 463: p->vleng = mkexpr(OPPLUS, ! 464: cpexpr(lp->headblock.vleng), ! 465: cpexpr(rp->headblock.vleng) ); ! 466: break; ! 467: ! 468: case OPASSIGN: ! 469: case OPPLUSEQ: ! 470: case OPSTAREQ: ! 471: if(ltype == rtype) ! 472: break; ! 473: if( ! ISCONST(rp) && ISREAL(ltype) && ISREAL(rtype) ) ! 474: break; ! 475: if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) ) ! 476: break; ! 477: if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT) ! 478: #if FAMILY==PCC ! 479: && typesize[ltype]>=typesize[rtype] ) ! 480: #else ! 481: && typesize[ltype]==typesize[rtype] ) ! 482: #endif ! 483: break; ! 484: p->rightp = fixtype( mkconv(ptype, rp) ); ! 485: break; ! 486: ! 487: case OPSLASH: ! 488: if( ISCOMPLEX(rtype) ) ! 489: { ! 490: p = (Exprp) call2(ptype, ! 491: ptype==TYCOMPLEX? "c_div" : "z_div", ! 492: mkconv(ptype, lp), mkconv(ptype, rp) ); ! 493: break; ! 494: } ! 495: case OPPLUS: ! 496: case OPMINUS: ! 497: case OPSTAR: ! 498: case OPMOD: ! 499: if(ptype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp) ) || ! 500: (rtype==TYREAL && ! ISCONST(rp) ) )) ! 501: break; ! 502: if( ISCOMPLEX(ptype) ) ! 503: break; ! 504: if(ltype != ptype) ! 505: p->leftp = fixtype(mkconv(ptype,lp)); ! 506: if(rtype != ptype) ! 507: p->rightp = fixtype(mkconv(ptype,rp)); ! 508: break; ! 509: ! 510: case OPPOWER: ! 511: return( mkpower(p) ); ! 512: ! 513: case OPLT: ! 514: case OPLE: ! 515: case OPGT: ! 516: case OPGE: ! 517: case OPEQ: ! 518: case OPNE: ! 519: if(ltype == rtype) ! 520: break; ! 521: mtype = cktype(OPMINUS, ltype, rtype); ! 522: if(mtype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp)) || ! 523: (rtype==TYREAL && ! ISCONST(rp)) )) ! 524: break; ! 525: if( ISCOMPLEX(mtype) ) ! 526: break; ! 527: if(ltype != mtype) ! 528: p->leftp = fixtype(mkconv(mtype,lp)); ! 529: if(rtype != mtype) ! 530: p->rightp = fixtype(mkconv(mtype,rp)); ! 531: break; ! 532: ! 533: ! 534: case OPCONV: ! 535: ptype = cktype(OPCONV, p->vtype, ltype); ! 536: if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA) ! 537: { ! 538: lp->exprblock.rightp = ! 539: fixtype( mkconv(ptype, lp->exprblock.rightp) ); ! 540: free( (charptr) p ); ! 541: p = (Exprp) lp; ! 542: } ! 543: break; ! 544: ! 545: case OPADDR: ! 546: if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR) ! 547: fatal("addr of addr"); ! 548: break; ! 549: ! 550: case OPCOMMA: ! 551: case OPQUEST: ! 552: case OPCOLON: ! 553: break; ! 554: ! 555: case OPMIN: ! 556: case OPMAX: ! 557: ptype = p->vtype; ! 558: break; ! 559: ! 560: default: ! 561: break; ! 562: } ! 563: ! 564: p->vtype = ptype; ! 565: return((expptr) p); ! 566: } ! 567: ! 568: #if SZINT < SZLONG ! 569: /* ! 570: for efficient subscripting, replace long ints by shorts ! 571: in easy places ! 572: */ ! 573: ! 574: expptr shorten(p) ! 575: register expptr p; ! 576: { ! 577: register expptr q; ! 578: ! 579: if(p->headblock.vtype != TYLONG) ! 580: return(p); ! 581: ! 582: switch(p->tag) ! 583: { ! 584: case TERROR: ! 585: case TLIST: ! 586: return(p); ! 587: ! 588: case TCONST: ! 589: case TADDR: ! 590: return( mkconv(TYINT,p) ); ! 591: ! 592: case TEXPR: ! 593: break; ! 594: ! 595: default: ! 596: badtag("shorten", p->tag); ! 597: } ! 598: ! 599: switch(p->exprblock.opcode) ! 600: { ! 601: case OPPLUS: ! 602: case OPMINUS: ! 603: case OPSTAR: ! 604: q = shorten( cpexpr(p->exprblock.rightp) ); ! 605: if(q->headblock.vtype == TYINT) ! 606: { ! 607: p->exprblock.leftp = shorten(p->exprblock.leftp); ! 608: if(p->exprblock.leftp->headblock.vtype == TYLONG) ! 609: frexpr(q); ! 610: else ! 611: { ! 612: frexpr(p->exprblock.rightp); ! 613: p->exprblock.rightp = q; ! 614: p->exprblock.vtype = TYINT; ! 615: } ! 616: } ! 617: break; ! 618: ! 619: case OPNEG: ! 620: p->exprblock.leftp = shorten(p->exprblock.leftp); ! 621: if(p->exprblock.leftp->headblock.vtype == TYINT) ! 622: p->exprblock.vtype = TYINT; ! 623: break; ! 624: ! 625: case OPCALL: ! 626: case OPCCALL: ! 627: p = mkconv(TYINT,p); ! 628: break; ! 629: default: ! 630: break; ! 631: } ! 632: ! 633: return(p); ! 634: } ! 635: #endif ! 636: ! 637: /* fix an argument list, taking due care for special first level cases */ ! 638: ! 639: fixargs(doput, p0) ! 640: int doput; /* doput is true if the function is not intrinsic */ ! 641: struct Listblock *p0; ! 642: { ! 643: register chainp p; ! 644: register tagptr q, t; ! 645: register int qtag; ! 646: int nargs; ! 647: Addrp mkscalar(); ! 648: ! 649: nargs = 0; ! 650: if(p0) ! 651: for(p = p0->listp ; p ; p = p->nextp) ! 652: { ! 653: ++nargs; ! 654: q = p->datap; ! 655: qtag = q->tag; ! 656: if(qtag == TCONST) ! 657: { ! 658: if(q->constblock.vtype == TYSHORT) ! 659: q = (tagptr) mkconv(tyint, q); ! 660: /* leave constant arguments of intrinsics alone -- ! 661: * the expression might still simplify. ! 662: */ ! 663: p->datap = doput ? (tagptr) putconst(q) : q ; ! 664: } ! 665: else if(qtag==TPRIM && q->primblock.argsp==0 && ! 666: q->primblock.namep->vclass==CLPROC) ! 667: p->datap = (tagptr) mkaddr(q->primblock.namep); ! 668: else if(qtag==TPRIM && q->primblock.argsp==0 && ! 669: q->primblock.namep->vdim!=NULL) ! 670: p->datap = (tagptr) mkscalar(q->primblock.namep); ! 671: else if(qtag==TPRIM && q->primblock.argsp==0 && ! 672: q->primblock.namep->vdovar && ! 673: (t = (tagptr) memversion(q->primblock.namep)) ) ! 674: p->datap = (tagptr) fixtype(t); ! 675: else ! 676: p->datap = (tagptr) fixtype(q); ! 677: } ! 678: return(nargs); ! 679: } ! 680: ! 681: ! 682: Addrp mkscalar(np) ! 683: register Namep np; ! 684: { ! 685: register Addrp ap; ! 686: ! 687: vardcl(np); ! 688: ap = mkaddr(np); ! 689: ! 690: #if TARGET == VAX ! 691: /* on the VAX, prolog causes array arguments ! 692: to point at the (0,...,0) element, except when ! 693: subscript checking is on ! 694: */ ! 695: if( !checksubs && np->vstg==STGARG) ! 696: { ! 697: register struct Dimblock *dp; ! 698: dp = np->vdim; ! 699: frexpr(ap->memoffset); ! 700: ap->memoffset = mkexpr(OPSTAR, ! 701: (np->vtype==TYCHAR ? ! 702: cpexpr(np->vleng) : ! 703: (tagptr)ICON(typesize[np->vtype]) ), ! 704: cpexpr(dp->baseoffset) ); ! 705: } ! 706: #endif ! 707: return(ap); ! 708: } ! 709: ! 710: ! 711: ! 712: ! 713: ! 714: expptr mkfunct(p) ! 715: register struct Primblock *p; ! 716: { ! 717: struct Entrypoint *ep; ! 718: Addrp ap; ! 719: struct Extsym *extp; ! 720: register Namep np; ! 721: register expptr q; ! 722: expptr intrcall(), stfcall(); ! 723: int k, nargs; ! 724: int class; ! 725: ! 726: if(p->tag != TPRIM) ! 727: return( errnode() ); ! 728: ! 729: np = p->namep; ! 730: class = np->vclass; ! 731: ! 732: if(class == CLUNKNOWN) ! 733: { ! 734: np->vclass = class = CLPROC; ! 735: if(np->vstg == STGUNKNOWN) ! 736: { ! 737: if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) ) ! 738: { ! 739: np->vstg = STGINTR; ! 740: np->vardesc.varno = k; ! 741: np->vprocclass = PINTRINSIC; ! 742: } ! 743: else ! 744: { ! 745: extp = mkext( varunder(VL,np->varname) ); ! 746: extp->extstg = STGEXT; ! 747: np->vstg = STGEXT; ! 748: np->vardesc.varno = extp - extsymtab; ! 749: np->vprocclass = PEXTERNAL; ! 750: } ! 751: } ! 752: else if(np->vstg==STGARG) ! 753: { ! 754: if(np->vtype!=TYCHAR && !ftn66flag) ! 755: warn("Dummy procedure not declared EXTERNAL. Code may be wrong."); ! 756: np->vprocclass = PEXTERNAL; ! 757: } ! 758: } ! 759: ! 760: if(class != CLPROC) ! 761: fatali("invalid class code %d for function", class); ! 762: if(p->fcharp || p->lcharp) ! 763: { ! 764: err("no substring of function call"); ! 765: goto error; ! 766: } ! 767: impldcl(np); ! 768: nargs = fixargs( np->vprocclass!=PINTRINSIC, p->argsp); ! 769: ! 770: switch(np->vprocclass) ! 771: { ! 772: case PEXTERNAL: ! 773: ap = mkaddr(np); ! 774: call: ! 775: q = mkexpr(OPCALL, ap, p->argsp); ! 776: if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN) ! 777: { ! 778: err("attempt to use untyped function"); ! 779: goto error; ! 780: } ! 781: if(np->vleng) ! 782: q->exprblock.vleng = (expptr) cpexpr(np->vleng); ! 783: break; ! 784: ! 785: case PINTRINSIC: ! 786: q = intrcall(np, p->argsp, nargs); ! 787: break; ! 788: ! 789: case PSTFUNCT: ! 790: q = stfcall(np, p->argsp); ! 791: break; ! 792: ! 793: case PTHISPROC: ! 794: warn("recursive call"); ! 795: for(ep = entries ; ep ; ep = ep->entnextp) ! 796: if(ep->enamep == np) ! 797: break; ! 798: if(ep == NULL) ! 799: fatal("mkfunct: impossible recursion"); ! 800: ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) ); ! 801: goto call; ! 802: ! 803: default: ! 804: fatali("mkfunct: impossible vprocclass %d", ! 805: (int) (np->vprocclass) ); ! 806: } ! 807: free( (charptr) p ); ! 808: return(q); ! 809: ! 810: error: ! 811: frexpr(p); ! 812: return( errnode() ); ! 813: } ! 814: ! 815: ! 816: ! 817: LOCAL expptr stfcall(np, actlist) ! 818: Namep np; ! 819: struct Listblock *actlist; ! 820: { ! 821: register chainp actuals; ! 822: int nargs; ! 823: chainp oactp, formals; ! 824: int type; ! 825: expptr q, rhs, ap; ! 826: Namep tnp; ! 827: register struct Rplblock *rp; ! 828: struct Rplblock *tlist; ! 829: ! 830: if(actlist) ! 831: { ! 832: actuals = actlist->listp; ! 833: free( (charptr) actlist); ! 834: } ! 835: else ! 836: actuals = NULL; ! 837: oactp = actuals; ! 838: ! 839: nargs = 0; ! 840: tlist = NULL; ! 841: if( (type = np->vtype) == TYUNKNOWN) ! 842: { ! 843: err("attempt to use untyped statement function"); ! 844: q = errnode(); ! 845: goto ret; ! 846: } ! 847: formals = (chainp) (np->varxptr.vstfdesc->datap); ! 848: rhs = (expptr) (np->varxptr.vstfdesc->nextp); ! 849: ! 850: /* copy actual arguments into temporaries */ ! 851: while(actuals!=NULL && formals!=NULL) ! 852: { ! 853: rp = ALLOC(Rplblock); ! 854: rp->rplnp = tnp = (Namep) (formals->datap); ! 855: ap = fixtype(actuals->datap); ! 856: if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR ! 857: && (ap->tag==TCONST || ap->tag==TADDR) ) ! 858: { ! 859: rp->rplvp = (expptr) ap; ! 860: rp->rplxp = NULL; ! 861: rp->rpltag = ap->tag; ! 862: } ! 863: else { ! 864: rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng); ! 865: rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) ); ! 866: if( (rp->rpltag = rp->rplxp->tag) == TERROR) ! 867: err("disagreement of argument types in statement function call"); ! 868: } ! 869: rp->rplnextp = tlist; ! 870: tlist = rp; ! 871: actuals = actuals->nextp; ! 872: formals = formals->nextp; ! 873: ++nargs; ! 874: } ! 875: ! 876: if(actuals!=NULL || formals!=NULL) ! 877: err("statement function definition and argument list differ"); ! 878: ! 879: /* ! 880: now push down names involved in formal argument list, then ! 881: evaluate rhs of statement function definition in this environment ! 882: */ ! 883: ! 884: if(tlist) /* put tlist in front of the rpllist */ ! 885: { ! 886: for(rp = tlist; rp->rplnextp; rp = rp->rplnextp) ! 887: ; ! 888: rp->rplnextp = rpllist; ! 889: rpllist = tlist; ! 890: } ! 891: ! 892: q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) ); ! 893: ! 894: /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */ ! 895: while(--nargs >= 0) ! 896: { ! 897: if(rpllist->rplxp) ! 898: q = mkexpr(OPCOMMA, rpllist->rplxp, q); ! 899: rp = rpllist->rplnextp; ! 900: frexpr(rpllist->rplvp); ! 901: free(rpllist); ! 902: rpllist = rp; ! 903: } ! 904: ! 905: ret: ! 906: frchain( &oactp ); ! 907: return(q); ! 908: } ! 909: ! 910: ! 911: ! 912: ! 913: Addrp mkplace(np) ! 914: register Namep np; ! 915: { ! 916: register Addrp s; ! 917: register struct Rplblock *rp; ! 918: int regn; ! 919: ! 920: /* is name on the replace list? */ ! 921: ! 922: for(rp = rpllist ; rp ; rp = rp->rplnextp) ! 923: { ! 924: if(np == rp->rplnp) ! 925: { ! 926: if(rp->rpltag == TNAME) ! 927: { ! 928: np = (Namep) (rp->rplvp); ! 929: break; ! 930: } ! 931: else return( (Addrp) cpexpr(rp->rplvp) ); ! 932: } ! 933: } ! 934: ! 935: /* is variable a DO index in a register ? */ ! 936: ! 937: if(np->vdovar && ( (regn = inregister(np)) >= 0) ) ! 938: if(np->vtype == TYERROR) ! 939: return( errnode() ); ! 940: else ! 941: { ! 942: s = ALLOC(Addrblock); ! 943: s->tag = TADDR; ! 944: s->vstg = STGREG; ! 945: s->vtype = TYIREG; ! 946: s->memno = regn; ! 947: s->memoffset = ICON(0); ! 948: return(s); ! 949: } ! 950: ! 951: vardcl(np); ! 952: return(mkaddr(np)); ! 953: } ! 954: ! 955: ! 956: ! 957: ! 958: expptr mklhs(p) ! 959: register struct Primblock *p; ! 960: { ! 961: expptr suboffset(); ! 962: register Addrp s; ! 963: Namep np; ! 964: ! 965: if(p->tag != TPRIM) ! 966: return( (expptr) p ); ! 967: np = p->namep; ! 968: ! 969: s = mkplace(np); ! 970: if(s->tag!=TADDR || s->vstg==STGREG) ! 971: { ! 972: free( (charptr) p ); ! 973: return( (expptr) s ); ! 974: } ! 975: ! 976: /* compute the address modified by subscripts */ ! 977: ! 978: s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) ); ! 979: frexpr(p->argsp); ! 980: p->argsp = NULL; ! 981: ! 982: /* now do substring part */ ! 983: ! 984: if(p->fcharp || p->lcharp) ! 985: { ! 986: if(np->vtype != TYCHAR) ! 987: errstr("substring of noncharacter %s", varstr(VL,np->varname)); ! 988: else { ! 989: if(p->lcharp == NULL) ! 990: p->lcharp = (expptr) cpexpr(s->vleng); ! 991: if(p->fcharp) ! 992: s->vleng = mkexpr(OPMINUS, p->lcharp, ! 993: mkexpr(OPMINUS, p->fcharp, ICON(1) )); ! 994: else { ! 995: frexpr(s->vleng); ! 996: s->vleng = p->lcharp; ! 997: } ! 998: } ! 999: } ! 1000: ! 1001: s->vleng = fixtype( s->vleng ); ! 1002: s->memoffset = fixtype( s->memoffset ); ! 1003: free( (charptr) p ); ! 1004: return( (expptr) s ); ! 1005: } ! 1006: ! 1007: ! 1008: ! 1009: ! 1010: ! 1011: deregister(np) ! 1012: Namep np; ! 1013: { ! 1014: if(nregvar>0 && regnamep[nregvar-1]==np) ! 1015: { ! 1016: --nregvar; ! 1017: #if FAMILY == DMR ! 1018: putnreg(); ! 1019: #endif ! 1020: } ! 1021: } ! 1022: ! 1023: ! 1024: ! 1025: ! 1026: Addrp memversion(np) ! 1027: register Namep np; ! 1028: { ! 1029: register Addrp s; ! 1030: ! 1031: if(np->vdovar==NO || (inregister(np)<0) ) ! 1032: return(NULL); ! 1033: np->vdovar = NO; ! 1034: s = mkplace(np); ! 1035: np->vdovar = YES; ! 1036: return(s); ! 1037: } ! 1038: ! 1039: ! 1040: ! 1041: inregister(np) ! 1042: register Namep np; ! 1043: { ! 1044: register int i; ! 1045: ! 1046: for(i = 0 ; i < nregvar ; ++i) ! 1047: if(regnamep[i] == np) ! 1048: return( regnum[i] ); ! 1049: return(-1); ! 1050: } ! 1051: ! 1052: ! 1053: ! 1054: ! 1055: enregister(np) ! 1056: Namep np; ! 1057: { ! 1058: if( inregister(np) >= 0) ! 1059: return(YES); ! 1060: if(nregvar >= maxregvar) ! 1061: return(NO); ! 1062: vardcl(np); ! 1063: if( ONEOF(np->vtype, MSKIREG) ) ! 1064: { ! 1065: regnamep[nregvar++] = np; ! 1066: if(nregvar > highregvar) ! 1067: highregvar = nregvar; ! 1068: #if FAMILY == DMR ! 1069: putnreg(); ! 1070: #endif ! 1071: return(YES); ! 1072: } ! 1073: else ! 1074: return(NO); ! 1075: } ! 1076: ! 1077: ! 1078: ! 1079: ! 1080: expptr suboffset(p) ! 1081: register struct Primblock *p; ! 1082: { ! 1083: int n; ! 1084: expptr size; ! 1085: chainp cp; ! 1086: expptr offp, prod; ! 1087: expptr subcheck(); ! 1088: struct Dimblock *dimp; ! 1089: expptr sub[MAXDIM+1]; ! 1090: register Namep np; ! 1091: ! 1092: np = p->namep; ! 1093: offp = ICON(0); ! 1094: n = 0; ! 1095: if(p->argsp) ! 1096: for(cp = p->argsp->listp ; cp ; cp = cp->nextp) ! 1097: { ! 1098: sub[n++] = fixtype(cpexpr(cp->datap)); ! 1099: if(n > maxdim) ! 1100: { ! 1101: erri("more than %d subscripts", maxdim); ! 1102: break; ! 1103: } ! 1104: } ! 1105: ! 1106: dimp = np->vdim; ! 1107: if(n>0 && dimp==NULL) ! 1108: err("subscripts on scalar variable"); ! 1109: else if(dimp && dimp->ndim!=n) ! 1110: errstr("wrong number of subscripts on %s", ! 1111: varstr(VL, np->varname) ); ! 1112: else if(n > 0) ! 1113: { ! 1114: prod = sub[--n]; ! 1115: while( --n >= 0) ! 1116: prod = mkexpr(OPPLUS, sub[n], ! 1117: mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) ); ! 1118: #if TARGET == VAX ! 1119: if(checksubs || np->vstg!=STGARG) ! 1120: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); ! 1121: #else ! 1122: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); ! 1123: #endif ! 1124: if(checksubs) ! 1125: prod = subcheck(np, prod); ! 1126: size = np->vtype == TYCHAR ? ! 1127: (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]); ! 1128: prod = mkexpr(OPSTAR, prod, size); ! 1129: offp = mkexpr(OPPLUS, offp, prod); ! 1130: } ! 1131: ! 1132: if(p->fcharp && np->vtype==TYCHAR) ! 1133: offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) )); ! 1134: ! 1135: return(offp); ! 1136: } ! 1137: ! 1138: ! 1139: ! 1140: ! 1141: expptr subcheck(np, p) ! 1142: Namep np; ! 1143: register expptr p; ! 1144: { ! 1145: struct Dimblock *dimp; ! 1146: expptr t, checkvar, checkcond, badcall; ! 1147: ! 1148: dimp = np->vdim; ! 1149: if(dimp->nelt == NULL) ! 1150: return(p); /* don't check arrays with * bounds */ ! 1151: checkvar = NULL; ! 1152: checkcond = NULL; ! 1153: if( ISICON(p) ) ! 1154: { ! 1155: if(p->constblock.const.ci < 0) ! 1156: goto badsub; ! 1157: if( ISICON(dimp->nelt) ) ! 1158: if(p->constblock.const.ci < dimp->nelt->constblock.const.ci) ! 1159: return(p); ! 1160: else ! 1161: goto badsub; ! 1162: } ! 1163: if(p->tag==TADDR && p->addrblock.vstg==STGREG) ! 1164: { ! 1165: checkvar = (expptr) cpexpr(p); ! 1166: t = p; ! 1167: } ! 1168: else { ! 1169: checkvar = (expptr) mktemp(p->headblock.vtype, ENULL); ! 1170: t = mkexpr(OPASSIGN, cpexpr(checkvar), p); ! 1171: } ! 1172: checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) ); ! 1173: if( ! ISICON(p) ) ! 1174: checkcond = mkexpr(OPAND, checkcond, ! 1175: mkexpr(OPLE, ICON(0), cpexpr(checkvar)) ); ! 1176: ! 1177: badcall = call4(p->headblock.vtype, "s_rnge", ! 1178: mkstrcon(VL, np->varname), ! 1179: mkconv(TYLONG, cpexpr(checkvar)), ! 1180: mkstrcon(XL, procname), ! 1181: ICON(lineno) ); ! 1182: badcall->exprblock.opcode = OPCCALL; ! 1183: p = mkexpr(OPQUEST, checkcond, ! 1184: mkexpr(OPCOLON, checkvar, badcall)); ! 1185: ! 1186: return(p); ! 1187: ! 1188: badsub: ! 1189: frexpr(p); ! 1190: errstr("subscript on variable %s out of range", varstr(VL,np->varname)); ! 1191: return ( ICON(0) ); ! 1192: } ! 1193: ! 1194: ! 1195: ! 1196: ! 1197: Addrp mkaddr(p) ! 1198: register Namep p; ! 1199: { ! 1200: struct Extsym *extp; ! 1201: register Addrp t; ! 1202: Addrp intraddr(); ! 1203: ! 1204: switch( p->vstg) ! 1205: { ! 1206: case STGUNKNOWN: ! 1207: if(p->vclass != CLPROC) ! 1208: break; ! 1209: extp = mkext( varunder(VL, p->varname) ); ! 1210: extp->extstg = STGEXT; ! 1211: p->vstg = STGEXT; ! 1212: p->vardesc.varno = extp - extsymtab; ! 1213: p->vprocclass = PEXTERNAL; ! 1214: ! 1215: case STGCOMMON: ! 1216: case STGEXT: ! 1217: case STGBSS: ! 1218: case STGINIT: ! 1219: case STGEQUIV: ! 1220: case STGARG: ! 1221: case STGLENG: ! 1222: case STGAUTO: ! 1223: t = ALLOC(Addrblock); ! 1224: t->tag = TADDR; ! 1225: if(p->vclass==CLPROC && p->vprocclass==PTHISPROC) ! 1226: t->vclass = CLVAR; ! 1227: else ! 1228: t->vclass = p->vclass; ! 1229: t->vtype = p->vtype; ! 1230: t->vstg = p->vstg; ! 1231: t->memno = p->vardesc.varno; ! 1232: t->memoffset = ICON(p->voffset); ! 1233: if(p->vleng) ! 1234: { ! 1235: t->vleng = (expptr) cpexpr(p->vleng); ! 1236: if( ISICON(t->vleng) ) ! 1237: t->varleng = t->vleng->constblock.const.ci; ! 1238: } ! 1239: return(t); ! 1240: ! 1241: case STGINTR: ! 1242: return( intraddr(p) ); ! 1243: ! 1244: } ! 1245: /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass); ! 1246: badstg("mkaddr", p->vstg); ! 1247: /* NOTREACHED */ ! 1248: } ! 1249: ! 1250: ! 1251: ! 1252: ! 1253: Addrp mkarg(type, argno) ! 1254: int type, argno; ! 1255: { ! 1256: register Addrp p; ! 1257: ! 1258: p = ALLOC(Addrblock); ! 1259: p->tag = TADDR; ! 1260: p->vtype = type; ! 1261: p->vclass = CLVAR; ! 1262: p->vstg = (type==TYLENG ? STGLENG : STGARG); ! 1263: p->memno = argno; ! 1264: return(p); ! 1265: } ! 1266: ! 1267: ! 1268: ! 1269: ! 1270: expptr mkprim(v, args, substr) ! 1271: register union ! 1272: { ! 1273: struct Paramblock paramblock; ! 1274: struct Nameblock nameblock; ! 1275: struct Headblock headblock; ! 1276: } *v; ! 1277: struct Listblock *args; ! 1278: chainp substr; ! 1279: { ! 1280: register struct Primblock *p; ! 1281: ! 1282: if(v->headblock.vclass == CLPARAM) ! 1283: { ! 1284: if(args || substr) ! 1285: { ! 1286: errstr("no qualifiers on parameter name %s", ! 1287: varstr(VL,v->paramblock.varname)); ! 1288: frexpr(args); ! 1289: if(substr) ! 1290: { ! 1291: frexpr(substr->datap); ! 1292: frexpr(substr->nextp->datap); ! 1293: frchain(&substr); ! 1294: } ! 1295: frexpr(v); ! 1296: return( errnode() ); ! 1297: } ! 1298: return( (expptr) cpexpr(v->paramblock.paramval) ); ! 1299: } ! 1300: ! 1301: p = ALLOC(Primblock); ! 1302: p->tag = TPRIM; ! 1303: p->vtype = v->nameblock.vtype; ! 1304: p->namep = (Namep) v; ! 1305: p->argsp = args; ! 1306: if(substr) ! 1307: { ! 1308: p->fcharp = (expptr) (substr->datap); ! 1309: p->lcharp = (expptr) (substr->nextp->datap); ! 1310: frchain(&substr); ! 1311: } ! 1312: return( (expptr) p); ! 1313: } ! 1314: ! 1315: ! 1316: ! 1317: vardcl(v) ! 1318: register Namep v; ! 1319: { ! 1320: int nelt; ! 1321: struct Dimblock *t; ! 1322: Addrp p; ! 1323: expptr neltp; ! 1324: ! 1325: if(v->vdcldone) ! 1326: return; ! 1327: if(v->vclass == CLNAMELIST) ! 1328: return; ! 1329: ! 1330: if(v->vtype == TYUNKNOWN) ! 1331: impldcl(v); ! 1332: if(v->vclass == CLUNKNOWN) ! 1333: v->vclass = CLVAR; ! 1334: else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC) ! 1335: { ! 1336: dclerr("used as variable", v); ! 1337: return; ! 1338: } ! 1339: if(v->vstg==STGUNKNOWN) ! 1340: v->vstg = implstg[ letter(v->varname[0]) ]; ! 1341: ! 1342: switch(v->vstg) ! 1343: { ! 1344: case STGBSS: ! 1345: v->vardesc.varno = ++lastvarno; ! 1346: break; ! 1347: case STGAUTO: ! 1348: if(v->vclass==CLPROC && v->vprocclass==PTHISPROC) ! 1349: break; ! 1350: nelt = 1; ! 1351: if(t = v->vdim) ! 1352: if( (neltp = t->nelt) && ISCONST(neltp) ) ! 1353: nelt = neltp->constblock.const.ci; ! 1354: else ! 1355: dclerr("adjustable automatic array", v); ! 1356: p = autovar(nelt, v->vtype, v->vleng); ! 1357: v->voffset = p->memoffset->constblock.const.ci; ! 1358: frexpr(p); ! 1359: break; ! 1360: ! 1361: default: ! 1362: break; ! 1363: } ! 1364: v->vdcldone = YES; ! 1365: } ! 1366: ! 1367: ! 1368: ! 1369: ! 1370: impldcl(p) ! 1371: register Namep p; ! 1372: { ! 1373: register int k; ! 1374: int type, leng; ! 1375: ! 1376: if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) ) ! 1377: return; ! 1378: if(p->vtype == TYUNKNOWN) ! 1379: { ! 1380: k = letter(p->varname[0]); ! 1381: type = impltype[ k ]; ! 1382: leng = implleng[ k ]; ! 1383: if(type == TYUNKNOWN) ! 1384: { ! 1385: if(p->vclass == CLPROC) ! 1386: return; ! 1387: dclerr("attempt to use undefined variable", p); ! 1388: type = TYERROR; ! 1389: leng = 1; ! 1390: } ! 1391: settype(p, type, leng); ! 1392: } ! 1393: } ! 1394: ! 1395: ! 1396: ! 1397: ! 1398: LOCAL letter(c) ! 1399: register int c; ! 1400: { ! 1401: if( isupper(c) ) ! 1402: c = tolower(c); ! 1403: return(c - 'a'); ! 1404: } ! 1405: ! 1406: #define ICONEQ(z, c) (ISICON(z) && z->constblock.const.ci==c) ! 1407: #define COMMUTE { e = lp; lp = rp; rp = e; } ! 1408: ! 1409: ! 1410: expptr mkexpr(opcode, lp, rp) ! 1411: int opcode; ! 1412: register expptr lp, rp; ! 1413: { ! 1414: register expptr e, e1; ! 1415: int etype; ! 1416: int ltype, rtype; ! 1417: int ltag, rtag; ! 1418: expptr fold(); ! 1419: ! 1420: ltype = lp->headblock.vtype; ! 1421: ltag = lp->tag; ! 1422: if(rp && opcode!=OPCALL && opcode!=OPCCALL) ! 1423: { ! 1424: rtype = rp->headblock.vtype; ! 1425: rtag = rp->tag; ! 1426: } ! 1427: else rtype = 0; ! 1428: ! 1429: etype = cktype(opcode, ltype, rtype); ! 1430: if(etype == TYERROR) ! 1431: goto error; ! 1432: ! 1433: switch(opcode) ! 1434: { ! 1435: /* check for multiplication by 0 and 1 and addition to 0 */ ! 1436: ! 1437: case OPSTAR: ! 1438: if( ISCONST(lp) ) ! 1439: COMMUTE ! 1440: ! 1441: if( ISICON(rp) ) ! 1442: { ! 1443: if(rp->constblock.const.ci == 0) ! 1444: goto retright; ! 1445: goto mulop; ! 1446: } ! 1447: break; ! 1448: ! 1449: case OPSLASH: ! 1450: case OPMOD: ! 1451: if( ICONEQ(rp, 0) ) ! 1452: { ! 1453: err("attempted division by zero"); ! 1454: rp = ICON(1); ! 1455: break; ! 1456: } ! 1457: if(opcode == OPMOD) ! 1458: break; ! 1459: ! 1460: ! 1461: mulop: ! 1462: if( ISICON(rp) ) ! 1463: { ! 1464: if(rp->constblock.const.ci == 1) ! 1465: goto retleft; ! 1466: ! 1467: if(rp->constblock.const.ci == -1) ! 1468: { ! 1469: frexpr(rp); ! 1470: return( mkexpr(OPNEG, lp, PNULL) ); ! 1471: } ! 1472: } ! 1473: ! 1474: if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) ) ! 1475: { ! 1476: if(opcode == OPSTAR) ! 1477: e = mkexpr(OPSTAR, lp->exprblock.rightp, rp); ! 1478: else if(ISICON(rp) && ! 1479: (lp->exprblock.rightp->constblock.const.ci % ! 1480: rp->constblock.const.ci) == 0) ! 1481: e = mkexpr(OPSLASH, lp->exprblock.rightp, rp); ! 1482: else break; ! 1483: ! 1484: e1 = lp->exprblock.leftp; ! 1485: free( (charptr) lp ); ! 1486: return( mkexpr(OPSTAR, e1, e) ); ! 1487: } ! 1488: break; ! 1489: ! 1490: ! 1491: case OPPLUS: ! 1492: if( ISCONST(lp) ) ! 1493: COMMUTE ! 1494: goto addop; ! 1495: ! 1496: case OPMINUS: ! 1497: if( ICONEQ(lp, 0) ) ! 1498: { ! 1499: frexpr(lp); ! 1500: return( mkexpr(OPNEG, rp, ENULL) ); ! 1501: } ! 1502: ! 1503: if( ISCONST(rp) ) ! 1504: { ! 1505: opcode = OPPLUS; ! 1506: consnegop(rp); ! 1507: } ! 1508: ! 1509: addop: ! 1510: if( ISICON(rp) ) ! 1511: { ! 1512: if(rp->constblock.const.ci == 0) ! 1513: goto retleft; ! 1514: if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) ) ! 1515: { ! 1516: e = mkexpr(OPPLUS, lp->exprblock.rightp, rp); ! 1517: e1 = lp->exprblock.leftp; ! 1518: free( (charptr) lp ); ! 1519: return( mkexpr(OPPLUS, e1, e) ); ! 1520: } ! 1521: } ! 1522: break; ! 1523: ! 1524: ! 1525: case OPPOWER: ! 1526: break; ! 1527: ! 1528: case OPNEG: ! 1529: if(ltag==TEXPR && lp->exprblock.opcode==OPNEG) ! 1530: { ! 1531: e = lp->exprblock.leftp; ! 1532: free( (charptr) lp ); ! 1533: return(e); ! 1534: } ! 1535: break; ! 1536: ! 1537: case OPNOT: ! 1538: if(ltag==TEXPR && lp->exprblock.opcode==OPNOT) ! 1539: { ! 1540: e = lp->exprblock.leftp; ! 1541: free( (charptr) lp ); ! 1542: return(e); ! 1543: } ! 1544: break; ! 1545: ! 1546: case OPCALL: ! 1547: case OPCCALL: ! 1548: etype = ltype; ! 1549: if(rp!=NULL && rp->listblock.listp==NULL) ! 1550: { ! 1551: free( (charptr) rp ); ! 1552: rp = NULL; ! 1553: } ! 1554: break; ! 1555: ! 1556: case OPAND: ! 1557: case OPOR: ! 1558: if( ISCONST(lp) ) ! 1559: COMMUTE ! 1560: ! 1561: if( ISCONST(rp) ) ! 1562: { ! 1563: if(rp->constblock.const.ci == 0) ! 1564: if(opcode == OPOR) ! 1565: goto retleft; ! 1566: else ! 1567: goto retright; ! 1568: else if(opcode == OPOR) ! 1569: goto retright; ! 1570: else ! 1571: goto retleft; ! 1572: } ! 1573: case OPEQV: ! 1574: case OPNEQV: ! 1575: ! 1576: case OPBITAND: ! 1577: case OPBITOR: ! 1578: case OPBITXOR: ! 1579: case OPBITNOT: ! 1580: case OPLSHIFT: ! 1581: case OPRSHIFT: ! 1582: ! 1583: case OPLT: ! 1584: case OPGT: ! 1585: case OPLE: ! 1586: case OPGE: ! 1587: case OPEQ: ! 1588: case OPNE: ! 1589: ! 1590: case OPCONCAT: ! 1591: break; ! 1592: case OPMIN: ! 1593: case OPMAX: ! 1594: ! 1595: case OPASSIGN: ! 1596: case OPPLUSEQ: ! 1597: case OPSTAREQ: ! 1598: ! 1599: case OPCONV: ! 1600: case OPADDR: ! 1601: ! 1602: case OPCOMMA: ! 1603: case OPQUEST: ! 1604: case OPCOLON: ! 1605: break; ! 1606: ! 1607: default: ! 1608: badop("mkexpr", opcode); ! 1609: } ! 1610: ! 1611: e = (expptr) ALLOC(Exprblock); ! 1612: e->exprblock.tag = TEXPR; ! 1613: e->exprblock.opcode = opcode; ! 1614: e->exprblock.vtype = etype; ! 1615: e->exprblock.leftp = lp; ! 1616: e->exprblock.rightp = rp; ! 1617: if(ltag==TCONST && (rp==0 || rtag==TCONST) ) ! 1618: e = fold(e); ! 1619: return(e); ! 1620: ! 1621: retleft: ! 1622: frexpr(rp); ! 1623: return(lp); ! 1624: ! 1625: retright: ! 1626: frexpr(lp); ! 1627: return(rp); ! 1628: ! 1629: error: ! 1630: frexpr(lp); ! 1631: if(rp && opcode!=OPCALL && opcode!=OPCCALL) ! 1632: frexpr(rp); ! 1633: return( errnode() ); ! 1634: } ! 1635: ! 1636: #define ERR(s) { errs = s; goto error; } ! 1637: ! 1638: cktype(op, lt, rt) ! 1639: register int op, lt, rt; ! 1640: { ! 1641: char *errs; ! 1642: ! 1643: if(lt==TYERROR || rt==TYERROR) ! 1644: goto error1; ! 1645: ! 1646: if(lt==TYUNKNOWN) ! 1647: return(TYUNKNOWN); ! 1648: if(rt==TYUNKNOWN) ! 1649: if(op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && op!=OPCCALL && op!=OPADDR) ! 1650: return(TYUNKNOWN); ! 1651: ! 1652: switch(op) ! 1653: { ! 1654: case OPPLUS: ! 1655: case OPMINUS: ! 1656: case OPSTAR: ! 1657: case OPSLASH: ! 1658: case OPPOWER: ! 1659: case OPMOD: ! 1660: if( ISNUMERIC(lt) && ISNUMERIC(rt) ) ! 1661: return( maxtype(lt, rt) ); ! 1662: ERR("nonarithmetic operand of arithmetic operator") ! 1663: ! 1664: case OPNEG: ! 1665: if( ISNUMERIC(lt) ) ! 1666: return(lt); ! 1667: ERR("nonarithmetic operand of negation") ! 1668: ! 1669: case OPNOT: ! 1670: if(lt == TYLOGICAL) ! 1671: return(TYLOGICAL); ! 1672: ERR("NOT of nonlogical") ! 1673: ! 1674: case OPAND: ! 1675: case OPOR: ! 1676: case OPEQV: ! 1677: case OPNEQV: ! 1678: if(lt==TYLOGICAL && rt==TYLOGICAL) ! 1679: return(TYLOGICAL); ! 1680: ERR("nonlogical operand of logical operator") ! 1681: ! 1682: case OPLT: ! 1683: case OPGT: ! 1684: case OPLE: ! 1685: case OPGE: ! 1686: case OPEQ: ! 1687: case OPNE: ! 1688: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) ! 1689: { ! 1690: if(lt != rt) ! 1691: ERR("illegal comparison") ! 1692: } ! 1693: ! 1694: else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) ) ! 1695: { ! 1696: if(op!=OPEQ && op!=OPNE) ! 1697: ERR("order comparison of complex data") ! 1698: } ! 1699: ! 1700: else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) ) ! 1701: ERR("comparison of nonarithmetic data") ! 1702: return(TYLOGICAL); ! 1703: ! 1704: case OPCONCAT: ! 1705: if(lt==TYCHAR && rt==TYCHAR) ! 1706: return(TYCHAR); ! 1707: ERR("concatenation of nonchar data") ! 1708: ! 1709: case OPCALL: ! 1710: case OPCCALL: ! 1711: return(lt); ! 1712: ! 1713: case OPADDR: ! 1714: return(TYADDR); ! 1715: ! 1716: case OPCONV: ! 1717: if(rt == 0) ! 1718: return(0); ! 1719: if(lt==TYCHAR && ISINT(rt) ) ! 1720: return(TYCHAR); ! 1721: case OPASSIGN: ! 1722: case OPPLUSEQ: ! 1723: case OPSTAREQ: ! 1724: if( ISINT(lt) && rt==TYCHAR) ! 1725: return(lt); ! 1726: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) ! 1727: if(op!=OPASSIGN || lt!=rt) ! 1728: { ! 1729: /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */ ! 1730: /* debug fatal("impossible conversion. possible compiler bug"); */ ! 1731: ERR("impossible conversion") ! 1732: } ! 1733: return(lt); ! 1734: ! 1735: case OPMIN: ! 1736: case OPMAX: ! 1737: case OPBITOR: ! 1738: case OPBITAND: ! 1739: case OPBITXOR: ! 1740: case OPBITNOT: ! 1741: case OPLSHIFT: ! 1742: case OPRSHIFT: ! 1743: return(lt); ! 1744: ! 1745: case OPCOMMA: ! 1746: case OPQUEST: ! 1747: case OPCOLON: ! 1748: return(rt); ! 1749: ! 1750: default: ! 1751: badop("cktype", op); ! 1752: } ! 1753: error: err(errs); ! 1754: error1: return(TYERROR); ! 1755: } ! 1756: ! 1757: LOCAL expptr fold(e) ! 1758: register expptr e; ! 1759: { ! 1760: Constp p; ! 1761: register expptr lp, rp; ! 1762: int etype, mtype, ltype, rtype, opcode; ! 1763: int i, ll, lr; ! 1764: char *q, *s; ! 1765: union Constant lcon, rcon; ! 1766: ! 1767: opcode = e->exprblock.opcode; ! 1768: etype = e->exprblock.vtype; ! 1769: ! 1770: lp = e->exprblock.leftp; ! 1771: ltype = lp->headblock.vtype; ! 1772: rp = e->exprblock.rightp; ! 1773: ! 1774: if(rp == 0) ! 1775: switch(opcode) ! 1776: { ! 1777: case OPNOT: ! 1778: lp->constblock.const.ci = ! lp->constblock.const.ci; ! 1779: return(lp); ! 1780: ! 1781: case OPBITNOT: ! 1782: lp->constblock.const.ci = ~ lp->constblock.const.ci; ! 1783: return(lp); ! 1784: ! 1785: case OPNEG: ! 1786: consnegop(lp); ! 1787: return(lp); ! 1788: ! 1789: case OPCONV: ! 1790: case OPADDR: ! 1791: return(e); ! 1792: ! 1793: default: ! 1794: badop("fold", opcode); ! 1795: } ! 1796: ! 1797: rtype = rp->headblock.vtype; ! 1798: ! 1799: p = ALLOC(Constblock); ! 1800: p->tag = TCONST; ! 1801: p->vtype = etype; ! 1802: p->vleng = e->exprblock.vleng; ! 1803: ! 1804: switch(opcode) ! 1805: { ! 1806: case OPCOMMA: ! 1807: case OPQUEST: ! 1808: case OPCOLON: ! 1809: return(e); ! 1810: ! 1811: case OPAND: ! 1812: p->const.ci = lp->constblock.const.ci && ! 1813: rp->constblock.const.ci; ! 1814: break; ! 1815: ! 1816: case OPOR: ! 1817: p->const.ci = lp->constblock.const.ci || ! 1818: rp->constblock.const.ci; ! 1819: break; ! 1820: ! 1821: case OPEQV: ! 1822: p->const.ci = lp->constblock.const.ci == ! 1823: rp->constblock.const.ci; ! 1824: break; ! 1825: ! 1826: case OPNEQV: ! 1827: p->const.ci = lp->constblock.const.ci != ! 1828: rp->constblock.const.ci; ! 1829: break; ! 1830: ! 1831: case OPBITAND: ! 1832: p->const.ci = lp->constblock.const.ci & ! 1833: rp->constblock.const.ci; ! 1834: break; ! 1835: ! 1836: case OPBITOR: ! 1837: p->const.ci = lp->constblock.const.ci | ! 1838: rp->constblock.const.ci; ! 1839: break; ! 1840: ! 1841: case OPBITXOR: ! 1842: p->const.ci = lp->constblock.const.ci ^ ! 1843: rp->constblock.const.ci; ! 1844: break; ! 1845: ! 1846: case OPLSHIFT: ! 1847: p->const.ci = lp->constblock.const.ci << ! 1848: rp->constblock.const.ci; ! 1849: break; ! 1850: ! 1851: case OPRSHIFT: ! 1852: p->const.ci = lp->constblock.const.ci >> ! 1853: rp->constblock.const.ci; ! 1854: break; ! 1855: ! 1856: case OPCONCAT: ! 1857: ll = lp->constblock.vleng->constblock.const.ci; ! 1858: lr = rp->constblock.vleng->constblock.const.ci; ! 1859: p->const.ccp = q = (char *) ckalloc(ll+lr); ! 1860: p->vleng = ICON(ll+lr); ! 1861: s = lp->constblock.const.ccp; ! 1862: for(i = 0 ; i < ll ; ++i) ! 1863: *q++ = *s++; ! 1864: s = rp->constblock.const.ccp; ! 1865: for(i = 0; i < lr; ++i) ! 1866: *q++ = *s++; ! 1867: break; ! 1868: ! 1869: ! 1870: case OPPOWER: ! 1871: if( ! ISINT(rtype) ) ! 1872: return(e); ! 1873: conspower(&(p->const), lp, rp->constblock.const.ci); ! 1874: break; ! 1875: ! 1876: ! 1877: default: ! 1878: if(ltype == TYCHAR) ! 1879: { ! 1880: lcon.ci = cmpstr(lp->constblock.const.ccp, ! 1881: rp->constblock.const.ccp, ! 1882: lp->constblock.vleng->constblock.const.ci, ! 1883: rp->constblock.vleng->constblock.const.ci); ! 1884: rcon.ci = 0; ! 1885: mtype = tyint; ! 1886: } ! 1887: else { ! 1888: mtype = maxtype(ltype, rtype); ! 1889: consconv(mtype, &lcon, ltype, &(lp->constblock.const) ); ! 1890: consconv(mtype, &rcon, rtype, &(rp->constblock.const) ); ! 1891: } ! 1892: consbinop(opcode, mtype, &(p->const), &lcon, &rcon); ! 1893: break; ! 1894: } ! 1895: ! 1896: frexpr(e); ! 1897: return( (expptr) p ); ! 1898: } ! 1899: ! 1900: ! 1901: ! 1902: /* assign constant l = r , doing coercion */ ! 1903: ! 1904: consconv(lt, lv, rt, rv) ! 1905: int lt, rt; ! 1906: register union Constant *lv, *rv; ! 1907: { ! 1908: switch(lt) ! 1909: { ! 1910: case TYCHAR: ! 1911: *(lv->ccp = (char *) ckalloc(1)) = rv->ci; ! 1912: break; ! 1913: ! 1914: case TYSHORT: ! 1915: case TYLONG: ! 1916: if(rt == TYCHAR) ! 1917: lv->ci = rv->ccp[0]; ! 1918: else if( ISINT(rt) ) ! 1919: lv->ci = rv->ci; ! 1920: else lv->ci = rv->cd[0]; ! 1921: break; ! 1922: ! 1923: case TYCOMPLEX: ! 1924: case TYDCOMPLEX: ! 1925: switch(rt) ! 1926: { ! 1927: case TYSHORT: ! 1928: case TYLONG: ! 1929: /* fall through and do real assignment of ! 1930: first element ! 1931: */ ! 1932: case TYREAL: ! 1933: case TYDREAL: ! 1934: lv->cd[1] = 0; break; ! 1935: case TYCOMPLEX: ! 1936: case TYDCOMPLEX: ! 1937: lv->cd[1] = rv->cd[1]; break; ! 1938: } ! 1939: ! 1940: case TYREAL: ! 1941: case TYDREAL: ! 1942: if( ISINT(rt) ) ! 1943: lv->cd[0] = rv->ci; ! 1944: else lv->cd[0] = rv->cd[0]; ! 1945: break; ! 1946: ! 1947: case TYLOGICAL: ! 1948: lv->ci = rv->ci; ! 1949: break; ! 1950: } ! 1951: } ! 1952: ! 1953: ! 1954: ! 1955: consnegop(p) ! 1956: register Constp p; ! 1957: { ! 1958: switch(p->vtype) ! 1959: { ! 1960: case TYSHORT: ! 1961: case TYLONG: ! 1962: p->const.ci = - p->const.ci; ! 1963: break; ! 1964: ! 1965: case TYCOMPLEX: ! 1966: case TYDCOMPLEX: ! 1967: p->const.cd[1] = - p->const.cd[1]; ! 1968: /* fall through and do the real parts */ ! 1969: case TYREAL: ! 1970: case TYDREAL: ! 1971: p->const.cd[0] = - p->const.cd[0]; ! 1972: break; ! 1973: default: ! 1974: badtype("consnegop", p->vtype); ! 1975: } ! 1976: } ! 1977: ! 1978: ! 1979: ! 1980: LOCAL conspower(powp, ap, n) ! 1981: register union Constant *powp; ! 1982: Constp ap; ! 1983: ftnint n; ! 1984: { ! 1985: register int type; ! 1986: union Constant x; ! 1987: ! 1988: switch(type = ap->vtype) /* pow = 1 */ ! 1989: { ! 1990: case TYSHORT: ! 1991: case TYLONG: ! 1992: powp->ci = 1; ! 1993: break; ! 1994: case TYCOMPLEX: ! 1995: case TYDCOMPLEX: ! 1996: powp->cd[1] = 0; ! 1997: case TYREAL: ! 1998: case TYDREAL: ! 1999: powp->cd[0] = 1; ! 2000: break; ! 2001: default: ! 2002: badtype("conspower", type); ! 2003: } ! 2004: ! 2005: if(n == 0) ! 2006: return; ! 2007: if(n < 0) ! 2008: { ! 2009: if( ISINT(type) ) ! 2010: { ! 2011: err("integer ** negative power "); ! 2012: return; ! 2013: } ! 2014: n = - n; ! 2015: consbinop(OPSLASH, type, &x, powp, &(ap->const)); ! 2016: } ! 2017: else ! 2018: consbinop(OPSTAR, type, &x, powp, &(ap->const)); ! 2019: ! 2020: for( ; ; ) ! 2021: { ! 2022: if(n & 01) ! 2023: consbinop(OPSTAR, type, powp, powp, &x); ! 2024: if(n >>= 1) ! 2025: consbinop(OPSTAR, type, &x, &x, &x); ! 2026: else ! 2027: break; ! 2028: } ! 2029: } ! 2030: ! 2031: ! 2032: ! 2033: /* do constant operation cp = a op b */ ! 2034: ! 2035: ! 2036: LOCAL consbinop(opcode, type, cp, ap, bp) ! 2037: int opcode, type; ! 2038: register union Constant *ap, *bp, *cp; ! 2039: { ! 2040: int k; ! 2041: double temp; ! 2042: ! 2043: switch(opcode) ! 2044: { ! 2045: case OPPLUS: ! 2046: switch(type) ! 2047: { ! 2048: case TYSHORT: ! 2049: case TYLONG: ! 2050: cp->ci = ap->ci + bp->ci; ! 2051: break; ! 2052: case TYCOMPLEX: ! 2053: case TYDCOMPLEX: ! 2054: cp->cd[1] = ap->cd[1] + bp->cd[1]; ! 2055: case TYREAL: ! 2056: case TYDREAL: ! 2057: cp->cd[0] = ap->cd[0] + bp->cd[0]; ! 2058: break; ! 2059: } ! 2060: break; ! 2061: ! 2062: case OPMINUS: ! 2063: switch(type) ! 2064: { ! 2065: case TYSHORT: ! 2066: case TYLONG: ! 2067: cp->ci = ap->ci - bp->ci; ! 2068: break; ! 2069: case TYCOMPLEX: ! 2070: case TYDCOMPLEX: ! 2071: cp->cd[1] = ap->cd[1] - bp->cd[1]; ! 2072: case TYREAL: ! 2073: case TYDREAL: ! 2074: cp->cd[0] = ap->cd[0] - bp->cd[0]; ! 2075: break; ! 2076: } ! 2077: break; ! 2078: ! 2079: case OPSTAR: ! 2080: switch(type) ! 2081: { ! 2082: case TYSHORT: ! 2083: case TYLONG: ! 2084: cp->ci = ap->ci * bp->ci; ! 2085: break; ! 2086: case TYREAL: ! 2087: case TYDREAL: ! 2088: cp->cd[0] = ap->cd[0] * bp->cd[0]; ! 2089: break; ! 2090: case TYCOMPLEX: ! 2091: case TYDCOMPLEX: ! 2092: temp = ap->cd[0] * bp->cd[0] - ! 2093: ap->cd[1] * bp->cd[1] ; ! 2094: cp->cd[1] = ap->cd[0] * bp->cd[1] + ! 2095: ap->cd[1] * bp->cd[0] ; ! 2096: cp->cd[0] = temp; ! 2097: break; ! 2098: } ! 2099: break; ! 2100: case OPSLASH: ! 2101: switch(type) ! 2102: { ! 2103: case TYSHORT: ! 2104: case TYLONG: ! 2105: cp->ci = ap->ci / bp->ci; ! 2106: break; ! 2107: case TYREAL: ! 2108: case TYDREAL: ! 2109: cp->cd[0] = ap->cd[0] / bp->cd[0]; ! 2110: break; ! 2111: case TYCOMPLEX: ! 2112: case TYDCOMPLEX: ! 2113: zdiv(cp,ap,bp); ! 2114: break; ! 2115: } ! 2116: break; ! 2117: ! 2118: case OPMOD: ! 2119: if( ISINT(type) ) ! 2120: { ! 2121: cp->ci = ap->ci % bp->ci; ! 2122: break; ! 2123: } ! 2124: else ! 2125: fatal("inline mod of noninteger"); ! 2126: ! 2127: default: /* relational ops */ ! 2128: switch(type) ! 2129: { ! 2130: case TYSHORT: ! 2131: case TYLONG: ! 2132: if(ap->ci < bp->ci) ! 2133: k = -1; ! 2134: else if(ap->ci == bp->ci) ! 2135: k = 0; ! 2136: else k = 1; ! 2137: break; ! 2138: case TYREAL: ! 2139: case TYDREAL: ! 2140: if(ap->cd[0] < bp->cd[0]) ! 2141: k = -1; ! 2142: else if(ap->cd[0] == bp->cd[0]) ! 2143: k = 0; ! 2144: else k = 1; ! 2145: break; ! 2146: case TYCOMPLEX: ! 2147: case TYDCOMPLEX: ! 2148: if(ap->cd[0] == bp->cd[0] && ! 2149: ap->cd[1] == bp->cd[1] ) ! 2150: k = 0; ! 2151: else k = 1; ! 2152: break; ! 2153: } ! 2154: ! 2155: switch(opcode) ! 2156: { ! 2157: case OPEQ: ! 2158: cp->ci = (k == 0); ! 2159: break; ! 2160: case OPNE: ! 2161: cp->ci = (k != 0); ! 2162: break; ! 2163: case OPGT: ! 2164: cp->ci = (k == 1); ! 2165: break; ! 2166: case OPLT: ! 2167: cp->ci = (k == -1); ! 2168: break; ! 2169: case OPGE: ! 2170: cp->ci = (k >= 0); ! 2171: break; ! 2172: case OPLE: ! 2173: cp->ci = (k <= 0); ! 2174: break; ! 2175: } ! 2176: break; ! 2177: } ! 2178: } ! 2179: ! 2180: ! 2181: ! 2182: ! 2183: conssgn(p) ! 2184: register expptr p; ! 2185: { ! 2186: if( ! ISCONST(p) ) ! 2187: fatal( "sgn(nonconstant)" ); ! 2188: ! 2189: switch(p->headblock.vtype) ! 2190: { ! 2191: case TYSHORT: ! 2192: case TYLONG: ! 2193: if(p->constblock.const.ci > 0) return(1); ! 2194: if(p->constblock.const.ci < 0) return(-1); ! 2195: return(0); ! 2196: ! 2197: case TYREAL: ! 2198: case TYDREAL: ! 2199: if(p->constblock.const.cd[0] > 0) return(1); ! 2200: if(p->constblock.const.cd[0] < 0) return(-1); ! 2201: return(0); ! 2202: ! 2203: case TYCOMPLEX: ! 2204: case TYDCOMPLEX: ! 2205: return(p->constblock.const.cd[0]!=0 || p->constblock.const.cd[1]!=0); ! 2206: ! 2207: default: ! 2208: badtype( "conssgn", p->constblock.vtype); ! 2209: } ! 2210: /* NOTREACHED */ ! 2211: } ! 2212: ! 2213: char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" }; ! 2214: ! 2215: ! 2216: LOCAL expptr mkpower(p) ! 2217: register expptr p; ! 2218: { ! 2219: register expptr q, lp, rp; ! 2220: int ltype, rtype, mtype; ! 2221: ! 2222: lp = p->exprblock.leftp; ! 2223: rp = p->exprblock.rightp; ! 2224: ltype = lp->headblock.vtype; ! 2225: rtype = rp->headblock.vtype; ! 2226: ! 2227: if(ISICON(rp)) ! 2228: { ! 2229: if(rp->constblock.const.ci == 0) ! 2230: { ! 2231: frexpr(p); ! 2232: if( ISINT(ltype) ) ! 2233: return( ICON(1) ); ! 2234: else ! 2235: return( (expptr) putconst( mkconv(ltype, ICON(1))) ); ! 2236: } ! 2237: if(rp->constblock.const.ci < 0) ! 2238: { ! 2239: if( ISINT(ltype) ) ! 2240: { ! 2241: frexpr(p); ! 2242: err("integer**negative"); ! 2243: return( errnode() ); ! 2244: } ! 2245: rp->constblock.const.ci = - rp->constblock.const.ci; ! 2246: p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp)); ! 2247: } ! 2248: if(rp->constblock.const.ci == 1) ! 2249: { ! 2250: frexpr(rp); ! 2251: free( (charptr) p ); ! 2252: return(lp); ! 2253: } ! 2254: ! 2255: if( ONEOF(ltype, MSKINT|MSKREAL) ) ! 2256: { ! 2257: p->exprblock.vtype = ltype; ! 2258: return(p); ! 2259: } ! 2260: } ! 2261: if( ISINT(rtype) ) ! 2262: { ! 2263: if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) ) ! 2264: q = call2(TYSHORT, "pow_hh", lp, rp); ! 2265: else { ! 2266: if(ltype == TYSHORT) ! 2267: { ! 2268: ltype = TYLONG; ! 2269: lp = mkconv(TYLONG,lp); ! 2270: } ! 2271: q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp)); ! 2272: } ! 2273: } ! 2274: else if( ISREAL( (mtype = maxtype(ltype,rtype)) )) ! 2275: q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp)); ! 2276: else { ! 2277: q = call2(TYDCOMPLEX, "pow_zz", ! 2278: mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp)); ! 2279: if(mtype == TYCOMPLEX) ! 2280: q = mkconv(TYCOMPLEX, q); ! 2281: } ! 2282: free( (charptr) p ); ! 2283: return(q); ! 2284: } ! 2285: ! 2286: ! 2287: ! 2288: /* Complex Division. Same code as in Runtime Library ! 2289: */ ! 2290: ! 2291: struct dcomplex { double dreal, dimag; }; ! 2292: ! 2293: ! 2294: LOCAL zdiv(c, a, b) ! 2295: register struct dcomplex *a, *b, *c; ! 2296: { ! 2297: double ratio, den; ! 2298: double abr, abi; ! 2299: ! 2300: if( (abr = b->dreal) < 0.) ! 2301: abr = - abr; ! 2302: if( (abi = b->dimag) < 0.) ! 2303: abi = - abi; ! 2304: if( abr <= abi ) ! 2305: { ! 2306: if(abi == 0) ! 2307: fatal("complex division by zero"); ! 2308: ratio = b->dreal / b->dimag ; ! 2309: den = b->dimag * (1 + ratio*ratio); ! 2310: c->dreal = (a->dreal*ratio + a->dimag) / den; ! 2311: c->dimag = (a->dimag*ratio - a->dreal) / den; ! 2312: } ! 2313: ! 2314: else ! 2315: { ! 2316: ratio = b->dimag / b->dreal ; ! 2317: den = b->dreal * (1 + ratio*ratio); ! 2318: c->dreal = (a->dreal + a->dimag*ratio) / den; ! 2319: c->dimag = (a->dimag - a->dreal*ratio) / den; ! 2320: } ! 2321: ! 2322: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.