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