Annotation of researchv10no/cmd/f77/expr.c, revision 1.1

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

unix.superglobalmegacorp.com

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