Annotation of researchv10dc/cmd/f2c/expr.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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