1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: static char *sccsid[] = "@(#)expr.c	5.8 (Berkeley) 5/9/86";
   9: #endif not lint
  10: 
  11: /*
  12:  * expr.c
  13:  *
  14:  * Routines for handling expressions, f77 compiler pass 1.
  15:  *
  16:  * University of Utah CS Dept modification history:
  17:  *
  18:  * $Log:	expr.c,v $
  19:  * Revision 5.13  86/05/07  18:54:23  donn
  20:  * Adjusted the warning for OPEQ with logical operands -- this is now printed
  21:  * in mkexpr since cktype can be called several times on the same operands
  22:  * (argh -- how slow can this compiler get?!).
  23:  *
  24:  * Revision 5.12  86/05/07  17:40:54  donn
  25:  * Make the lengths of expr nodes be copied by cpexpr and freed by frexpr.
  26:  *
  27:  * Revision 5.11  86/05/07  16:57:17  donn
  28:  * Logical data is supposed to be compared using .eqv. and .neqv., but we
  29:  * will support .eq. and .ne. with a warning.  Other relational operators
  30:  * now provoke errors when used with logical operands.
  31:  *
  32:  * Revision 5.10  86/04/26  13:24:30  donn
  33:  * Someone forgot about comparisons of logical constants in consbinop() --
  34:  * the results of such tests were garbage.
  35:  *
  36:  * Revision 5.9  86/02/20  23:38:31  donn
  37:  * Fix memory management problem with reordering of array dimension and
  38:  * substring code in mklhs().
  39:  *
  40:  * Revision 5.8  85/12/20  21:37:58  donn
  41:  * Fix bug in mklhs() that caused the 'first character' substring parameter
  42:  * to be evaluated twice.
  43:  *
  44:  * Revision 5.7  85/12/20  19:42:05  donn
  45:  * Be more specfic -- name the offending subroutine when it's used as a
  46:  * function.
  47:  *
  48:  * Revision 5.6  85/12/19  20:08:12  donn
  49:  * Don't optimize first/last char values when they contain function calls
  50:  * or array references.
  51:  *
  52:  * Revision 5.5  85/12/19  00:35:22  donn
  53:  * Lots of changes for handling hardware errors which can crop up when
  54:  * evaluating constant expressions.
  55:  *
  56:  * Revision 5.4  85/11/25  00:23:53  donn
  57:  * 4.3 beta
  58:  *
  59:  * Revision 5.3  85/08/10  05:48:16  donn
  60:  * Fixed another of my goofs in the substring parameter conversion code.
  61:  *
  62:  * Revision 5.2  85/08/10  04:13:51  donn
  63:  * Jerry Berkman's change to call pow() directly rather than indirectly
  64:  * through pow_dd, in mkpower().
  65:  *
  66:  * Revision 5.1  85/08/10  03:44:19  donn
  67:  * 4.3 alpha
  68:  *
  69:  * Revision 3.16  85/06/21  16:38:09  donn
  70:  * The fix to mkprim() didn't handle null substring parameters (sigh).
  71:  *
  72:  * Revision 3.15  85/06/04  04:37:03  donn
  73:  * Changed mkprim() to force substring parameters to be integral types.
  74:  *
  75:  * Revision 3.14  85/06/04  03:41:52  donn
  76:  * Change impldcl() to handle functions of type 'undefined'.
  77:  *
  78:  * Revision 3.13  85/05/06  23:14:55  donn
  79:  * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get
  80:  * a temporary when converting character strings to integers; previously we
  81:  * were having problems because mkconv() was called after tempalloc().
  82:  *
  83:  * Revision 3.12  85/03/18  08:07:47  donn
  84:  * Fixes to help out with short integers -- if integers are by default short,
  85:  * then so are constants; and if addresses can't be stored in shorts, complain.
  86:  *
  87:  * Revision 3.11  85/03/16  22:31:27  donn
  88:  * Added hack to mkconv() to allow character values of length > 1 to be
  89:  * converted to numeric types, for Helge Skrivervik.  Note that this does
  90:  * not affect use of the intrinsic ichar() conversion.
  91:  *
  92:  * Revision 3.10  85/01/15  21:06:47  donn
  93:  * Changed mkconv() to comment on implicit conversions; added intrconv() for
  94:  * use with explicit conversions by intrinsic functions.
  95:  *
  96:  * Revision 3.9  85/01/11  21:05:49  donn
  97:  * Added changes to implement SAVE statements.
  98:  *
  99:  * Revision 3.8  84/12/17  02:21:06  donn
 100:  * Added a test to prevent constant folding from being done on expressions
 101:  * whose type is not known at that point in mkexpr().
 102:  *
 103:  * Revision 3.7  84/12/11  21:14:17  donn
 104:  * Removed obnoxious 'excess precision' warning.
 105:  *
 106:  * Revision 3.6  84/11/23  01:00:36  donn
 107:  * Added code to trim excess precision from single-precision constants, and
 108:  * to warn the user when this occurs.
 109:  *
 110:  * Revision 3.5  84/11/23  00:10:39  donn
 111:  * Changed stfcall() to remark on argument type clashes in 'calls' to
 112:  * statement functions.
 113:  *
 114:  * Revision 3.4  84/11/22  21:21:17  donn
 115:  * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics.
 116:  *
 117:  * Revision 3.3  84/11/12  18:26:14  donn
 118:  * Shuffled some code around so that the compiler remembers to free some vleng
 119:  * structures which used to just sit around.
 120:  *
 121:  * Revision 3.2  84/10/16  19:24:15  donn
 122:  * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent
 123:  * core dumps by replacing bad subscripts with good ones.
 124:  *
 125:  * Revision 3.1  84/10/13  01:31:32  donn
 126:  * Merged Jerry Berkman's version into mine.
 127:  *
 128:  * Revision 2.7  84/09/27  15:42:52  donn
 129:  * The last fix for multiplying undeclared variables by 0 isn't sufficient,
 130:  * since the type of the 0 may not be the (implicit) type of the variable.
 131:  * I added a hack to check the implicit type of implicitly declared
 132:  * variables...
 133:  *
 134:  * Revision 2.6  84/09/14  19:34:03  donn
 135:  * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert
 136:  * 0 to type UNKNOWN, which is illegal.  Fix is to use native type instead.
 137:  * Not sure how correct (or important) this is...
 138:  *
 139:  * Revision 2.5  84/08/05  23:05:27  donn
 140:  * Added fixes to prevent fixexpr() from slicing and dicing complex conversions
 141:  * with two operands.
 142:  *
 143:  * Revision 2.4  84/08/05  17:34:48  donn
 144:  * Added an optimization to mklhs() to detect substrings of the form ch(i:i)
 145:  * and assign constant length 1 to them.
 146:  *
 147:  * Revision 2.3  84/07/19  19:38:33  donn
 148:  * Added a typecast to the last fix.  Somehow I missed it the first time...
 149:  *
 150:  * Revision 2.2  84/07/19  17:19:57  donn
 151:  * Caused OPPAREN expressions to inherit the length of their operands, so
 152:  * that parenthesized character expressions work correctly.
 153:  *
 154:  * Revision 2.1  84/07/19  12:03:02  donn
 155:  * Changed comment headers for UofU.
 156:  *
 157:  * Revision 1.2  84/04/06  20:12:17  donn
 158:  * Fixed bug which caused programs with mixed-type multiplications involving
 159:  * the constant 0 to choke the compiler.
 160:  *
 161:  */
 162: 
 163: #include "defs.h"
 164: 
 165: 
 166: /* little routines to create constant blocks */
 167: 
 168: Constp mkconst(t)
 169: register int t;
 170: {
 171: register Constp p;
 172: 
 173: p = ALLOC(Constblock);
 174: p->tag = TCONST;
 175: p->vtype = t;
 176: return(p);
 177: }
 178: 
 179: 
 180: expptr mklogcon(l)
 181: register int l;
 182: {
 183: register Constp  p;
 184: 
 185: p = mkconst(TYLOGICAL);
 186: p->const.ci = l;
 187: return( (expptr) p );
 188: }
 189: 
 190: 
 191: 
 192: expptr mkintcon(l)
 193: ftnint l;
 194: {
 195: register Constp p;
 196: int usetype;
 197: 
 198: if(tyint == TYSHORT)
 199:   {
 200:     short s = l;
 201:     if(l != s)
 202:       usetype = TYLONG;
 203:     else
 204:       usetype = TYSHORT;
 205:   }
 206: else
 207:   usetype = tyint;
 208: p = mkconst(usetype);
 209: p->const.ci = l;
 210: return( (expptr) p );
 211: }
 212: 
 213: 
 214: 
 215: expptr mkaddcon(l)
 216: register int l;
 217: {
 218: register Constp p;
 219: 
 220: p = mkconst(TYADDR);
 221: p->const.ci = l;
 222: return( (expptr) p );
 223: }
 224: 
 225: 
 226: 
 227: expptr mkrealcon(t, d)
 228: register int t;
 229: double d;
 230: {
 231: register Constp p;
 232: 
 233: if(t == TYREAL)
 234:   {
 235:     float f = d;
 236:     if(f != d)
 237:       {
 238: #ifdef notdef
 239:     warn("excess precision in real constant lost");
 240: #endif notdef
 241:     d = f;
 242:       }
 243:   }
 244: p = mkconst(t);
 245: p->const.cd[0] = d;
 246: return( (expptr) p );
 247: }
 248: 
 249: 
 250: expptr mkbitcon(shift, leng, s)
 251: int shift;
 252: register int leng;
 253: register char *s;
 254: {
 255:   Constp p;
 256:   register int i, j, k;
 257:   register char *bp;
 258:   int size;
 259: 
 260:   size = (shift*leng + BYTESIZE -1)/BYTESIZE;
 261:   bp = (char *) ckalloc(size);
 262: 
 263:   i = 0;
 264: 
 265: #if (TARGET == PDP11 || TARGET == VAX)
 266:   j = 0;
 267: #else
 268:   j = size;
 269: #endif
 270: 
 271:   k = 0;
 272: 
 273:   while (leng > 0)
 274:     {
 275:       k |= (hextoi(s[--leng]) << i);
 276:       i += shift;
 277:       if (i >= BYTESIZE)
 278:     {
 279: #if (TARGET == PDP11 || TARGET == VAX)
 280:       bp[j++] = k & MAXBYTE;
 281: #else
 282:       bp[--j] = k & MAXBYTE;
 283: #endif
 284:       k = k >> BYTESIZE;
 285:       i -= BYTESIZE;
 286:     }
 287:     }
 288: 
 289:   if (k != 0)
 290: #if (TARGET == PDP11 || TARGET == VAX)
 291:     bp[j++] = k;
 292: #else
 293:     bp[--j] = k;
 294: #endif
 295: 
 296:   p = mkconst(TYBITSTR);
 297:   p->vleng = ICON(size);
 298:   p->const.ccp = bp;
 299: 
 300:   return ((expptr) p);
 301: }
 302: 
 303: 
 304: 
 305: expptr mkstrcon(l,v)
 306: int l;
 307: register char *v;
 308: {
 309: register Constp p;
 310: register char *s;
 311: 
 312: p = mkconst(TYCHAR);
 313: p->vleng = ICON(l);
 314: p->const.ccp = s = (char *) ckalloc(l);
 315: while(--l >= 0)
 316:     *s++ = *v++;
 317: return( (expptr) p );
 318: }
 319: 
 320: 
 321: expptr mkcxcon(realp,imagp)
 322: register expptr realp, imagp;
 323: {
 324: int rtype, itype;
 325: register Constp p;
 326: 
 327: rtype = realp->headblock.vtype;
 328: itype = imagp->headblock.vtype;
 329: 
 330: if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
 331:     {
 332:     p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
 333:     if( ISINT(rtype) )
 334:         p->const.cd[0] = realp->constblock.const.ci;
 335:     else    p->const.cd[0] = realp->constblock.const.cd[0];
 336:     if( ISINT(itype) )
 337:         p->const.cd[1] = imagp->constblock.const.ci;
 338:     else    p->const.cd[1] = imagp->constblock.const.cd[0];
 339:     }
 340: else
 341:     {
 342:     err("invalid complex constant");
 343:     p = (Constp) errnode();
 344:     }
 345: 
 346: frexpr(realp);
 347: frexpr(imagp);
 348: return( (expptr) p );
 349: }
 350: 
 351: 
 352: expptr errnode()
 353: {
 354: struct Errorblock *p;
 355: p = ALLOC(Errorblock);
 356: p->tag = TERROR;
 357: p->vtype = TYERROR;
 358: return( (expptr) p );
 359: }
 360: 
 361: 
 362: 
 363: 
 364: 
 365: expptr mkconv(t, p)
 366: register int t;
 367: register expptr p;
 368: {
 369: register expptr q;
 370: Addrp r, s;
 371: register int pt;
 372: expptr opconv();
 373: 
 374: if(t==TYUNKNOWN || t==TYERROR)
 375:     badtype("mkconv", t);
 376: pt = p->headblock.vtype;
 377: if(t == pt)
 378:     return(p);
 379: 
 380: if( pt == TYCHAR && ISNUMERIC(t) )
 381:     {
 382:     warn("implicit conversion of character to numeric type");
 383: 
 384:     /*
 385: 	 * Ugly kluge to copy character values into numerics.
 386: 	 */
 387:     s = mkaltemp(t, ENULL);
 388:     r = (Addrp) cpexpr(s);
 389:     r->vtype = TYCHAR;
 390:     r->varleng = typesize[t];
 391:     r->vleng = mkintcon(r->varleng);
 392:     q = mkexpr(OPASSIGN, r, p);
 393:     q = mkexpr(OPCOMMA, q, s);
 394:     return(q);
 395:     }
 396: 
 397: #if SZADDR > SZSHORT
 398: if( pt == TYADDR && t == TYSHORT)
 399:     {
 400:     err("insufficient precision to hold address type");
 401:     return( errnode() );
 402:     }
 403: #endif
 404: if( pt == TYADDR && ISNUMERIC(t) )
 405:     warn("implicit conversion of address to numeric type");
 406: 
 407: if( ISCONST(p) && pt!=TYADDR)
 408:     {
 409:     q = (expptr) mkconst(t);
 410:     consconv(t, &(q->constblock.const),
 411:         p->constblock.vtype, &(p->constblock.const) );
 412:     frexpr(p);
 413:     }
 414: #if TARGET == PDP11
 415: else if(ISINT(t) && pt==TYCHAR)
 416:     {
 417:     q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
 418:     if(t == TYLONG)
 419:         q = opconv(q, TYLONG);
 420:     }
 421: #endif
 422: else
 423:     q = opconv(p, t);
 424: 
 425: if(t == TYCHAR)
 426:     q->constblock.vleng = ICON(1);
 427: return(q);
 428: }
 429: 
 430: 
 431: 
 432: /* intrinsic conversions */
 433: expptr intrconv(t, p)
 434: register int t;
 435: register expptr p;
 436: {
 437: register expptr q;
 438: register int pt;
 439: expptr opconv();
 440: 
 441: if(t==TYUNKNOWN || t==TYERROR)
 442:     badtype("intrconv", t);
 443: pt = p->headblock.vtype;
 444: if(t == pt)
 445:     return(p);
 446: 
 447: else if( ISCONST(p) && pt!=TYADDR)
 448:     {
 449:     q = (expptr) mkconst(t);
 450:     consconv(t, &(q->constblock.const),
 451:         p->constblock.vtype, &(p->constblock.const) );
 452:     frexpr(p);
 453:     }
 454: #if TARGET == PDP11
 455: else if(ISINT(t) && pt==TYCHAR)
 456:     {
 457:     q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
 458:     if(t == TYLONG)
 459:         q = opconv(q, TYLONG);
 460:     }
 461: #endif
 462: else
 463:     q = opconv(p, t);
 464: 
 465: if(t == TYCHAR)
 466:     q->constblock.vleng = ICON(1);
 467: return(q);
 468: }
 469: 
 470: 
 471: 
 472: expptr opconv(p, t)
 473: expptr p;
 474: int t;
 475: {
 476: register expptr q;
 477: 
 478: q = mkexpr(OPCONV, p, PNULL);
 479: q->headblock.vtype = t;
 480: return(q);
 481: }
 482: 
 483: 
 484: 
 485: expptr addrof(p)
 486: expptr p;
 487: {
 488: return( mkexpr(OPADDR, p, PNULL) );
 489: }
 490: 
 491: 
 492: 
 493: tagptr cpexpr(p)
 494: register tagptr p;
 495: {
 496: register tagptr e;
 497: int tag;
 498: register chainp ep, pp;
 499: tagptr cpblock();
 500: 
 501: static int blksize[ ] =
 502:     {   0,
 503:         sizeof(struct Nameblock),
 504:         sizeof(struct Constblock),
 505:         sizeof(struct Exprblock),
 506:         sizeof(struct Addrblock),
 507:         sizeof(struct Tempblock),
 508:         sizeof(struct Primblock),
 509:         sizeof(struct Listblock),
 510:         sizeof(struct Errorblock)
 511:     };
 512: 
 513: if(p == NULL)
 514:     return(NULL);
 515: 
 516: if( (tag = p->tag) == TNAME)
 517:     return(p);
 518: 
 519: e = cpblock( blksize[p->tag] , p);
 520: 
 521: switch(tag)
 522:     {
 523:     case TCONST:
 524:         if(e->constblock.vtype == TYCHAR)
 525:             {
 526:             e->constblock.const.ccp =
 527:                 copyn(1+strlen(e->constblock.const.ccp),
 528:                     e->constblock.const.ccp);
 529:             e->constblock.vleng =
 530:                 (expptr) cpexpr(e->constblock.vleng);
 531:             }
 532:     case TERROR:
 533:         break;
 534: 
 535:     case TEXPR:
 536:         e->exprblock.leftp =  (expptr) cpexpr(p->exprblock.leftp);
 537:         e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
 538:         e->addrblock.vleng =  (expptr) cpexpr(e->addrblock.vleng);
 539:         break;
 540: 
 541:     case TLIST:
 542:         if(pp = p->listblock.listp)
 543:             {
 544:             ep = e->listblock.listp =
 545:                 mkchain( cpexpr(pp->datap), CHNULL);
 546:             for(pp = pp->nextp ; pp ; pp = pp->nextp)
 547:                 ep = ep->nextp =
 548:                     mkchain( cpexpr(pp->datap), CHNULL);
 549:             }
 550:         break;
 551: 
 552:     case TADDR:
 553:         e->addrblock.vleng = (expptr)  cpexpr(e->addrblock.vleng);
 554:         e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
 555:         e->addrblock.istemp = NO;
 556:         break;
 557: 
 558:     case TTEMP:
 559:         e->tempblock.vleng = (expptr)  cpexpr(e->tempblock.vleng);
 560:         e->tempblock.istemp = NO;
 561:         break;
 562: 
 563:     case TPRIM:
 564:         e->primblock.argsp = (struct Listblock *)
 565:                     cpexpr(e->primblock.argsp);
 566:         e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
 567:         e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
 568:         break;
 569: 
 570:     default:
 571:         badtag("cpexpr", tag);
 572:     }
 573: 
 574: return(e);
 575: }
 576: 
 577: frexpr(p)
 578: register tagptr p;
 579: {
 580: register chainp q;
 581: 
 582: if(p == NULL)
 583:     return;
 584: 
 585: switch(p->tag)
 586:     {
 587:     case TCONST:
 588:         switch (p->constblock.vtype)
 589:             {
 590:             case TYBITSTR:
 591:             case TYCHAR:
 592:             case TYHOLLERITH:
 593:                 free( (charptr) (p->constblock.const.ccp) );
 594:                 frexpr(p->constblock.vleng);
 595:             }
 596:         break;
 597: 
 598:     case TADDR:
 599:         if (!optimflag && p->addrblock.istemp)
 600:             {
 601:             frtemp(p);
 602:             return;
 603:             }
 604:         frexpr(p->addrblock.vleng);
 605:         frexpr(p->addrblock.memoffset);
 606:         break;
 607: 
 608:     case TTEMP:
 609:         frexpr(p->tempblock.vleng);
 610:         break;
 611: 
 612:     case TERROR:
 613:         break;
 614: 
 615:     case TNAME:
 616:         return;
 617: 
 618:     case TPRIM:
 619:         frexpr(p->primblock.argsp);
 620:         frexpr(p->primblock.fcharp);
 621:         frexpr(p->primblock.lcharp);
 622:         break;
 623: 
 624:     case TEXPR:
 625:         frexpr(p->exprblock.leftp);
 626:         if(p->exprblock.rightp)
 627:             frexpr(p->exprblock.rightp);
 628:         if(p->exprblock.vleng)
 629:             frexpr(p->exprblock.vleng);
 630:         break;
 631: 
 632:     case TLIST:
 633:         for(q = p->listblock.listp ; q ; q = q->nextp)
 634:             frexpr(q->datap);
 635:         frchain( &(p->listblock.listp) );
 636:         break;
 637: 
 638:     default:
 639:         badtag("frexpr", p->tag);
 640:     }
 641: 
 642: free( (charptr) p );
 643: }
 644: 
 645: /* fix up types in expression; replace subtrees and convert
 646:    names to address blocks */
 647: 
 648: expptr fixtype(p)
 649: register tagptr p;
 650: {
 651: 
 652: if(p == 0)
 653:     return(0);
 654: 
 655: switch(p->tag)
 656:     {
 657:     case TCONST:
 658:         return( (expptr) p );
 659: 
 660:     case TADDR:
 661:         p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
 662:         return( (expptr) p);
 663: 
 664:     case TTEMP:
 665:         return( (expptr) p);
 666: 
 667:     case TERROR:
 668:         return( (expptr) p);
 669: 
 670:     default:
 671:         badtag("fixtype", p->tag);
 672: 
 673:     case TEXPR:
 674:         return( fixexpr(p) );
 675: 
 676:     case TLIST:
 677:         return( (expptr) p );
 678: 
 679:     case TPRIM:
 680:         if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
 681:             {
 682:             if(p->primblock.namep->vtype == TYSUBR)
 683:                 {
 684:                 dclerr("function invocation of subroutine",
 685:                     p->primblock.namep);
 686:                 return( errnode() );
 687:                 }
 688:             else
 689:                 return( mkfunct(p) );
 690:             }
 691:         else    return( mklhs(p) );
 692:     }
 693: }
 694: 
 695: 
 696: 
 697: 
 698: 
 699: /* special case tree transformations and cleanups of expression trees */
 700: 
 701: expptr fixexpr(p)
 702: register Exprp p;
 703: {
 704: expptr lp;
 705: register expptr rp;
 706: register expptr q;
 707: int opcode, ltype, rtype, ptype, mtype;
 708: expptr lconst, rconst;
 709: expptr mkpower();
 710: 
 711: if( ISERROR(p) )
 712:     return( (expptr) p );
 713: else if(p->tag != TEXPR)
 714:     badtag("fixexpr", p->tag);
 715: opcode = p->opcode;
 716: if (ISCONST(p->leftp))
 717:     lconst = (expptr) cpexpr(p->leftp);
 718: else
 719:     lconst = NULL;
 720: if (p->rightp && ISCONST(p->rightp))
 721:     rconst = (expptr) cpexpr(p->rightp);
 722: else
 723:     rconst = NULL;
 724: lp = p->leftp = fixtype(p->leftp);
 725: ltype = lp->headblock.vtype;
 726: if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP)
 727:     {
 728:     err("left side of assignment must be variable");
 729:     frexpr(p);
 730:     return( errnode() );
 731:     }
 732: 
 733: if(p->rightp)
 734:     {
 735:     rp = p->rightp = fixtype(p->rightp);
 736:     rtype = rp->headblock.vtype;
 737:     }
 738: else
 739:     {
 740:     rp = NULL;
 741:     rtype = 0;
 742:     }
 743: 
 744: if(ltype==TYERROR || rtype==TYERROR)
 745:     {
 746:     frexpr(p);
 747:     frexpr(lconst);
 748:     frexpr(rconst);
 749:     return( errnode() );
 750:     }
 751: 
 752: /* force folding if possible */
 753: if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
 754:     {
 755:     q = mkexpr(opcode, lp, rp);
 756:     if( ISCONST(q) )
 757:         {
 758:         frexpr(lconst);
 759:         frexpr(rconst);
 760:         return(q);
 761:         }
 762:     free( (charptr) q );    /* constants did not fold */
 763:     }
 764: 
 765: if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
 766:     {
 767:     frexpr(p);
 768:     frexpr(lconst);
 769:     frexpr(rconst);
 770:     return( errnode() );
 771:     }
 772: 
 773: switch(opcode)
 774:     {
 775:     case OPCONCAT:
 776:         if(p->vleng == NULL)
 777:             p->vleng = mkexpr(OPPLUS,
 778:                 cpexpr(lp->headblock.vleng),
 779:                 cpexpr(rp->headblock.vleng) );
 780:         break;
 781: 
 782:     case OPASSIGN:
 783:     case OPPLUSEQ:
 784:     case OPSTAREQ:
 785:         if(ltype == rtype)
 786:             break;
 787:         if( ! rconst && ISREAL(ltype) && ISREAL(rtype) )
 788:             break;
 789:         if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
 790:             break;
 791:         if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
 792: #if FAMILY==PCC
 793:             && typesize[ltype]>=typesize[rtype] )
 794: #else
 795:             && typesize[ltype]==typesize[rtype] )
 796: #endif
 797:             break;
 798:         if (rconst)
 799:             {
 800:             p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) );
 801:             frexpr(rp);
 802:             }
 803:         else
 804:             p->rightp = fixtype(mkconv(ptype, rp));
 805:         break;
 806: 
 807:     case OPSLASH:
 808:         if( ISCOMPLEX(rtype) )
 809:             {
 810:             p = (Exprp) call2(ptype,
 811:                 ptype==TYCOMPLEX? "c_div" : "z_div",
 812:                 mkconv(ptype, lp), mkconv(ptype, rp) );
 813:             break;
 814:             }
 815:     case OPPLUS:
 816:     case OPMINUS:
 817:     case OPSTAR:
 818:     case OPMOD:
 819:         if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) ||
 820:             (rtype==TYREAL && ! rconst ) ))
 821:             break;
 822:         if( ISCOMPLEX(ptype) )
 823:             break;
 824:         if(ltype != ptype)
 825:             if (lconst)
 826:                 {
 827:                 p->leftp = fixtype(mkconv(ptype,
 828:                         cpexpr(lconst)));
 829:                 frexpr(lp);
 830:                 }
 831:             else
 832:                 p->leftp = fixtype(mkconv(ptype,lp));
 833:         if(rtype != ptype)
 834:             if (rconst)
 835:                 {
 836:                 p->rightp = fixtype(mkconv(ptype,
 837:                         cpexpr(rconst)));
 838:                 frexpr(rp);
 839:                 }
 840:             else
 841:                 p->rightp = fixtype(mkconv(ptype,rp));
 842:         break;
 843: 
 844:     case OPPOWER:
 845:         return( mkpower(p) );
 846: 
 847:     case OPLT:
 848:     case OPLE:
 849:     case OPGT:
 850:     case OPGE:
 851:     case OPEQ:
 852:     case OPNE:
 853:         if(ltype == rtype)
 854:             break;
 855:         mtype = cktype(OPMINUS, ltype, rtype);
 856:         if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) ||
 857:             (rtype==TYREAL && ! rconst) ))
 858:             break;
 859:         if( ISCOMPLEX(mtype) )
 860:             break;
 861:         if(ltype != mtype)
 862:             if (lconst)
 863:                 {
 864:                 p->leftp = fixtype(mkconv(mtype,
 865:                         cpexpr(lconst)));
 866:                 frexpr(lp);
 867:                 }
 868:             else
 869:                 p->leftp = fixtype(mkconv(mtype,lp));
 870:         if(rtype != mtype)
 871:             if (rconst)
 872:                 {
 873:                 p->rightp = fixtype(mkconv(mtype,
 874:                         cpexpr(rconst)));
 875:                 frexpr(rp);
 876:                 }
 877:             else
 878:                 p->rightp = fixtype(mkconv(mtype,rp));
 879:         break;
 880: 
 881: 
 882:     case OPCONV:
 883:         if(ISCOMPLEX(p->vtype))
 884:             {
 885:             ptype = cktype(OPCONV, p->vtype, ltype);
 886:             if(p->rightp)
 887:                 ptype = cktype(OPCONV, ptype, rtype);
 888:             break;
 889:             }
 890:         ptype = cktype(OPCONV, p->vtype, ltype);
 891:         if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
 892:             {
 893:             lp->exprblock.rightp =
 894:                 fixtype( mkconv(ptype, lp->exprblock.rightp) );
 895:             free( (charptr) p );
 896:             p = (Exprp) lp;
 897:             }
 898:         break;
 899: 
 900:     case OPADDR:
 901:         if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
 902:             fatal("addr of addr");
 903:         break;
 904: 
 905:     case OPCOMMA:
 906:     case OPQUEST:
 907:     case OPCOLON:
 908:         break;
 909: 
 910:     case OPPAREN:
 911:         p->vleng = (expptr) cpexpr( lp->headblock.vleng );
 912:         break;
 913: 
 914:     case OPMIN:
 915:     case OPMAX:
 916:         ptype = p->vtype;
 917:         break;
 918: 
 919:     default:
 920:         break;
 921:     }
 922: 
 923: p->vtype = ptype;
 924: frexpr(lconst);
 925: frexpr(rconst);
 926: return((expptr) p);
 927: }
 928: 
 929: #if SZINT < SZLONG
 930: /*
 931:    for efficient subscripting, replace long ints by shorts
 932:    in easy places
 933: */
 934: 
 935: expptr shorten(p)
 936: register expptr p;
 937: {
 938: register expptr q;
 939: 
 940: if(p->headblock.vtype != TYLONG)
 941:     return(p);
 942: 
 943: switch(p->tag)
 944:     {
 945:     case TERROR:
 946:     case TLIST:
 947:         return(p);
 948: 
 949:     case TCONST:
 950:     case TADDR:
 951:         return( mkconv(TYINT,p) );
 952: 
 953:     case TEXPR:
 954:         break;
 955: 
 956:     default:
 957:         badtag("shorten", p->tag);
 958:     }
 959: 
 960: switch(p->exprblock.opcode)
 961:     {
 962:     case OPPLUS:
 963:     case OPMINUS:
 964:     case OPSTAR:
 965:         q = shorten( cpexpr(p->exprblock.rightp) );
 966:         if(q->headblock.vtype == TYINT)
 967:             {
 968:             p->exprblock.leftp = shorten(p->exprblock.leftp);
 969:             if(p->exprblock.leftp->headblock.vtype == TYLONG)
 970:                 frexpr(q);
 971:             else
 972:                 {
 973:                 frexpr(p->exprblock.rightp);
 974:                 p->exprblock.rightp = q;
 975:                 p->exprblock.vtype = TYINT;
 976:                 }
 977:             }
 978:         break;
 979: 
 980:     case OPNEG:
 981:     case OPPAREN:
 982:         p->exprblock.leftp = shorten(p->exprblock.leftp);
 983:         if(p->exprblock.leftp->headblock.vtype == TYINT)
 984:             p->exprblock.vtype = TYINT;
 985:         break;
 986: 
 987:     case OPCALL:
 988:     case OPCCALL:
 989:         p = mkconv(TYINT,p);
 990:         break;
 991:     default:
 992:         break;
 993:     }
 994: 
 995: return(p);
 996: }
 997: #endif
 998: 
 999: /* fix an argument list, taking due care for special first level cases */
