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