Annotation of 43BSDTahoe/usr.bin/f77/f77.tahoe/f77pass1/expr.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.