1000: 
1001: fixargs(doput, p0)
1002: int doput;  /* doput is true if the function is not intrinsic;
1003: 		   was used to decide whether to do a putconst,
1004: 		   but this is no longer done here (Feb82)*/
1005: struct Listblock *p0;
1006: {
1007: register chainp p;
1008: register tagptr q, t;
1009: register int qtag;
1010: int nargs;
1011: Addrp mkscalar();
1012: 
1013: nargs = 0;
1014: if(p0)
1015:     for(p = p0->listp ; p ; p = p->nextp)
1016:     {
1017:     ++nargs;
1018:     q = p->datap;
1019:     qtag = q->tag;
1020:     if(qtag == TCONST)
1021:         {
1022:         if(q->constblock.vtype == TYSHORT)
1023:             q = (tagptr) mkconv(tyint, q);
1024:         p->datap = q ;
1025:         }
1026:     else if(qtag==TPRIM && q->primblock.argsp==0 &&
1027:         q->primblock.namep->vclass==CLPROC)
1028:             p->datap = (tagptr) mkaddr(q->primblock.namep);
1029:     else if(qtag==TPRIM && q->primblock.argsp==0 &&
1030:         q->primblock.namep->vdim!=NULL)
1031:             p->datap = (tagptr) mkscalar(q->primblock.namep);
1032:     else if(qtag==TPRIM && q->primblock.argsp==0 &&
1033:         q->primblock.namep->vdovar &&
1034:         (t = (tagptr) memversion(q->primblock.namep)) )
1035:             p->datap = (tagptr) fixtype(t);
1036:     else
1037:         p->datap = (tagptr) fixtype(q);
1038:     }
1039: return(nargs);
1040: }
1041: 
1042: 
1043: Addrp mkscalar(np)
1044: register Namep np;
1045: {
1046: register Addrp ap;
1047: 
1048: vardcl(np);
1049: ap = mkaddr(np);
1050: 
1051: #if TARGET == VAX
1052:     /* on the VAX, prolog causes array arguments
1053: 	   to point at the (0,...,0) element, except when
1054: 	   subscript checking is on
1055: 	*/
1056: #ifdef SDB
1057:     if( !checksubs && !sdbflag && np->vstg==STGARG)
1058: #else
1059:     if( !checksubs && np->vstg==STGARG)
1060: #endif
1061:         {
1062:         register struct Dimblock *dp;
1063:         dp = np->vdim;
1064:         frexpr(ap->memoffset);
1065:         ap->memoffset = mkexpr(OPSTAR,
1066:                 (np->vtype==TYCHAR ?
1067:                     cpexpr(np->vleng) :
1068:                     (tagptr)ICON(typesize[np->vtype]) ),
1069:                 cpexpr(dp->baseoffset) );
1070:         }
1071: #endif
1072: return(ap);
1073: }
1074: 
1075: 
1076: 
1077: 
1078: 
1079: expptr mkfunct(p)
1080: register struct Primblock *p;
1081: {
1082: struct Entrypoint *ep;
1083: Addrp ap;
1084: struct Extsym *extp;
1085: register Namep np;
1086: register expptr q;
1087: expptr intrcall(), stfcall();
1088: int k, nargs;
1089: int class;
1090: 
1091: if(p->tag != TPRIM)
1092:     return( errnode() );
1093: 
1094: np = p->namep;
1095: class = np->vclass;
1096: 
1097: if(class == CLUNKNOWN)
1098:     {
1099:     np->vclass = class = CLPROC;
1100:     if(np->vstg == STGUNKNOWN)
1101:         {
1102:         if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
1103:             {
1104:             np->vstg = STGINTR;
1105:             np->vardesc.varno = k;
1106:             np->vprocclass = PINTRINSIC;
1107:             }
1108:         else
1109:             {
1110:             extp = mkext( varunder(VL,np->varname) );
1111:             extp->extstg = STGEXT;
1112:             np->vstg = STGEXT;
1113:             np->vardesc.varno = extp - extsymtab;
1114:             np->vprocclass = PEXTERNAL;
1115:             }
1116:         }
1117:     else if(np->vstg==STGARG)
1118:         {
1119:         if(np->vtype!=TYCHAR && !ftn66flag)
1120:             warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
1121:         np->vprocclass = PEXTERNAL;
1122:         }
1123:     }
1124: 
1125: if(class != CLPROC)
1126:     fatali("invalid class code %d for function", class);
1127: if(p->fcharp || p->lcharp)
1128:     {
1129:     err("no substring of function call");
1130:     goto error;
1131:     }
1132: impldcl(np);
1133: nargs = fixargs( np->vprocclass!=PINTRINSIC,  p->argsp);
1134: 
1135: switch(np->vprocclass)
1136:     {
1137:     case PEXTERNAL:
1138:         ap = mkaddr(np);
1139:     call:
1140:         q = mkexpr(OPCALL, ap, p->argsp);
1141:         if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
1142:             {
1143:             err("attempt to use untyped function");
1144:             goto error;
1145:             }
1146:         if(np->vleng)
1147:             q->exprblock.vleng = (expptr) cpexpr(np->vleng);
1148:         break;
1149: 
1150:     case PINTRINSIC:
1151:         q = intrcall(np, p->argsp, nargs);
1152:         break;
1153: 
1154:     case PSTFUNCT:
1155:         q = stfcall(np, p->argsp);
1156:         break;
1157: 
1158:     case PTHISPROC:
1159:         warn("recursive call");
1160:         for(ep = entries ; ep ; ep = ep->entnextp)
1161:             if(ep->enamep == np)
1162:                 break;
1163:         if(ep == NULL)
1164:             fatal("mkfunct: impossible recursion");
1165:         ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
1166:         goto call;
1167: 
1168:     default:
1169:         fatali("mkfunct: impossible vprocclass %d",
1170:             (int) (np->vprocclass) );
1171:     }
1172: free( (charptr) p );
1173: return(q);
1174: 
1175: error:
1176:     frexpr(p);
1177:     return( errnode() );
1178: }
1179: 
1180: 
1181: 
1182: LOCAL expptr stfcall(np, actlist)
1183: Namep np;
1184: struct Listblock *actlist;
1185: {
1186: register chainp actuals;
1187: int nargs;
1188: chainp oactp, formals;
1189: int type;
1190: expptr q, rhs, ap;
1191: Namep tnp;
1192: register struct Rplblock *rp;
1193: struct Rplblock *tlist;
1194: 
1195: if(actlist)
1196:     {
1197:     actuals = actlist->listp;
1198:     free( (charptr) actlist);
1199:     }
1200: else
1201:     actuals = NULL;
1202: oactp = actuals;
1203: 
1204: nargs = 0;
1205: tlist = NULL;
1206: if( (type = np->vtype) == TYUNKNOWN)
1207:     {
1208:     err("attempt to use untyped statement function");
1209:     q = errnode();
1210:     goto ret;
1211:     }
1212: formals = (chainp) (np->varxptr.vstfdesc->datap);
1213: rhs = (expptr) (np->varxptr.vstfdesc->nextp);
1214: 
1215: /* copy actual arguments into temporaries */
1216: while(actuals!=NULL && formals!=NULL)
1217:     {
1218:     rp = ALLOC(Rplblock);
1219:     rp->rplnp = tnp = (Namep) (formals->datap);
1220:     ap = fixtype(actuals->datap);
1221:     if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
1222:        && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) )
1223:         {
1224:         rp->rplvp = (expptr) ap;
1225:         rp->rplxp = NULL;
1226:         rp->rpltag = ap->tag;
1227:         }
1228:     else    {
1229:         rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
1230:         rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
1231:         if( (rp->rpltag = rp->rplxp->tag) == TERROR)
1232:             err("disagreement of argument types in statement function call");
1233:         else if(tnp->vtype!=ap->headblock.vtype)
1234:             warn("argument type mismatch in statement function");
1235:         }
1236:     rp->rplnextp = tlist;
1237:     tlist = rp;
1238:     actuals = actuals->nextp;
1239:     formals = formals->nextp;
1240:     ++nargs;
1241:     }
1242: 
1243: if(actuals!=NULL || formals!=NULL)
1244:     err("statement function definition and argument list differ");
1245: 
1246: /*
1247:    now push down names involved in formal argument list, then
1248:    evaluate rhs of statement function definition in this environment
1249: */
1250: 
1251: if(tlist)   /* put tlist in front of the rpllist */
1252:     {
1253:     for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
1254:         ;
1255:     rp->rplnextp = rpllist;
1256:     rpllist = tlist;
1257:     }
1258: 
1259: q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
1260: 
1261: /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
1262: while(--nargs >= 0)
1263:     {
1264:     if(rpllist->rplxp)
1265:         q = mkexpr(OPCOMMA, rpllist->rplxp, q);
1266:     rp = rpllist->rplnextp;
1267:     frexpr(rpllist->rplvp);
1268:     free(rpllist);
1269:     rpllist = rp;
1270:     }
1271: 
1272: ret:
1273:     frchain( &oactp );
1274:     return(q);
1275: }
1276: 
1277: 
1278: 
1279: 
1280: Addrp mkplace(np)
1281: register Namep np;
1282: {
1283: register Addrp s;
1284: register struct Rplblock *rp;
1285: int regn;
1286: 
1287: /* is name on the replace list? */
1288: 
1289: for(rp = rpllist ; rp ; rp = rp->rplnextp)
1290:     {
1291:     if(np == rp->rplnp)
1292:         {
1293:         if(rp->rpltag == TNAME)
1294:             {
1295:             np = (Namep) (rp->rplvp);
1296:             break;
1297:             }
1298:         else    return( (Addrp) cpexpr(rp->rplvp) );
1299:         }
1300:     }
1301: 
1302: /* is variable a DO index in a register ? */
1303: 
1304: if(np->vdovar && ( (regn = inregister(np)) >= 0) )
1305:     if(np->vtype == TYERROR)
1306:         return( (Addrp) errnode() );
1307:     else
1308:         {
1309:         s = ALLOC(Addrblock);
1310:         s->tag = TADDR;
1311:         s->vstg = STGREG;
1312:         s->vtype = TYIREG;
1313:         s->issaved = np->vsave;
1314:         s->memno = regn;
1315:         s->memoffset = ICON(0);
1316:         return(s);
1317:         }
1318: 
1319: vardcl(np);
1320: return(mkaddr(np));
1321: }
1322: 
1323: 
1324: 
1325: 
1326: expptr mklhs(p)
1327: register struct Primblock *p;
1328: {
1329: expptr suboffset();
1330: expptr ep = ENULL;
1331: register Addrp s;
1332: Namep np;
1333: 
1334: if(p->tag != TPRIM)
1335:     return( (expptr) p );
1336: np = p->namep;
1337: 
1338: s = mkplace(np);
1339: if(s->tag!=TADDR || s->vstg==STGREG)
1340:     {
1341:     free( (charptr) p );
1342:     return( (expptr) s );
1343:     }
1344: 
1345: /* do the substring part */
1346: 
1347: if(p->fcharp || p->lcharp)
1348:     {
1349:     if(np->vtype != TYCHAR)
1350:         errstr("substring of noncharacter %s", varstr(VL,np->varname));
1351:     else    {
1352:         if(p->lcharp == NULL)
1353:             p->lcharp = (expptr) cpexpr(s->vleng);
1354:         frexpr(s->vleng);
1355:         if(p->fcharp)
1356:             {
1357:             if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM
1358:             && p->fcharp->primblock.namep == p->lcharp->primblock.namep
1359:             && p->fcharp->primblock.argsp == NULL
1360:             && p->lcharp->primblock.argsp == NULL)
1361:                 /* A trivial optimization -- upper == lower */
1362:                 s->vleng = ICON(1);
1363:             else
1364:                 {
1365:                 if(p->fcharp->tag == TEXPR
1366:                 || (p->fcharp->tag == TPRIM
1367:                    && p->fcharp->primblock.argsp != NULL))
1368:                     {
1369:                     ep = fixtype(cpexpr(p->fcharp));
1370:                     p->fcharp = (expptr) mktemp(ep->headblock.vtype, ENULL);
1371:                     }
1372:                 s->vleng = mkexpr(OPMINUS, p->lcharp,
1373:                  mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
1374:                 }
1375:             }
1376:         else
1377:             s->vleng = p->lcharp;
1378:         }
1379:     }
1380: 
1381: /* compute the address modified by subscripts */
1382: 
1383: s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
1384: frexpr(p->argsp);
1385: p->argsp = NULL;
1386: 
1387: s->vleng = fixtype( s->vleng );
1388: s->memoffset = fixtype( s->memoffset );
1389: if(ep)
1390:     /* this code depends on memoffset being evaluated before vleng */
1391:     s->memoffset = mkexpr(OPCOMMA, mkexpr(OPASSIGN, cpexpr(p->fcharp), ep), s->memoffset);
1392: frexpr(p->fcharp);
1393: free( (charptr) p );
1394: return( (expptr) s );
1395: }
1396: 
1397: 
1398: 
1399: 
1400: 
1401: deregister(np)
1402: Namep np;
1403: {
1404: if(nregvar>0 && regnamep[nregvar-1]==np)
1405:     {
1406:     --nregvar;
1407: #if FAMILY == DMR
1408:     putnreg();
1409: #endif
1410:     }
1411: }
1412: 
1413: 
1414: 
1415: 
1416: Addrp memversion(np)
1417: register Namep np;
1418: {
1419: register Addrp s;
1420: 
1421: if(np->vdovar==NO || (inregister(np)<0) )
1422:     return(NULL);
1423: np->vdovar = NO;
1424: s = mkplace(np);
1425: np->vdovar = YES;
1426: return(s);
1427: }
1428: 
1429: 
1430: 
1431: inregister(np)
1432: register Namep np;
1433: {
1434: register int i;
1435: 
1436: for(i = 0 ; i < nregvar ; ++i)
1437:     if(regnamep[i] == np)
1438:         return( regnum[i] );
1439: return(-1);
1440: }
1441: 
1442: 
1443: 
1444: 
1445: enregister(np)
1446: Namep np;
1447: {
1448: if( inregister(np) >= 0)
1449:     return(YES);
1450: if(nregvar >= maxregvar)
1451:     return(NO);
1452: vardcl(np);
1453: if( ONEOF(np->vtype, MSKIREG) )
1454:     {
1455:     regnamep[nregvar++] = np;
1456:     if(nregvar > highregvar)
1457:         highregvar = nregvar;
1458: #if FAMILY == DMR
1459:     putnreg();
1460: #endif
1461:     return(YES);
1462:     }
1463: else
1464:     return(NO);
1465: }
1466: 
1467: 
1468: 
1469: 
1470: expptr suboffset(p)
1471: register struct Primblock *p;
1472: {
1473: int n;
1474: expptr size;
1475: expptr oftwo();
1476: chainp cp;
1477: expptr offp, prod;
1478: expptr subcheck();
1479: struct Dimblock *dimp;
1480: expptr sub[MAXDIM+1];
1481: register Namep np;
1482: 
1483: np = p->namep;
1484: offp = ICON(0);
1485: n = 0;
1486: if(p->argsp)
1487:     for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp)
1488:         {
1489:         sub[n] = fixtype(cpexpr(cp->datap));
1490:         if ( ! ISINT(sub[n]->headblock.vtype)) {
1491:             errstr("%s: non-integer subscript expression",
1492:                 varstr(VL, np->varname) );
1493:             /* Provide a substitute -- go on to find more errors */
1494:             frexpr(sub[n]);
1495:             sub[n] = ICON(1);
1496:         }
1497:         if(n > maxdim)
1498:             {
1499:                char str[28+VL];
1500:                sprintf(str, "%s: more than %d subscripts",
1501:                 varstr(VL, np->varname), maxdim );
1502:                err( str );
1503:             break;
1504:             }
1505:         }
1506: 
1507: dimp = np->vdim;
1508: if(n>0 && dimp==NULL)
1509:     errstr("%s: subscripts on scalar variable",
1510:         varstr(VL, np->varname), maxdim );
1511: else if(dimp && dimp->ndim!=n)
1512:     errstr("wrong number of subscripts on %s",
1513:         varstr(VL, np->varname) );
1514: else if(n > 0)
1515:     {
1516:     prod = sub[--n];
1517:     while( --n >= 0)
1518:         prod = mkexpr(OPPLUS, sub[n],
1519:             mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
1520: #if TARGET == VAX
1521: #ifdef SDB
1522:     if(checksubs || np->vstg!=STGARG || sdbflag)
1523: #else
1524:     if(checksubs || np->vstg!=STGARG)
1525: #endif
1526:         prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1527: #else
1528:     prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1529: #endif
1530:     if(checksubs)
1531:         prod = subcheck(np, prod);
1532:     size = np->vtype == TYCHAR ?
1533:         (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
1534:     if (!oftwo(size))
1535:         prod = mkexpr(OPSTAR, prod, size);
1536:     else
1537:         prod = mkexpr(OPLSHIFT,prod,oftwo(size));
1538: 
1539:     offp = mkexpr(OPPLUS, offp, prod);
1540:     }
1541: 
1542: if(p->fcharp && np->vtype==TYCHAR)
1543:     offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
1544: 
1545: return(offp);
1546: }
1547: 
1548: 
1549: 
1550: 
1551: expptr subcheck(np, p)
1552: Namep np;
1553: register expptr p;
1554: {
1555: struct Dimblock *dimp;
1556: expptr t, checkvar, checkcond, badcall;
1557: 
1558: dimp = np->vdim;
1559: if(dimp->nelt == NULL)
1560:     return(p);  /* don't check arrays with * bounds */
1561: checkvar = NULL;
1562: checkcond = NULL;
1563: if( ISICON(p) )
1564:     {
1565:     if(p->constblock.const.ci < 0)
1566:         goto badsub;
1567:     if( ISICON(dimp->nelt) )
1568:         if(p->constblock.const.ci < dimp->nelt->constblock.const.ci)
1569:             return(p);
1570:         else
1571:             goto badsub;
1572:     }
1573: if(p->tag==TADDR && p->addrblock.vstg==STGREG)
1574:     {
1575:     checkvar = (expptr) cpexpr(p);
1576:     t = p;
1577:     }
1578: else    {
1579:     checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
1580:     t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
1581:     }
1582: checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
1583: if( ! ISICON(p) )
1584:     checkcond = mkexpr(OPAND, checkcond,
1585:             mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
1586: 
1587: badcall = call4(p->headblock.vtype, "s_rnge",
1588:         mkstrcon(VL, np->varname),
1589:         mkconv(TYLONG,  cpexpr(checkvar)),
1590:         mkstrcon(XL, procname),
1591:         ICON(lineno) );
1592: badcall->exprblock.opcode = OPCCALL;
1593: p = mkexpr(OPQUEST, checkcond,
1594:     mkexpr(OPCOLON, checkvar, badcall));
1595: 
1596: return(p);
1597: 
1598: badsub:
1599:     frexpr(p);
1600:     errstr("subscript on variable %s out of range", varstr(VL,np->varname));
1601:     return ( ICON(0) );
1602: }
1603: 
1604: 
1605: 
1606: 
1607: Addrp mkaddr(p)
1608: register Namep p;
1609: {
1610: struct Extsym *extp;
1611: register Addrp t;
1612: Addrp intraddr();
1613: 
1614: switch( p->vstg)
1615:     {
1616:     case STGUNKNOWN:
1617:         if(p->vclass != CLPROC)
1618:             break;
1619:         extp = mkext( varunder(VL, p->varname) );
1620:         extp->extstg = STGEXT;
1621:         p->vstg = STGEXT;
1622:         p->vardesc.varno = extp - extsymtab;
1623:         p->vprocclass = PEXTERNAL;
1624: 
1625:     case STGCOMMON:
1626:     case STGEXT:
1627:     case STGBSS:
1628:     case STGINIT:
1629:     case STGEQUIV:
1630:     case STGARG:
1631:     case STGLENG:
1632:     case STGAUTO:
1633:         t = ALLOC(Addrblock);
1634:         t->tag = TADDR;
1635:         if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
1636:             t->vclass = CLVAR;
1637:         else
1638:             t->vclass = p->vclass;
1639:         t->vtype = p->vtype;
1640:         t->vstg = p->vstg;
1641:         t->memno = p->vardesc.varno;
1642:         t->issaved = p->vsave;
1643:                 if(p->vdim) t->isarray = YES;
1644:         t->memoffset = ICON(p->voffset);
1645:         if(p->vleng)
1646:             {
1647:             t->vleng = (expptr) cpexpr(p->vleng);
1648:             if( ISICON(t->vleng) )
1649:                 t->varleng = t->vleng->constblock.const.ci;
1650:             }
1651:         if (p->vstg == STGBSS)
1652:             t->varsize = p->varsize;
1653:         else if (p->vstg == STGEQUIV)
1654:             t->varsize = eqvclass[t->memno].eqvleng;
1655:         return(t);
1656: 
1657:     case STGINTR:
1658:         return( intraddr(p) );
1659: 
1660:     }
1661: /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
1662: badstg("mkaddr", p->vstg);
1663: /* NOTREACHED */
1664: }
1665: 
1666: 
1667: 
1668: 
1669: Addrp mkarg(type, argno)
1670: int type, argno;
1671: {
1672: register Addrp p;
1673: 
1674: p = ALLOC(Addrblock);
1675: p->tag = TADDR;
1676: p->vtype = type;
1677: p->vclass = CLVAR;
1678: p->vstg = (type==TYLENG ? STGLENG : STGARG);
1679: p->memno = argno;
1680: return(p);
1681: }
1682: 
1683: 
1684: 
1685: 
1686: expptr mkprim(v, args, substr)
1687: register union
1688:     {
1689:     struct Paramblock paramblock;
1690:     struct Nameblock nameblock;
1691:     struct Headblock headblock;
1692:     } *v;
1693: struct Listblock *args;
1694: chainp substr;
1695: {
1696: register struct Primblock *p;
1697: 
1698: if(v->headblock.vclass == CLPARAM)
1699:     {
1700:     if(args || substr)
1701:         {
1702:         errstr("no qualifiers on parameter name %s",
1703:             varstr(VL,v->paramblock.varname));
1704:         frexpr(args);
1705:         if(substr)
1706:             {
1707:             frexpr(substr->datap);
1708:             frexpr(substr->nextp->datap);
1709:             frchain(&substr);
1710:             }
1711:         frexpr(v);
1712:         return( errnode() );
1713:         }
1714:     return( (expptr) cpexpr(v->paramblock.paramval) );
1715:     }
1716: 
1717: p = ALLOC(Primblock);
1718: p->tag = TPRIM;
1719: p->vtype = v->nameblock.vtype;
1720: p->namep = (Namep) v;
1721: p->argsp = args;
1722: if(substr)
1723:     {
1724:     p->fcharp = (expptr) substr->datap;
1725:     if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype))
1726:         p->fcharp = mkconv(TYINT, p->fcharp);
1727:     p->lcharp = (expptr) substr->nextp->datap;
1728:     if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype))
1729:         p->lcharp = mkconv(TYINT, p->lcharp);
1730:     frchain(&substr);
1731:     }
1732: return( (expptr) p);
1733: }
1734: 
1735: 
1736: 
1737: vardcl(v)
1738: register Namep v;
1739: {
1740: int nelt;
1741: struct Dimblock *t;
1742: Addrp p;
1743: expptr neltp;
1744: int eltsize;
1745: int varsize;
1746: int tsize;
1747: int align;
1748: 
1749: if(v->vdcldone)
1750:     return;
1751: if(v->vclass == CLNAMELIST)
1752:     return;
1753: 
1754: if(v->vtype == TYUNKNOWN)
1755:     impldcl(v);
1756: if(v->vclass == CLUNKNOWN)
1757:     v->vclass = CLVAR;
1758: else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
1759:     {
1760:     dclerr("used both as variable and non-variable", v);
1761:     return;
1762:     }
1763: if(v->vstg==STGUNKNOWN)
1764:     v->vstg = implstg[ letter(v->varname[0]) ];
1765: 
1766: switch(v->vstg)
1767:     {
1768:     case STGBSS:
1769:         v->vardesc.varno = ++lastvarno;
1770:         if (v->vclass != CLVAR)
1771:             break;
1772:         nelt = 1;
1773:         t = v->vdim;
1774:         if (t)
1775:             {
1776:             neltp = t->nelt;
1777:             if (neltp && ISICON(neltp))
1778:                 nelt = neltp->constblock.const.ci;
1779:             else
1780:                 dclerr("improperly dimensioned array", v);
1781:             }
1782: 
1783:         if (v->vtype == TYCHAR)
1784:             {
1785:             v->vleng = fixtype(v->vleng);
1786:             if (v->vleng == NULL)
1787:                 eltsize = typesize[TYCHAR];
1788:             else if (ISICON(v->vleng))
1789:                 eltsize = typesize[TYCHAR] *
1790:                     v->vleng->constblock.const.ci;
1791:             else if (v->vleng->tag != TERROR)
1792:                 {
1793:                 errstr("nonconstant string length on %s",
1794:                     varstr(VL, v->varname));
1795:                 eltsize = 0;
1796:                 }
1797:             }
1798:         else
1799:             eltsize = typesize[v->vtype];
1800: 
1801:         v->varsize = nelt * eltsize;
1802:         break;
1803:     case STGAUTO:
1804:         if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
1805:             break;
1806:         nelt = 1;
1807:         if(t = v->vdim)
1808:             if( (neltp = t->nelt) && ISCONST(neltp) )
1809:                 nelt = neltp->constblock.const.ci;
1810:             else
1811:                 dclerr("adjustable automatic array", v);
1812:         p = autovar(nelt, v->vtype, v->vleng);
1813:         v->vardesc.varno = p->memno;
1814:         v->voffset = p->memoffset->constblock.const.ci;
1815:         frexpr(p);
1816:         break;
1817: 
1818:     default:
1819:         break;
1820:     }
1821: v->vdcldone = YES;
1822: }
1823: 
1824: 
1825: 
1826: 
1827: impldcl(p)
1828: register Namep p;
1829: {
1830: register int k;
1831: int type, leng;
1832: 
1833: if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
1834:     return;
1835: if(p->vtype == TYUNKNOWN)
1836:     {
1837:     k = letter(p->varname[0]);
1838:     type = impltype[ k ];
1839:     leng = implleng[ k ];
1840:     if(type == TYUNKNOWN)
1841:         {
1842:         if(p->vclass == CLPROC)
1843:             dclerr("attempt to use function of undefined type", p);
1844:         else
1845:             dclerr("attempt to use undefined variable", p);
1846:         type = TYERROR;
1847:         leng = 1;
1848:         }
1849:     settype(p, type, leng);
1850:     }
1851: }
1852: 
1853: 
1854: 
1855: 
1856: LOCAL letter(c)
1857: register int c;
1858: {
1859: if( isupper(c) )
1860:     c = tolower(c);
1861: return(c - 'a');
1862: }
1863: 
1864: #define ICONEQ(z, c)  (ISICON(z) && z->constblock.const.ci==c)
1865: #define COMMUTE { e = lp;  lp = rp;  rp = e; }
1866: 
1867: 
1868: expptr mkexpr(opcode, lp, rp)
1869: int opcode;
1870: register expptr lp, rp;
1871: {
1872: register expptr e, e1;
1873: int etype;
1874: int ltype, rtype;
1875: int ltag, rtag;
1876: expptr q, q1;
1877: expptr fold();
1878: int k;
1879: 
1880: ltype = lp->headblock.vtype;
1881: ltag = lp->tag;
1882: if(rp && opcode!=OPCALL && opcode!=OPCCALL)
1883:     {
1884:     rtype = rp->headblock.vtype;
1885:     rtag = rp->tag;
1886:     }
1887: else    {
1888:     rtype = 0;
1889:     rtag = 0;
1890:     }
1891: 
1892: /*
1893:  * Yuck.  Why can't we fold constants AFTER
1894:  * variables are implicitly declared???
1895:  */
1896: if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
1897:     {
1898:     k = letter(lp->primblock.namep->varname[0]);
1899:     ltype = impltype[ k ];
1900:     }
1901: if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
1902:     {
1903:     k = letter(rp->primblock.namep->varname[0]);
1904:     rtype = impltype[ k ];
1905:     }
1906: 
1907: /*
1908:  * Eliminate all but the topmost OPPAREN operator when folding constants.
1909:  */
1910: if(lp->tag == TEXPR &&
1911:    lp->exprblock.opcode == OPPAREN &&
1912:    lp->exprblock.leftp->tag == TCONST)
1913:     {
1914:     q = (expptr) cpexpr(lp->exprblock.leftp);
1915:     frexpr(lp);
1916:     lp = q;
1917:     ltag = TCONST;
1918:     ltype = lp->constblock.vtype;
1919:     }
1920: if(rp &&
1921:    rp->tag == TEXPR &&
1922:    rp->exprblock.opcode == OPPAREN &&
1923:    rp->exprblock.leftp->tag == TCONST)
1924:     {
1925:     q = (expptr) cpexpr(rp->exprblock.leftp);
1926:     frexpr(rp);
1927:     rp = q;
1928:     rtag = TCONST;
1929:     rtype = rp->constblock.vtype;
1930:     }
1931: 
1932: etype = cktype(opcode, ltype, rtype);
1933: if(etype == TYERROR)
1934:     goto error;
1935: 
1936: if(ltag==TCONST && (rp==0 || rtag==TCONST) )
1937:     goto makenode;
1938: if(etype == TYUNKNOWN)
1939:     goto makenode;
1940: 
1941: switch(opcode)
1942:     {
1943:     /* check for multiplication by 0 and 1 and addition to 0 */
1944: 
1945:     case OPSTAR:
1946:         if( ISCONST(lp) )
1947:             COMMUTE
1948: 
1949:         if( ISICON(rp) )
1950:             {
1951:             if(rp->constblock.const.ci == 0)
1952:                 {
1953:                 if(etype == TYUNKNOWN)
1954:                     break;
1955:                 rp = mkconv(etype, rp);
1956:                 goto retright;
1957:                 }
1958:             if ((lp->tag == TEXPR) &&
1959:                 ((lp->exprblock.opcode == OPPLUS) ||
1960:                  (lp->exprblock.opcode == OPMINUS)) &&
1961:                 ISCONST(lp->exprblock.rightp) &&
1962:                 ISINT(lp->exprblock.rightp->constblock.vtype))
1963:                 {
1964:                 q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
1965:                        cpexpr(rp));
1966:                 q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
1967:                 q = mkexpr(lp->exprblock.opcode, q, q1);
1968:                 free ((char *) lp);
1969:                 return q;
1970:                 }
1971:             else
1972:                 goto mulop;
1973:             }
1974:         break;
1975: 
1976:     case OPSLASH:
1977:     case OPMOD:
1978:         if( ICONEQ(rp, 0) )
1979:             {
1980:             err("attempted division by zero");
1981:             rp = ICON(1);
1982:             break;
1983:             }
1984:         if(opcode == OPMOD)
1985:             break;
1986: 
1987: 
1988:     mulop:
1989:         if( ISICON(rp) )
1990:             {
1991:             if(rp->constblock.const.ci == 1)
1992:                 goto retleft;
1993: 
1994:             if(rp->constblock.const.ci == -1)
1995:                 {
1996:                 frexpr(rp);
1997:                 return( mkexpr(OPNEG, lp, PNULL) );
1998:                 }
1999:             }
2000: 
2001:         if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
2002:             {
2003:             if(opcode == OPSTAR)
2004:                 e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
2005:             else  if(ISICON(rp) &&
2006:                 (lp->exprblock.rightp->constblock.const.ci %
2007:                     rp->constblock.const.ci) == 0)
2008:                 e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
2009:             else    break;
2010: 
2011:             e1 = lp->exprblock.leftp;
2012:             free( (charptr) lp );
2013:             return( mkexpr(OPSTAR, e1, e) );
2014:             }
2015:         break;
2016: 
2017: 
2018:     case OPPLUS:
2019:         if( ISCONST(lp) )
2020:             COMMUTE
2021:         goto addop;
2022: 
2023:     case OPMINUS:
2024:         if( ICONEQ(lp, 0) )
2025:             {
2026:             frexpr(lp);
2027:             return( mkexpr(OPNEG, rp, ENULL) );
2028:             }
2029: 
2030:         if( ISCONST(rp) )
2031:             {
2032:             opcode = OPPLUS;
2033:             consnegop(rp);
2034:             }
2035: 
2036:     addop:
2037:         if( ISICON(rp) )
2038:             {
2039:             if(rp->constblock.const.ci == 0)
2040:                 goto retleft;
2041:             if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
2042:                 {
2043:                 e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
2044:                 e1 = lp->exprblock.leftp;
2045:                 free( (charptr) lp );
2046:                 return( mkexpr(OPPLUS, e1, e) );
2047:                 }
2048:             }
2049:         break;
2050: 
2051: 
2052:     case OPPOWER:
2053:         break;
2054: 
2055:     case OPNEG:
2056:         if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
2057:             {
2058:             e = lp->exprblock.leftp;
2059:             free( (charptr) lp );
2060:             return(e);
2061:             }
2062:         break;
2063: 
2064:     case OPNOT:
2065:         if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
2066:             {
2067:             e = lp->exprblock.leftp;
2068:             free( (charptr) lp );
2069:             return(e);
2070:             }
2071:         break;
2072: 
2073:     case OPCALL:
2074:     case OPCCALL:
2075:         etype = ltype;
2076:         if(rp!=NULL && rp->listblock.listp==NULL)
2077:             {
2078:             free( (charptr) rp );
2079:             rp = NULL;
2080:             }
2081:         break;
2082: 
2083:     case OPAND:
2084:     case OPOR:
2085:         if( ISCONST(lp) )
2086:             COMMUTE
2087: 
2088:         if( ISCONST(rp) )
2089:             {
2090:             if(rp->constblock.const.ci == 0)
2091:                 if(opcode == OPOR)
2092:                     goto retleft;
2093:                 else
2094:                     goto retright;
2095:             else if(opcode == OPOR)
2096:                 goto retright;
2097:             else
2098:                 goto retleft;
2099:             }
2100:     case OPLSHIFT:
2101:         if (ISICON(rp))
2102:             {
2103:             if (rp->constblock.const.ci == 0)
2104:                 goto retleft;
2105:             if ((lp->tag == TEXPR) &&
2106:                 ((lp->exprblock.opcode == OPPLUS) ||
2107:                  (lp->exprblock.opcode == OPMINUS)) &&
2108:                 ISICON(lp->exprblock.rightp))
2109:                 {
2110:                 q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
2111:                     cpexpr(rp));
2112:                 q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
2113:                 q = mkexpr(lp->exprblock.opcode, q, q1);
2114:                 free((char *) lp);
2115:                 return q;
2116:                 }
2117:             }
2118: 
2119:     case OPEQV:
2120:     case OPNEQV:
2121: 
2122:     case OPBITAND:
2123:     case OPBITOR:
2124:     case OPBITXOR:
2125:     case OPBITNOT:
2126:     case OPRSHIFT:
2127: 
2128:     case OPLT:
2129:     case OPGT:
2130:     case OPLE:
2131:     case OPGE:
2132:         break;
2133: 
2134:     case OPEQ:
2135:     case OPNE:
2136:         /*
2137: 		 * This warning is here instead of in cktype because
2138: 		 * cktype repeats warnings (it can be run more
2139: 		 * than once on an expression).
2140: 		 */
2141:         if (ltype == TYLOGICAL)
2142:             warn("logical operand of nonlogical operator");
2143:         break;
2144: 
2145:     case OPCONCAT:
2146: 
2147:     case OPMIN:
2148:     case OPMAX:
2149: 
2150:     case OPASSIGN:
2151:     case OPPLUSEQ:
2152:     case OPSTAREQ:
2153: 
2154:     case OPCONV:
2155:     case OPADDR:
2156: 
2157:     case OPCOMMA:
2158:     case OPQUEST:
2159:     case OPCOLON:
2160: 
2161:     case OPPAREN:
2162:         break;
2163: 
2164:     default:
2165:         badop("mkexpr", opcode);
2166:     }
2167: 
2168: makenode:
2169: 
2170: e = (expptr) ALLOC(Exprblock);
2171: e->exprblock.tag = TEXPR;
2172: e->exprblock.opcode = opcode;
2173: e->exprblock.vtype = etype;
2174: e->exprblock.leftp = lp;
2175: e->exprblock.rightp = rp;
2176: if(ltag==TCONST && (rp==0 || rtag==TCONST) )
2177:     e = fold(e);
2178: return(e);
2179: 
2180: retleft:
2181:     frexpr(rp);
2182:     return(lp);
2183: 
2184: retright:
2185:     frexpr(lp);
2186:     return(rp);
2187: 
2188: error:
2189:     frexpr(lp);
2190:     if(rp && opcode!=OPCALL && opcode!=OPCCALL)
2191:         frexpr(rp);
2192:     return( errnode() );
2193: }
2194: 
2195: #define ERR(s)   { errs = s; goto error; }
2196: 
2197: cktype(op, lt, rt)
2198: register int op, lt, rt;
2199: {
2200: char *errs;
2201: 
2202: if(lt==TYERROR || rt==TYERROR)
2203:     goto error1;
2204: 
2205: if(lt==TYUNKNOWN)
2206:     return(TYUNKNOWN);
2207: if(rt==TYUNKNOWN)
2208:     if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
2209:         op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
2210:         return(TYUNKNOWN);
2211: 
2212: switch(op)
2213:     {
2214:     case OPPLUS:
2215:     case OPMINUS:
2216:     case OPSTAR:
2217:     case OPSLASH:
2218:     case OPPOWER:
2219:     case OPMOD:
2220:         if( ISNUMERIC(lt) && ISNUMERIC(rt) )
2221:             return( maxtype(lt, rt) );
2222:         ERR("nonarithmetic operand of arithmetic operator")
2223: 
2224:     case OPNEG:
2225:         if( ISNUMERIC(lt) )
2226:             return(lt);
2227:         ERR("nonarithmetic operand of negation")
2228: 
2229:     case OPNOT:
2230:         if(lt == TYLOGICAL)
2231:             return(TYLOGICAL);
2232:         ERR("NOT of nonlogical")
2233: 
2234:     case OPAND:
2235:     case OPOR:
2236:     case OPEQV:
2237:     case OPNEQV:
2238:         if(lt==TYLOGICAL && rt==TYLOGICAL)
2239:             return(TYLOGICAL);
2240:         ERR("nonlogical operand of logical operator")
2241: 
2242:     case OPLT:
2243:     case OPGT:
2244:     case OPLE:
2245:     case OPGE:
2246:     case OPEQ:
2247:     case OPNE:
2248:         if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
2249:             {
2250:             if(lt != rt)
2251:                 ERR("illegal comparison")
2252:             if(lt == TYLOGICAL)
2253:                 {
2254:                 if(op!=OPEQ && op!=OPNE)
2255:                     ERR("order comparison of complex data")
2256:                 }
2257:             }
2258: 
2259:         else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
2260:             {
2261:             if(op!=OPEQ && op!=OPNE)
2262:                 ERR("order comparison of complex data")
2263:             }
2264: 
2265:         else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
2266:             ERR("comparison of nonarithmetic data")
2267:         return(TYLOGICAL);
2268: 
2269:     case OPCONCAT:
2270:         if(lt==TYCHAR && rt==TYCHAR)
2271:             return(TYCHAR);
2272:         ERR("concatenation of nonchar data")
2273: 
2274:     case OPCALL:
2275:     case OPCCALL:
2276:         return(lt);
2277: 
2278:     case OPADDR:
2279:         return(TYADDR);
2280: 
2281:     case OPCONV:
2282:         if(ISCOMPLEX(lt))
2283:             {
2284:             if(ISNUMERIC(rt))
2285:                 return(lt);
2286:             ERR("impossible conversion")
2287:             }
2288:         if(rt == 0)
2289:             return(0);
2290:         if(lt==TYCHAR && ISINT(rt) )
2291:             return(TYCHAR);
2292:     case OPASSIGN:
2293:     case OPPLUSEQ:
2294:     case OPSTAREQ:
2295:         if( ISINT(lt) && rt==TYCHAR)
2296:             return(lt);
2297:         if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
2298:             if(op!=OPASSIGN || lt!=rt)
2299:                 {
2300: /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
2301: /* debug fatal("impossible conversion.  possible compiler bug"); */
2302:                 ERR("impossible conversion")
2303:                 }
2304:         return(lt);
2305: 
2306:     case OPMIN:
2307:     case OPMAX:
2308:     case OPBITOR:
2309:     case OPBITAND:
2310:     case OPBITXOR:
2311:     case OPBITNOT:
2312:     case OPLSHIFT:
2313:     case OPRSHIFT:
2314:     case OPPAREN:
2315:         return(lt);
2316: 
2317:     case OPCOMMA:
2318:     case OPQUEST:
2319:     case OPCOLON:
2320:         return(rt);
2321: 
2322:     default:
2323:         badop("cktype", op);
2324:     }
2325: error:  err(errs);
2326: error1: return(TYERROR);
2327: }
2328: 
2329: #if HERE == VAX
2330: #include <signal.h>
2331: #include <setjmp.h>
2332: #define setfpe()    ;asm("bispsw	$0x60")
2333: jmp_buf jmp_fpe;
2334: 
2335: LOCAL int fold_fpe_handler( sig, code )
2336: int sig;
2337: int code;
2338: {
2339: char        *message;
2340: 
2341: switch ( code )
2342:     {
2343:     case FPE_INTOVF_TRAP:
2344:         message = "integer overflow"; break;
2345:     case FPE_INTDIV_TRAP:
2346:         message = "integer divide by zero"; break;
2347:     case FPE_FLTOVF_TRAP:
2348:     case FPE_FLTOVF_FAULT:
2349:         message = "floating overflow"; break;
2350:     case FPE_FLTDIV_TRAP:
2351:     case FPE_FLTDIV_FAULT:
2352:         message = "floating divide by zero"; break;
2353:     case FPE_FLTUND_TRAP:
2354:     case FPE_FLTUND_FAULT:
2355:         message = "floating underflow"; break;
2356:     default:
2357:         message     = "arithmetic exception";
2358:     }
2359: errstr("%s in constant expression", message);
2360: longjmp(jmp_fpe, 1);
2361: }
2362: #endif
2363: 
2364: #ifndef setfpe
2365: #define setfpe()
2366: #endif
2367: 
2368: LOCAL expptr fold(e)
2369: register expptr e;
2370: {
2371: Constp p;
2372: register expptr lp, rp;
2373: int etype, mtype, ltype, rtype, opcode;
2374: int i, ll, lr;
2375: char *q, *s;
2376: union Constant lcon, rcon;
2377: 
2378: #if HERE == VAX
2379: int (*fpe_handler)();
2380: 
2381: if(setjmp(jmp_fpe))
2382:     {
2383:     (void) signal(SIGFPE, fpe_handler);
2384:     frexpr(e);
2385:     return(errnode());
2386:     }
2387: fpe_handler = signal(SIGFPE, fold_fpe_handler);
2388: setfpe();
2389: #endif
2390: 
2391: opcode = e->exprblock.opcode;
2392: etype = e->exprblock.vtype;
2393: 
2394: lp = e->exprblock.leftp;
2395: ltype = lp->headblock.vtype;
2396: rp = e->exprblock.rightp;
2397: 
2398: if(rp == 0)
2399:     switch(opcode)
2400:         {
2401:         case OPNOT:
2402:             lp->constblock.const.ci = ! lp->constblock.const.ci;
2403:             return(lp);
2404: 
2405:         case OPBITNOT:
2406:             lp->constblock.const.ci = ~ lp->constblock.const.ci;
2407:             return(lp);
2408: 
2409:         case OPNEG:
2410:             consnegop(lp);
2411:             return(lp);
2412: 
2413:         case OPCONV:
2414:         case OPADDR:
2415:         case OPPAREN:
2416:             return(e);
2417: 
2418:         default:
2419:             badop("fold", opcode);
2420:         }
2421: 
2422: rtype = rp->headblock.vtype;
2423: 
2424: p = ALLOC(Constblock);
2425: p->tag = TCONST;
2426: p->vtype = etype;
2427: p->vleng = e->exprblock.vleng;
2428: 
2429: switch(opcode)
2430:     {
2431:     case OPCOMMA:
2432:     case OPQUEST:
2433:     case OPCOLON:
2434:         return(e);
2435: 
2436:     case OPAND:
2437:         p->const.ci = lp->constblock.const.ci &&
2438:                 rp->constblock.const.ci;
2439:         break;
2440: 
2441:     case OPOR:
2442:         p->const.ci = lp->constblock.const.ci ||
2443:                 rp->constblock.const.ci;
2444:         break;
2445: 
2446:     case OPEQV:
2447:         p->const.ci = lp->constblock.const.ci ==
2448:                 rp->constblock.const.ci;
2449:         break;
2450: 
2451:     case OPNEQV:
2452:         p->const.ci = lp->constblock.const.ci !=
2453:                 rp->constblock.const.ci;
2454:         break;
2455: 
2456:     case OPBITAND:
2457:         p->const.ci = lp->constblock.const.ci &
2458:                 rp->constblock.const.ci;
2459:         break;
2460: 
2461:     case OPBITOR:
2462:         p->const.ci = lp->constblock.const.ci |
2463:                 rp->constblock.const.ci;
2464:         break;
2465: 
2466:     case OPBITXOR:
2467:         p->const.ci = lp->constblock.const.ci ^
2468:                 rp->constblock.const.ci;
2469:         break;
2470: 
2471:     case OPLSHIFT:
2472:         p->const.ci = lp->constblock.const.ci <<
2473:                 rp->constblock.const.ci;
2474:         break;
2475: 
2476:     case OPRSHIFT:
2477:         p->const.ci = lp->constblock.const.ci >>
2478:                 rp->constblock.const.ci;
2479:         break;
2480: 
2481:     case OPCONCAT:
2482:         ll = lp->constblock.vleng->constblock.const.ci;
2483:         lr = rp->constblock.vleng->constblock.const.ci;
2484:         p->const.ccp = q = (char *) ckalloc(ll+lr);
2485:         p->vleng = ICON(ll+lr);
2486:         s = lp->constblock.const.ccp;
2487:         for(i = 0 ; i < ll ; ++i)
2488:             *q++ = *s++;
2489:         s = rp->constblock.const.ccp;
2490:         for(i = 0; i < lr; ++i)
2491:             *q++ = *s++;
2492:         break;
2493: 
2494: 
2495:     case OPPOWER:
2496:         if( ! ISINT(rtype) )
2497:             return(e);
2498:         conspower(&(p->const), lp, rp->constblock.const.ci);
2499:         break;
2500: 
2501: 
2502:     default:
2503:         if(ltype == TYCHAR)
2504:             {
2505:             lcon.ci = cmpstr(lp->constblock.const.ccp,
2506:                     rp->constblock.const.ccp,
2507:                     lp->constblock.vleng->constblock.const.ci,
2508:                     rp->constblock.vleng->constblock.const.ci);
2509:             rcon.ci = 0;
2510:             mtype = tyint;
2511:             }
2512:         else    {
2513:             mtype = maxtype(ltype, rtype);
2514:             consconv(mtype, &lcon, ltype, &(lp->constblock.const) );
2515:             consconv(mtype, &rcon, rtype, &(rp->constblock.const) );
2516:             }
2517:         consbinop(opcode, mtype, &(p->const), &lcon, &rcon);
2518:         break;
2519:     }
2520: 
2521: frexpr(e);
2522: return( (expptr) p );
2523: }
2524: 
2525: 
2526: 
2527: /* assign constant l = r , doing coercion */
2528: 
2529: consconv(lt, lv, rt, rv)
2530: int lt, rt;
2531: register union Constant *lv, *rv;
2532: {
2533: switch(lt)
2534:     {
2535:     case TYCHAR:
2536:         *(lv->ccp = (char *) ckalloc(1)) = rv->ci;
2537:         break;
2538: 
2539:     case TYSHORT:
2540:     case TYLONG:
2541:         if(rt == TYCHAR)
2542:             lv->ci = rv->ccp[0];
2543:         else if( ISINT(rt) )
2544:             lv->ci = rv->ci;
2545:         else    lv->ci = rv->cd[0];
2546:         break;
2547: 
2548:     case TYCOMPLEX:
2549:     case TYDCOMPLEX:
2550:         switch(rt)
2551:             {
2552:             case TYSHORT:
2553:             case TYLONG:
2554:                 /* fall through and do real assignment of
2555: 				   first element
2556: 				*/
2557:             case TYREAL:
2558:             case TYDREAL:
2559:                 lv->cd[1] = 0; break;
2560:             case TYCOMPLEX:
2561:             case TYDCOMPLEX:
2562:                 lv->cd[1] = rv->cd[1]; break;
2563:             }
2564: 
2565:     case TYREAL:
2566:     case TYDREAL:
2567:         if( ISINT(rt) )
2568:             lv->cd[0] = rv->ci;
2569:         else    lv->cd[0] = rv->cd[0];
2570:         if( lt == TYREAL)
2571:             {
2572:             float f = lv->cd[0];
2573:             lv->cd[0] = f;
2574:             }
2575:         break;
2576: 
2577:     case TYLOGICAL:
2578:         lv->ci = rv->ci;
2579:         break;
2580:     }
2581: }
2582: 
2583: 
2584: 
2585: consnegop(p)
2586: register Constp p;
2587: {
2588: setfpe();
2589: 
2590: switch(p->vtype)
2591:     {
2592:     case TYSHORT:
2593:     case TYLONG:
2594:         p->const.ci = - p->const.ci;
2595:         break;
2596: 
2597:     case TYCOMPLEX:
2598:     case TYDCOMPLEX:
2599:         p->const.cd[1] = - p->const.cd[1];
2600:         /* fall through and do the real parts */
2601:     case TYREAL:
2602:     case TYDREAL:
2603:         p->const.cd[0] = - p->const.cd[0];
2604:         break;
2605:     default:
2606:         badtype("consnegop", p->vtype);
2607:     }
2608: }
2609: 
2610: 
2611: 
2612: LOCAL conspower(powp, ap, n)
2613: register union Constant *powp;
2614: Constp ap;
2615: ftnint n;
2616: {
2617: register int type;
2618: union Constant x;
2619: 
2620: switch(type = ap->vtype)    /* pow = 1 */
2621:     {
2622:     case TYSHORT:
2623:     case TYLONG:
2624:         powp->ci = 1;
2625:         break;
2626:     case TYCOMPLEX:
2627:     case TYDCOMPLEX:
2628:         powp->cd[1] = 0;
2629:     case TYREAL:
2630:     case TYDREAL:
2631:         powp->cd[0] = 1;
2632:         break;
2633:     default:
2634:         badtype("conspower", type);
2635:     }
2636: 
2637: if(n == 0)
2638:     return;
2639: if(n < 0)
2640:     {
2641:     if( ISINT(type) )
2642:         {
2643:         if (ap->const.ci == 0)
2644:             err("zero raised to a negative power");
2645:         else if (ap->const.ci == 1)
2646:             return;
2647:         else if (ap->const.ci == -1)
2648:             {
2649:             if (n < -2)
2650:                 n = n + 2;
2651:             n = -n;
2652:             if (n % 2 == 1)
2653:                 powp->ci = -1;
2654:             }
2655:         else
2656:             powp->ci = 0;
2657:         return;
2658:         }
2659:     n = - n;
2660:     consbinop(OPSLASH, type, &x, powp, &(ap->const));
2661:     }
2662: else
2663:     consbinop(OPSTAR, type, &x, powp, &(ap->const));
2664: 
2665: for( ; ; )
2666:     {
2667:     if(n & 01)
2668:         consbinop(OPSTAR, type, powp, powp, &x);
2669:     if(n >>= 1)
2670:         consbinop(OPSTAR, type, &x, &x, &x);
2671:     else
2672:         break;
2673:     }
2674: }
2675: 
2676: 
2677: 
2678: /* do constant operation cp = a op b */
2679: 
2680: 
2681: LOCAL consbinop(opcode, type, cp, ap, bp)
2682: int opcode, type;
2683: register union Constant *ap, *bp, *cp;
2684: {
2685: int k;
2686: double temp;
2687: 
2688: setfpe();
2689: 
2690: switch(opcode)
2691:     {
2692:     case OPPLUS:
2693:         switch(type)
2694:             {
2695:             case TYSHORT:
2696:             case TYLONG:
2697:                 cp->ci = ap->ci + bp->ci;
2698:                 break;
2699:             case TYCOMPLEX:
2700:             case TYDCOMPLEX:
2701:                 cp->cd[1] = ap->cd[1] + bp->cd[1];
2702:             case TYREAL:
2703:             case TYDREAL:
2704:                 cp->cd[0] = ap->cd[0] + bp->cd[0];
2705:                 break;
2706:             }
2707:         break;
2708: 
2709:     case OPMINUS:
2710:         switch(type)
2711:             {
2712:             case TYSHORT:
2713:             case TYLONG:
2714:                 cp->ci = ap->ci - bp->ci;
2715:                 break;
2716:             case TYCOMPLEX:
2717:             case TYDCOMPLEX:
2718:                 cp->cd[1] = ap->cd[1] - bp->cd[1];
2719:             case TYREAL:
2720:             case TYDREAL:
2721:                 cp->cd[0] = ap->cd[0] - bp->cd[0];
2722:                 break;
2723:             }
2724:         break;
2725: 
2726:     case OPSTAR:
2727:         switch(type)
2728:             {
2729:             case TYSHORT:
2730:             case TYLONG:
2731:                 cp->ci = ap->ci * bp->ci;
2732:                 break;
2733:             case TYREAL:
2734:             case TYDREAL:
2735:                 cp->cd[0] = ap->cd[0] * bp->cd[0];
2736:                 break;
2737:             case TYCOMPLEX:
2738:             case TYDCOMPLEX:
2739:                 temp = ap->cd[0] * bp->cd[0] -
2740:                         ap->cd[1] * bp->cd[1] ;
2741:                 cp->cd[1] = ap->cd[0] * bp->cd[1] +
2742:                         ap->cd[1] * bp->cd[0] ;
2743:                 cp->cd[0] = temp;
2744:                 break;
2745:             }
2746:         break;
2747:     case OPSLASH:
2748:         switch(type)
2749:             {
2750:             case TYSHORT:
2751:             case TYLONG:
2752:                 cp->ci = ap->ci / bp->ci;
2753:                 break;
2754:             case TYREAL:
2755:             case TYDREAL:
2756:                 cp->cd[0] = ap->cd[0] / bp->cd[0];
2757:                 break;
2758:             case TYCOMPLEX:
2759:             case TYDCOMPLEX:
2760:                 zdiv(cp,ap,bp);
2761:                 break;
2762:             }
2763:         break;
2764: 
2765:     case OPMOD:
2766:         if( ISINT(type) )
2767:             {
2768:             cp->ci = ap->ci % bp->ci;
2769:             break;
2770:             }
2771:         else
2772:             fatal("inline mod of noninteger");
2773: 
2774:     default:      /* relational ops */
2775:         switch(type)
2776:             {
2777:             case TYSHORT:
2778:             case TYLONG:
2779:                 if(ap->ci < bp->ci)
2780:                     k = -1;
2781:                 else if(ap->ci == bp->ci)
2782:                     k = 0;
2783:                 else    k = 1;
2784:                 break;
2785:             case TYREAL:
2786:             case TYDREAL:
2787:                 if(ap->cd[0] < bp->cd[0])
2788:                     k = -1;
2789:                 else if(ap->cd[0] == bp->cd[0])
2790:                     k = 0;
2791:                 else    k = 1;
2792:                 break;
2793:             case TYCOMPLEX:
2794:             case TYDCOMPLEX:
2795:                 if(ap->cd[0] == bp->cd[0] &&
2796:                    ap->cd[1] == bp->cd[1] )
2797:                     k = 0;
2798:                 else    k = 1;
2799:                 break;
2800:             case TYLOGICAL:
2801:                 if(ap->ci == bp->ci)
2802:                     k = 0;
2803:                 else    k = 1;
2804:                 break;
2805:             }
2806: 
2807:         switch(opcode)
2808:             {
2809:             case OPEQ:
2810:                 cp->ci = (k == 0);
2811:                 break;
2812:             case OPNE:
2813:                 cp->ci = (k != 0);
2814:                 break;
2815:             case OPGT:
2816:                 cp->ci = (k == 1);
2817:                 break;
2818:             case OPLT:
2819:                 cp->ci = (k == -1);
2820:                 break;
2821:             case OPGE:
2822:                 cp->ci = (k >= 0);
2823:                 break;
2824:             case OPLE:
2825:                 cp->ci = (k <= 0);
2826:                 break;
2827:             default:
2828:                 badop ("consbinop", opcode);
2829:             }
2830:         break;
2831:     }
2832: }
2833: 
2834: 
2835: 
2836: 
2837: conssgn(p)
2838: register expptr p;
2839: {
2840: if( ! ISCONST(p) )
2841:     fatal( "sgn(nonconstant)" );
2842: 
2843: switch(p->headblock.vtype)
2844:     {
2845:     case TYSHORT:
2846:     case TYLONG:
2847:         if(p->constblock.const.ci > 0) return(1);
2848:         if(p->constblock.const.ci < 0) return(-1);
2849:         return(0);
2850: 
2851:     case TYREAL:
2852:     case TYDREAL:
2853:         if(p->constblock.const.cd[0] > 0) return(1);
2854:         if(p->constblock.const.cd[0] < 0) return(-1);
2855:         return(0);
2856: 
2857:     case TYCOMPLEX:
2858:     case TYDCOMPLEX:
2859:         return(p->constblock.const.cd[0]!=0 || p->constblock.const.cd[1]!=0);
2860: 
2861:     default:
2862:         badtype( "conssgn", p->constblock.vtype);
2863:     }
2864: /* NOTREACHED */
2865: }
2866: 
2867: char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
2868: 
2869: 
2870: LOCAL expptr mkpower(p)
2871: register expptr p;
2872: {
2873: register expptr q, lp, rp;
2874: int ltype, rtype, mtype;
2875: struct Listblock *args, *mklist();
2876: Addrp ap;
2877: 
2878: lp = p->exprblock.leftp;
2879: rp = p->exprblock.rightp;
2880: ltype = lp->headblock.vtype;
2881: rtype = rp->headblock.vtype;
2882: 
2883: if(ISICON(rp))
2884:     {
2885:     if(rp->constblock.const.ci == 0)
2886:         {
2887:         frexpr(p);
2888:         if( ISINT(ltype) )
2889:             return( ICON(1) );
2890:         else
2891:             {
2892:             expptr pp;
2893:             pp = mkconv(ltype, ICON(1));
2894:             return( pp );
2895:             }
2896:         }
2897:     if(rp->constblock.const.ci < 0)
2898:         {
2899:         if( ISINT(ltype) )
2900:             {
2901:             frexpr(p);
2902:             err("integer**negative");
2903:             return( errnode() );
2904:             }
2905:         rp->constblock.const.ci = - rp->constblock.const.ci;
2906:         p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
2907:         }
2908:     if(rp->constblock.const.ci == 1)
2909:         {
2910:         frexpr(rp);
2911:         free( (charptr) p );
2912:         return(lp);
2913:         }
2914: 
2915:     if( ONEOF(ltype, MSKINT|MSKREAL) )
2916:         {
2917:         p->exprblock.vtype = ltype;
2918:         return(p);
2919:         }
2920:     }
2921: if( ISINT(rtype) )
2922:     {
2923:     if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
2924:         q = call2(TYSHORT, "pow_hh", lp, rp);
2925:     else    {
2926:         if(ltype == TYSHORT)
2927:             {
2928:             ltype = TYLONG;
2929:             lp = mkconv(TYLONG,lp);
2930:             }
2931:         q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
2932:         }
2933:     }
2934: else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
2935:     {
2936:     args = mklist( mkchain( mkconv(TYDREAL,lp), mkchain( mkconv(TYDREAL,rp), CHNULL ) ) );
2937:     fixargs(YES, args );
2938:     ap = builtin( TYDREAL, "pow" );
2939:     ap->vstg = STGINTR;
2940:     q = fixexpr( mkexpr(OPCCALL, ap, args ));
2941:     q->exprblock.vtype = mtype;
2942:     }
2943: else    {
2944:     q  = call2(TYDCOMPLEX, "pow_zz",
2945:         mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
2946:     if(mtype == TYCOMPLEX)
2947:         q = mkconv(TYCOMPLEX, q);
2948:     }
2949: free( (charptr) p );
2950: return(q);
2951: }
2952: 
2953: 
2954: 
2955: /* Complex Division.  Same code as in Runtime Library
2956: */
2957: 
2958: struct dcomplex { double dreal, dimag; };
2959: 
2960: 
2961: LOCAL zdiv(c, a, b)
2962: register struct dcomplex *a, *b, *c;
2963: {
2964: double ratio, den;
2965: double abr, abi;
2966: 
2967: setfpe();
2968: 
2969: if( (abr = b->dreal) < 0.)
2970:     abr = - abr;
2971: if( (abi = b->dimag) < 0.)
2972:     abi = - abi;
2973: if( abr <= abi )
2974:     {
2975:     if(abi == 0)
2976:         fatal("complex division by zero");
2977:     ratio = b->dreal / b->dimag ;
2978:     den = b->dimag * (1 + ratio*ratio);
2979:     c->dreal = (a->dreal*ratio + a->dimag) / den;
2980:     c->dimag = (a->dimag*ratio - a->dreal) / den;
2981:     }
2982: 
2983: else
2984:     {
2985:     ratio = b->dimag / b->dreal ;
2986:     den = b->dreal * (1 + ratio*ratio);
2987:     c->dreal = (a->dreal + a->dimag*ratio) / den;
2988:     c->dimag = (a->dimag - a->dreal*ratio) / den;
2989:     }
2990: 
2991: }
2992: 
2993: expptr oftwo(e)
2994: expptr e;
2995: {
2996:     int val,res;
2997: 
2998:     if (! ISCONST (e))
2999:         return (0);
3000: 
3001:     val = e->constblock.const.ci;
3002:     switch (val)
3003:         {
3004:         case 2:     res = 1; break;
3005:         case 4:     res = 2; break;
3006:         case 8:     res = 3; break;
3007:         case 16:    res = 4; break;
3008:         case 32:    res = 5; break;
3009:         case 64:    res = 6; break;
3010:         case 128:   res = 7; break;
3011:         case 256:   res = 8; break;
3012:         default:    return (0);
3013:         }
3014:     return (ICON (res));
3015: }

Defined functions

cktype defined in line 2197; used 6 times
consbinop defined in line 2681; used 5 times
consconv defined in line 2529; used 4 times
consnegop defined in line 2585; used 3 times
conspower defined in line 2612; used 1 times
conssgn defined in line 2837; used 2 times
cpexpr defined in line 493; used 247 times
deregister defined in line 1401; used 1 times
enregister defined in line 1445; used 1 times
fixargs defined in line 1001; used 3 times
fold defined in line 2368; used 2 times
fold_fpe_handler defined in line 2335; used 1 times
inregister defined in line 1431; used 3 times
letter defined in line 1856; used 4 times
mkaddr defined in line 1607; used 5 times
mkarg defined in line 1669; used 3 times
mkconst defined in line 168; used 36 times
mkexpr defined in line 1868; used 191 times
mkpower defined in line 2870; used 2 times
mkscalar defined in line 1043; used 7 times
oftwo defined in line 2993; used 3 times
opconv defined in line 472; used 8 times
shorten defined in line 935; used 5 times
stfcall defined in line 1182; used 2 times
subcheck defined in line 1551; used 2 times
suboffset defined in line 1470; used 4 times
zdiv defined in line 2961; used 1 times

Defined variables

args defined in line 1693; used 8 times
jmp_fpe defined in line 2333; used 2 times
powint defined in line 2867; used 1 times
sccsid defined in line 8; never used
substr defined in line 1694; used 10 times
v defined in line 1692; used 48 times

Defined struct's

dcomplex defined in line 2958; used 2 times

Defined macros

COMMUTE defined in line 1865; used 3 times
ERR defined in line 2195; used 11 times
ICONEQ defined in line 1864; used 2 times
setfpe defined in line 2365; used 5 times
Last modified: 1986-05-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 7336
Valid CSS Valid XHTML 1.0 Strict