Annotation of 3BSD/cmd/f77/expr.c, revision 1.1

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

unix.superglobalmegacorp.com

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