Annotation of 43BSD/usr.bin/f77/src/f77pass1/proc.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)proc.c     5.7 (Berkeley) 1/30/86";
                      9: #endif not lint
                     10: 
                     11: /*
                     12:  * proc.c
                     13:  *
                     14:  * Routines for handling procedures, f77 compiler, pass 1.
                     15:  *
                     16:  * University of Utah CS Dept modification history:
                     17:  *
                     18:  * $Log:       proc.c,v $
                     19:  * Revision 5.9  86/01/28  22:30:28  donn
                     20:  * Let functions of type character have adjustable length.
                     21:  * 
                     22:  * Revision 5.8  86/01/10  19:02:19  donn
                     23:  * More dbx hacking -- filter out incomplete declarations (with bogus types).
                     24:  * 
                     25:  * Revision 5.7  86/01/10  13:53:02  donn
                     26:  * Since we now postpone determination of the type of an argument, we must
                     27:  * make sure to emit stab information at the end of the routine when we
                     28:  * definitely have the type.  Notice some care was taken to make sure that
                     29:  * arguments appear in order in the output file since that's how dbx wants
                     30:  * them.  Also a minor change for dummy procedures.
                     31:  * 
                     32:  * Revision 5.6  86/01/06  16:28:06  donn
                     33:  * Sigh.  We can't commit to defining a symbol as a variable instead of a
                     34:  * function based only on what we have seen through the declaration section;
                     35:  * this was properly handled for normal variables but not for arguments.
                     36:  * 
                     37:  * Revision 5.5  86/01/01  21:59:17  donn
                     38:  * Pick up CHARACTER*(*) declarations for variables which aren't dummy
                     39:  * arguments, and complain about them.
                     40:  * 
                     41:  * Revision 5.4  85/12/20  19:18:35  donn
                     42:  * Don't assume that dummy procedures of unknown type are functions of type
                     43:  * undefined until the user (mis-)uses them that way -- they may also be
                     44:  * subroutines.
                     45:  * 
                     46:  * Revision 5.3  85/09/30  23:21:07  donn
                     47:  * Print space with prspace() in outlocvars() so that alignment is preserved.
                     48:  * 
                     49:  * Revision 5.2  85/08/10  05:03:34  donn
                     50:  * Support for NAMELIST i/o from Jerry Berkman.
                     51:  * 
                     52:  * Revision 5.1  85/08/10  03:49:14  donn
                     53:  * 4.3 alpha
                     54:  * 
                     55:  * Revision 3.11  85/06/04  03:45:29  donn
                     56:  * Changed retval() to recognize that a function declaration might have
                     57:  * bombed out earlier, leaving an error node behind...
                     58:  * 
                     59:  * Revision 3.10  85/03/08  23:13:06  donn
                     60:  * Finally figured out why function calls and array elements are not legal
                     61:  * dummy array dimension declarator elements.  Hacked safedim() to stop 'em.
                     62:  * 
                     63:  * Revision 3.9  85/02/02  00:26:10  donn
                     64:  * Removed the call to entrystab() in enddcl() -- this was redundant (it was
                     65:  * also done in startproc()) and confusing to dbx to boot.
                     66:  * 
                     67:  * Revision 3.8  85/01/14  04:21:53  donn
                     68:  * Added changes to implement Jerry's '-q' option.
                     69:  * 
                     70:  * Revision 3.7  85/01/11  21:10:35  donn
                     71:  * In conjunction with other changes to implement SAVE statements, function
                     72:  * nameblocks were changed to make it appear that they are 'saved' too --
                     73:  * this arranges things so that function return values are forced out of
                     74:  * register before a return.
                     75:  * 
                     76:  * Revision 3.6  84/12/10  19:27:20  donn
                     77:  * comblock() signals an illegal common block name by returning a null pointer,
                     78:  * but incomm() wasn't able to handle it, leading to core dumps.  I put the
                     79:  * fix in incomm() to pick up null common blocks.
                     80:  * 
                     81:  * Revision 3.5  84/11/21  20:33:31  donn
                     82:  * It seems that I/O elements are treated as character strings so that their
                     83:  * length can be passed to the I/O routines...  Unfortunately the compiler
                     84:  * assumes that no temporaries can be of type CHARACTER and casually tosses
                     85:  * length and type info away when removing TEMP blocks.  This has been fixed...
                     86:  * 
                     87:  * Revision 3.4  84/11/05  22:19:30  donn
                     88:  * Fixed a silly bug in the last fix.
                     89:  * 
                     90:  * Revision 3.3  84/10/29  08:15:23  donn
                     91:  * Added code to check the type and shape of subscript declarations,
                     92:  * per Jerry Berkman's suggestion.
                     93:  * 
                     94:  * Revision 3.2  84/10/29  05:52:07  donn
                     95:  * Added change suggested by Jerry Berkman to report an error when an array
                     96:  * is redimensioned.
                     97:  * 
                     98:  * Revision 3.1  84/10/13  02:12:31  donn
                     99:  * Merged Jerry Berkman's version into mine.
                    100:  * 
                    101:  * Revision 2.1  84/07/19  12:04:09  donn
                    102:  * Changed comment headers for UofU.
                    103:  * 
                    104:  * Revision 1.6  84/07/19  11:32:15  donn
                    105:  * Incorporated fix to setbound() to detect backward array subscript limits.
                    106:  * The fix is by Bob Corbett, donated by Jerry Berkman.
                    107:  * 
                    108:  * Revision 1.5  84/07/18  18:25:50  donn
                    109:  * Fixed problem with doentry() where a placeholder for a return value
                    110:  * was not allocated if the first entry didn't require one but a later
                    111:  * entry did.
                    112:  * 
                    113:  * Revision 1.4  84/05/24  20:52:09  donn
                    114:  * Installed firewall #ifdef around the code that recycles stack temporaries,
                    115:  * since it seems to be broken and lacks a good fix for the time being.
                    116:  * 
                    117:  * Revision 1.3  84/04/16  09:50:46  donn
                    118:  * Fixed mkargtemp() so that it only passes back a copy of a temporary, keeping
                    119:  * the original for its own use.  This fixes a set of bugs that are caused by
                    120:  * elements in the argtemplist getting stomped on.
                    121:  * 
                    122:  * Revision 1.2  84/02/28  21:12:58  donn
                    123:  * Added Berkeley changes for subroutine call argument temporaries fix.
                    124:  * 
                    125:  */
                    126: 
                    127: #include "defs.h"
                    128: 
                    129: #ifdef SDB
                    130: #      include <a.out.h>
                    131: #      ifndef N_SO
                    132: #              include <stab.h>
                    133: #      endif
                    134: #endif
                    135: 
                    136: extern flag namesflag;
                    137: 
                    138: typedef
                    139:   struct SizeList
                    140:     {
                    141:       struct SizeList *next;
                    142:       ftnint size;
                    143:       struct VarList *vars;
                    144:     }
                    145:   sizelist;
                    146: 
                    147: 
                    148: typedef
                    149:   struct VarList
                    150:     {
                    151:       struct VarList *next;
                    152:       Namep np;
                    153:       struct Equivblock *ep;
                    154:     }
                    155:   varlist;
                    156: 
                    157: 
                    158: LOCAL sizelist *varsizes;
                    159: 
                    160: 
                    161: /* start a new procedure */
                    162: 
                    163: newproc()
                    164: {
                    165: if(parstate != OUTSIDE)
                    166:        {
                    167:        execerr("missing end statement", CNULL);
                    168:        endproc();
                    169:        }
                    170: 
                    171: parstate = INSIDE;
                    172: procclass = CLMAIN;    /* default */
                    173: }
                    174: 
                    175: 
                    176: 
                    177: /* end of procedure. generate variables, epilogs, and prologs */
                    178: 
                    179: endproc()
                    180: {
                    181: struct Labelblock *lp;
                    182: 
                    183: if(parstate < INDATA)
                    184:        enddcl();
                    185: if(ctlstack >= ctls)
                    186:        err("DO loop or BLOCK IF not closed");
                    187: for(lp = labeltab ; lp < labtabend ; ++lp)
                    188:        if(lp->stateno!=0 && lp->labdefined==NO)
                    189:                errstr("missing statement number %s", convic(lp->stateno) );
                    190: 
                    191: if (optimflag)
                    192:   optimize();
                    193: 
                    194: outiodata();
                    195: epicode();
                    196: procode();
                    197: donmlist();
                    198: dobss();
                    199: 
                    200: #if FAMILY == PCC
                    201:        putbracket();
                    202: #endif
                    203: fixlwm();
                    204: procinit();    /* clean up for next procedure */
                    205: }
                    206: 
                    207: 
                    208: 
                    209: /* End of declaration section of procedure.  Allocate storage. */
                    210: 
                    211: enddcl()
                    212: {
                    213: register struct Entrypoint *ep;
                    214: 
                    215: parstate = INEXEC;
                    216: docommon();
                    217: doequiv();
                    218: docomleng();
                    219: for(ep = entries ; ep ; ep = ep->entnextp) {
                    220:        doentry(ep);
                    221: }
                    222: }
                    223: 
                    224: /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */
                    225: 
                    226: /* Main program or Block data */
                    227: 
                    228: startproc(prgname, class)
                    229: Namep prgname;
                    230: int class;
                    231: {
                    232: struct Extsym *progname;
                    233: register struct Entrypoint *p;
                    234: 
                    235: if(prgname)
                    236:        procname = prgname->varname;
                    237: if(namesflag == YES) {
                    238:        fprintf(diagfile, "   %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") );
                    239:        if(prgname)
                    240:                fprintf(diagfile, " %s", varstr(XL, procname) );
                    241:        fprintf(diagfile, ":\n");
                    242:        }
                    243: 
                    244: if( prgname ) 
                    245:        progname = newentry( prgname );
                    246: else
                    247:        progname = NULL;
                    248: 
                    249: p = ALLOC(Entrypoint);
                    250: if(class == CLMAIN)
                    251:        puthead("MAIN_", CLMAIN);
                    252: else
                    253:        puthead(CNULL, CLBLOCK);
                    254: if(class == CLMAIN)
                    255:        newentry( mkname(5, "MAIN") );
                    256: p->entryname = progname;
                    257: p->entrylabel = newlabel();
                    258: entries = p;
                    259: 
                    260: procclass = class;
                    261: retlabel = newlabel();
                    262: #ifdef SDB
                    263: if(sdbflag) {
                    264:          entrystab(p,class);
                    265: }
                    266: #endif
                    267: }
                    268: 
                    269: /* subroutine or function statement */
                    270: 
                    271: struct Extsym *newentry(v)
                    272: register Namep v;
                    273: {
                    274: register struct Extsym *p;
                    275: 
                    276: p = mkext( varunder(VL, v->varname) );
                    277: 
                    278: if(p==NULL || p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) )
                    279:        {
                    280:        if(p == 0)
                    281:                dclerr("invalid entry name", v);
                    282:        else    dclerr("external name already used", v);
                    283:        return(0);
                    284:        }
                    285: v->vstg = STGAUTO;
                    286: v->vprocclass = PTHISPROC;
                    287: v->vclass = CLPROC;
                    288: p->extstg = STGEXT;
                    289: p->extinit = YES;
                    290: return(p);
                    291: }
                    292: 
                    293: 
                    294: entrypt(class, type, length, entname, args)
                    295: int class, type;
                    296: ftnint length;
                    297: Namep entname;
                    298: chainp args;
                    299: {
                    300: struct Extsym *entry;
                    301: register Namep q;
                    302: register struct Entrypoint *p, *ep;
                    303: 
                    304: if(namesflag == YES) {
                    305:        if(class == CLENTRY)
                    306:                fprintf(diagfile, "       entry ");
                    307:        if(entname)
                    308:                fprintf(diagfile, "   %s", varstr(XL, entname->varname) );
                    309:        fprintf(diagfile, ":\n");
                    310:        }
                    311: 
                    312: if( entname->vclass == CLPARAM ) {
                    313:        errstr("entry name %s used in 'parameter' statement", 
                    314:                varstr(XL, entname->varname) );
                    315:        return;
                    316:        }
                    317: if( ((type == TYSUBR) || (class == CLENTRY && proctype == TYSUBR)) 
                    318:        && (entname->vtype != TYUNKNOWN && entname->vtype != TYSUBR) ) {
                    319:        errstr("subroutine entry %s previously declared",
                    320:                varstr(XL, entname->varname) );
                    321:        return;
                    322:        }
                    323: if(  (entname->vstg != STGEXT && entname->vstg != STGUNKNOWN)
                    324:        ||  (entname->vdim != NULL) ) {
                    325:        errstr("subroutine or function entry %s previously declared",
                    326:                varstr(XL, entname->varname) );
                    327:        return;
                    328:        }
                    329: 
                    330: if( (class == CLPROC || class == CLENTRY) && type != TYSUBR )
                    331:        /* arrange to save function return values */
                    332:        entname->vsave = YES;
                    333:        
                    334: entry = newentry( entname );
                    335: 
                    336: if(class != CLENTRY)
                    337:        puthead( varstr(XL, procname = entry->extname), class);
                    338: q = mkname(VL, nounder(XL,entry->extname) );
                    339: 
                    340: if( (type = lengtype(type, (int) length)) != TYCHAR)
                    341:        length = 0;
                    342: if(class == CLPROC)
                    343:        {
                    344:        procclass = CLPROC;
                    345:        proctype = type;
                    346:        procleng = length;
                    347: 
                    348:        retlabel = newlabel();
                    349:        if(type == TYSUBR)
                    350:                ret0label = newlabel();
                    351:        }
                    352: 
                    353: p = ALLOC(Entrypoint);
                    354: if(entries)    /* put new block at end of entries list */
                    355:        {
                    356:        for(ep = entries; ep->entnextp; ep = ep->entnextp)
                    357:                ;
                    358:        ep->entnextp = p;
                    359:        }
                    360: else
                    361:        entries = p;
                    362: 
                    363: p->entryname = entry;
                    364: p->arglist = args;
                    365: p->entrylabel = newlabel();
                    366: p->enamep = q;
                    367: 
                    368: if(class == CLENTRY)
                    369:        {
                    370:        class = CLPROC;
                    371:        if(proctype == TYSUBR)
                    372:                type = TYSUBR;
                    373:        }
                    374: 
                    375: q->vclass = class;
                    376: q->vprocclass = PTHISPROC;
                    377: settype(q, type, (int) length);
                    378: /* hold all initial entry points till end of declarations */
                    379: if(parstate >= INDATA) {
                    380:        doentry(p);
                    381: }
                    382: #ifdef SDB
                    383:        if(sdbflag)
                    384:        { /* may need to preserve CLENTRY here */
                    385:        entrystab(p,class);
                    386:        }
                    387: #endif
                    388: }
                    389: 
                    390: /* generate epilogs */
                    391: 
                    392: LOCAL epicode()
                    393: {
                    394: register int i;
                    395: 
                    396: if(procclass==CLPROC)
                    397:        {
                    398:        if(proctype==TYSUBR)
                    399:                {
                    400:                putlabel(ret0label);
                    401:                if(substars)
                    402:                        putforce(TYINT, ICON(0) );
                    403:                putlabel(retlabel);
                    404:                goret(TYSUBR);
                    405:                }
                    406:        else    {
                    407:                putlabel(retlabel);
                    408:                if(multitype)
                    409:                        {
                    410:                        typeaddr = autovar(1, TYADDR, PNULL);
                    411:                        putbranch( cpexpr(typeaddr) );
                    412:                        for(i = 0; i < NTYPES ; ++i)
                    413:                                if(rtvlabel[i] != 0)
                    414:                                        {
                    415:                                        putlabel(rtvlabel[i]);
                    416:                                        retval(i);
                    417:                                        }
                    418:                        }
                    419:                else
                    420:                        retval(proctype);
                    421:                }
                    422:        }
                    423: 
                    424: else if(procclass != CLBLOCK)
                    425:        {
                    426:        putlabel(retlabel);
                    427:        goret(TYSUBR);
                    428:        }
                    429: }
                    430: 
                    431: 
                    432: /* generate code to return value of type  t */
                    433: 
                    434: LOCAL retval(t)
                    435: register int t;
                    436: {
                    437: register Addrp p;
                    438: 
                    439: switch(t)
                    440:        {
                    441:        case TYCHAR:
                    442:        case TYCOMPLEX:
                    443:        case TYDCOMPLEX:
                    444:                break;
                    445: 
                    446:        case TYLOGICAL:
                    447:                t = tylogical;
                    448:        case TYADDR:
                    449:        case TYSHORT:
                    450:        case TYLONG:
                    451:                p = (Addrp) cpexpr(retslot);
                    452:                p->vtype = t;
                    453:                putforce(t, p);
                    454:                break;
                    455: 
                    456:        case TYREAL:
                    457:        case TYDREAL:
                    458:                p = (Addrp) cpexpr(retslot);
                    459:                p->vtype = t;
                    460:                putforce(t, p);
                    461:                break;
                    462: 
                    463:        case TYERROR:
                    464:                return;         /* someone else already complained */
                    465: 
                    466:        default:
                    467:                badtype("retval", t);
                    468:        }
                    469: goret(t);
                    470: }
                    471: 
                    472: 
                    473: /* Allocate extra argument array if needed. Generate prologs. */
                    474: 
                    475: LOCAL procode()
                    476: {
                    477: register struct Entrypoint *p;
                    478: Addrp argvec;
                    479: 
                    480: #if TARGET==GCOS
                    481:        argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
                    482: #else
                    483:        if(lastargslot>0 && nentry>1)
                    484: #if TARGET == VAX
                    485:                argvec = autovar(1 + lastargslot/SZADDR, TYADDR, PNULL);
                    486: #else
                    487:                argvec = autovar(lastargslot/SZADDR, TYADDR, PNULL);
                    488: #endif
                    489:        else
                    490:                argvec = NULL;
                    491: #endif
                    492: 
                    493: 
                    494: #if TARGET == PDP11
                    495:        /* for the optimizer */
                    496:        if(fudgelabel)
                    497:                putlabel(fudgelabel);
                    498: #endif
                    499: 
                    500: for(p = entries ; p ; p = p->entnextp)
                    501:        prolog(p, argvec);
                    502: 
                    503: #if FAMILY == PCC
                    504:        putrbrack(procno);
                    505: #endif
                    506: 
                    507: prendproc();
                    508: }
                    509: 
                    510: 
                    511: /*
                    512:  * manipulate argument lists (allocate argument slot positions)
                    513:  * keep track of return types and labels
                    514:  */
                    515: 
                    516: LOCAL doentry(ep)
                    517: struct Entrypoint *ep;
                    518: {
                    519: register int type;
                    520: register Namep np;
                    521: chainp p;
                    522: register Namep q;
                    523: Addrp mkarg();
                    524: 
                    525: ++nentry;
                    526: if(procclass == CLMAIN)
                    527:        {
                    528:        if (optimflag)
                    529:                optbuff (SKLABEL, 0, ep->entrylabel, 0);
                    530:        else
                    531:                putlabel(ep->entrylabel);
                    532:        return;
                    533:        }
                    534: else if(procclass == CLBLOCK)
                    535:        return;
                    536: 
                    537: impldcl( np = mkname(VL, nounder(XL, ep->entryname->extname) ) );
                    538: type = np->vtype;
                    539: if(proctype == TYUNKNOWN)
                    540:        if( (proctype = type) == TYCHAR)
                    541:                procleng = (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1));
                    542: 
                    543: if(proctype == TYCHAR)
                    544:        {
                    545:        if(type != TYCHAR)
                    546:                err("noncharacter entry of character function");
                    547:        else if( (np->vleng ? np->vleng->constblock.const.ci : (ftnint) (-1)) != procleng)
                    548:                err("mismatched character entry lengths");
                    549:        }
                    550: else if(type == TYCHAR)
                    551:        err("character entry of noncharacter function");
                    552: else if(type != proctype)
                    553:        multitype = YES;
                    554: if(rtvlabel[type] == 0)
                    555:        rtvlabel[type] = newlabel();
                    556: ep->typelabel = rtvlabel[type];
                    557: 
                    558: if(type == TYCHAR)
                    559:        {
                    560:        if(chslot < 0)
                    561:                {
                    562:                chslot = nextarg(TYADDR);
                    563:                chlgslot = nextarg(TYLENG);
                    564:                }
                    565:        np->vstg = STGARG;
                    566:        np->vardesc.varno = chslot;
                    567:        if(procleng < 0)
                    568:                np->vleng = (expptr) mkarg(TYLENG, chlgslot);
                    569:        }
                    570: else if( ISCOMPLEX(type) )
                    571:        {
                    572:        np->vstg = STGARG;
                    573:        if(cxslot < 0)
                    574:                cxslot = nextarg(TYADDR);
                    575:        np->vardesc.varno = cxslot;
                    576:        }
                    577: else if(type != TYSUBR)
                    578:        {
                    579:        if(retslot == NULL)
                    580:                retslot = autovar(1, TYDREAL, PNULL);
                    581:        np->vstg = STGAUTO;
                    582:        np->voffset = retslot->memoffset->constblock.const.ci;
                    583:        }
                    584: 
                    585: for(p = ep->arglist ; p ; p = p->nextp)
                    586:        if(! (( q = (Namep) (p->datap) )->vdcldone) )
                    587:                q->vardesc.varno = nextarg(TYADDR);
                    588: 
                    589: for(p = ep->arglist ; p ; p = p->nextp)
                    590:        if(! (( q = (Namep) (p->datap) )->vdcldone) )
                    591:                {
                    592:                if(q->vclass == CLPROC && q->vtype == TYUNKNOWN)
                    593:                        continue;
                    594:                impldcl(q);
                    595:                if(q->vtype == TYCHAR)
                    596:                        {
                    597:                        if(q->vleng == NULL)    /* character*(*) */
                    598:                                q->vleng = (expptr)
                    599:                                                mkarg(TYLENG, nextarg(TYLENG) );
                    600:                        else if(nentry == 1)
                    601:                                nextarg(TYLENG);
                    602:                        }
                    603:                else if(q->vclass==CLPROC && nentry==1)
                    604:                        nextarg(TYLENG) ;
                    605:                }
                    606: 
                    607: if (optimflag)
                    608:        optbuff (SKLABEL, 0, ep->entrylabel, 0);
                    609: else
                    610:        putlabel(ep->entrylabel);
                    611: }
                    612: 
                    613: 
                    614: 
                    615: LOCAL nextarg(type)
                    616: int type;
                    617: {
                    618: int k;
                    619: k = lastargslot;
                    620: lastargslot += typesize[type];
                    621: return(k);
                    622: }
                    623: 
                    624: /* generate variable references */
                    625: 
                    626: LOCAL dobss()
                    627: {
                    628: register struct Hashentry *p;
                    629: register Namep q;
                    630: register int i;
                    631: int align;
                    632: ftnint leng, iarrl;
                    633: char *memname();
                    634: int qstg, qclass, qtype;
                    635: 
                    636: pruse(asmfile, USEBSS);
                    637: varsizes = NULL;
                    638: 
                    639: for(p = hashtab ; p<lasthash ; ++p)
                    640:     if(q = p->varp)
                    641:        {
                    642:        qstg = q->vstg;
                    643:        qtype = q->vtype;
                    644:        qclass = q->vclass;
                    645: 
                    646:        if( (qclass==CLUNKNOWN && qstg!=STGARG) ||
                    647:            (qclass==CLVAR && qstg==STGUNKNOWN) )
                    648:                warn1("local variable %s never used", varstr(VL,q->varname) );
                    649:        else if(qclass==CLPROC && q->vprocclass==PEXTERNAL && qstg!=STGARG)
                    650:                mkext(varunder(VL, q->varname)) ->extstg = STGEXT;
                    651: 
                    652:        if (qclass == CLVAR && qstg == STGBSS)
                    653:          {
                    654:            if (SMALLVAR(q->varsize))
                    655:              {
                    656:                enlist(q->varsize, q, NULL);
                    657:                q->inlcomm = NO;
                    658:              }
                    659:            else
                    660:              {
                    661:                if (q->init == NO)
                    662:                  {
                    663:                    preven(ALIDOUBLE);
                    664:                    prlocvar(memname(qstg, q->vardesc.varno), q->varsize);
                    665:                    q->inlcomm = YES;
                    666:                  }
                    667:                else
                    668:                  prlocdata(memname(qstg, q->vardesc.varno), q->varsize,
                    669:                            q->vtype, q->initoffset, &(q->inlcomm));
                    670:              }
                    671:          }
                    672:        else if(qclass==CLVAR && qstg!=STGARG)
                    673:                {
                    674:                if(q->vdim && !ISICON(q->vdim->nelt) )
                    675:                        dclerr("adjustable dimension on non-argument", q);
                    676:                if(qtype==TYCHAR && (q->vleng==NULL || !ISICON(q->vleng)))
                    677:                        dclerr("adjustable leng on nonargument", q);
                    678:                }
                    679: 
                    680:        chkdim(q);
                    681:        }
                    682: 
                    683: for (i = 0 ; i < nequiv ; ++i)
                    684:   if ( (leng = eqvclass[i].eqvleng) != 0 )
                    685:     {
                    686:       if (SMALLVAR(leng))
                    687:        enlist(leng, NULL, eqvclass + i);
                    688:       else if (eqvclass[i].init == NO)
                    689:        {
                    690:          preven(ALIDOUBLE);
                    691:          prlocvar(memname(STGEQUIV, i), leng);
                    692:          eqvclass[i].inlcomm = YES;
                    693:        }
                    694:       else
                    695:        prlocdata(memname(STGEQUIV, i), leng, TYDREAL, 
                    696:                  eqvclass[i].initoffset, &(eqvclass[i].inlcomm));
                    697:     }
                    698: 
                    699:   outlocvars();
                    700: #ifdef SDB
                    701:     if(sdbflag) {
                    702:       register struct Entrypoint *ep;
                    703:       register chainp cp;
                    704: 
                    705:       for (ep = entries; ep; ep = ep->entnextp)
                    706:        for (cp = ep->arglist ; cp ; cp = cp->nextp)
                    707:          if ((q = (Namep) cp->datap) && q->vstg == STGARG) {
                    708:            q->vdcldone = YES;
                    709:            namestab(q);
                    710:          }
                    711:       for (p = hashtab ; p<lasthash ; ++p) if(q = p->varp) {
                    712:        if (q->vtype == TYUNKNOWN || q->vtype == TYERROR)
                    713:          continue;
                    714:        qstg = q->vstg;
                    715:        qclass = q->vclass;
                    716:        q->vdcldone = YES;
                    717:        if ( ONEOF(qclass, M(CLVAR)|M(CLPARAM)|M(CLPROC)) ) {
                    718:          if (! ONEOF(qstg,M(STGCOMMON)|M(STGARG) ) )
                    719:            namestab(q);
                    720:        } 
                    721:       }
                    722:     }
                    723: #endif
                    724: 
                    725:   close(vdatafile);
                    726:   close(vchkfile);
                    727:   unlink(vdatafname);
                    728:   unlink(vchkfname);
                    729:   vdatahwm = 0;
                    730: }
                    731: 
                    732: 
                    733: 
                    734: donmlist()
                    735: {
                    736: register struct Hashentry *p;
                    737: register Namep q;
                    738: 
                    739: pruse(asmfile, USEINIT);
                    740: 
                    741: for(p=hashtab; p<lasthash; ++p)
                    742:        if( (q = p->varp) && q->vclass==CLNAMELIST)
                    743:                namelist(q);
                    744: }
                    745: 
                    746: 
                    747: doext()
                    748: {
                    749: struct Extsym *p;
                    750: 
                    751: for(p = extsymtab ; p<nextext ; ++p)
                    752:        prext(p);
                    753: }
                    754: 
                    755: 
                    756: 
                    757: 
                    758: ftnint iarrlen(q)
                    759: register Namep q;
                    760: {
                    761: ftnint leng;
                    762: 
                    763: leng = typesize[q->vtype];
                    764: if(leng <= 0)
                    765:        return(-1);
                    766: if(q->vdim)
                    767:        if( ISICON(q->vdim->nelt) )
                    768:                leng *= q->vdim->nelt->constblock.const.ci;
                    769:        else    return(-1);
                    770: if(q->vleng)
                    771:        if( ISICON(q->vleng) )
                    772:                leng *= q->vleng->constblock.const.ci;
                    773:        else    return(-1);
                    774: return(leng);
                    775: }
                    776: 
                    777: /* This routine creates a static block representing the namelist.
                    778:    An equivalent declaration of the structure produced is:
                    779:        struct namelist
                    780:                {
                    781:                char namelistname[16];
                    782:                struct namelistentry
                    783:                        {
                    784:                        char varname[16]; #  16 plus null padding -> 20
                    785:                        char *varaddr;
                    786:                        short int type;
                    787:                        short int len;  # length of type
                    788:                        struct dimensions *dimp; # null means scalar
                    789:                        } names[];
                    790:                };
                    791: 
                    792:        struct dimensions
                    793:                {
                    794:                int numberofdimensions;
                    795:                int numberofelements
                    796:                int baseoffset;
                    797:                int span[numberofdimensions];
                    798:                };
                    799:    where the namelistentry list terminates with a null varname
                    800:    If dimp is not null, then the corner element of the array is at
                    801:    varaddr.  However,  the element with subscripts (i1,...,in) is at
                    802:    varaddr - dimp->baseoffset + sizeoftype * (i1+span[0]*(i2+span[1]*...)
                    803: */
                    804: 
                    805: namelist(np)
                    806: Namep np;
                    807: {
                    808: register chainp q;
                    809: register Namep v;
                    810: register struct Dimblock *dp;
                    811: char *memname();
                    812: int type, dimno, dimoffset;
                    813: flag bad;
                    814: 
                    815: 
                    816: preven(ALILONG);
                    817: fprintf(asmfile, LABELFMT, memname(STGINIT, np->vardesc.varno));
                    818: putstr(asmfile, varstr(VL, np->varname), 16);
                    819: dimno = ++lastvarno;
                    820: dimoffset = 0;
                    821: bad = NO;
                    822: 
                    823: for(q = np->varxptr.namelist ; q ; q = q->nextp)
                    824:        {
                    825:        vardcl( v = (Namep) (q->datap) );
                    826:        type = v->vtype;
                    827:        if( ONEOF(v->vstg, MSKSTATIC) )
                    828:                {
                    829:                preven(ALILONG);
                    830:                putstr(asmfile, varstr(VL,v->varname), 16);
                    831:                praddr(asmfile, v->vstg, v->vardesc.varno, v->voffset);
                    832:                prconi(asmfile, TYSHORT, type );
                    833:                prconi(asmfile, TYSHORT,
                    834:                        type==TYCHAR ?
                    835:                            (v->vleng->constblock.const.ci) :
                    836:                                        (ftnint) typesize[type]);
                    837:                if(v->vdim)
                    838:                        {
                    839:                        praddr(asmfile, STGINIT, dimno, (ftnint)dimoffset);
                    840:                        dimoffset += (3 + v->vdim->ndim) * SZINT;
                    841:                        }
                    842:                else
                    843:                        praddr(asmfile, STGNULL,0,(ftnint) 0);
                    844:                }
                    845:        else
                    846:                {
                    847:                dclerr("may not appear in namelist", v);
                    848:                bad = YES;
                    849:                }
                    850:        }
                    851: 
                    852: if(bad)
                    853:        return;
                    854: 
                    855: putstr(asmfile, "", 16);
                    856: 
                    857: if(dimoffset > 0)
                    858:        {
                    859:        fprintf(asmfile, LABELFMT, memname(STGINIT,dimno));
                    860:        for(q = np->varxptr.namelist ; q ; q = q->nextp)
                    861:                if(dp = q->datap->nameblock.vdim)
                    862:                        {
                    863:                        int i;
                    864:                        prconi(asmfile, TYINT, (ftnint) (dp->ndim) );
                    865:                        prconi(asmfile, TYINT,
                    866:                                (ftnint) (dp->nelt->constblock.const.ci) );
                    867:                        prconi(asmfile, TYINT,
                    868:                                (ftnint) (dp->baseoffset->constblock.const.ci));
                    869:                        for(i=0; i<dp->ndim ; ++i)
                    870:                                prconi(asmfile, TYINT,
                    871:                                        dp->dims[i].dimsize->constblock.const.ci);
                    872:                        }
                    873:        }
                    874: 
                    875: }
                    876: 
                    877: LOCAL docommon()
                    878: {
                    879: register struct Extsym *p;
                    880: register chainp q;
                    881: struct Dimblock *t;
                    882: expptr neltp;
                    883: register Namep v;
                    884: ftnint size;
                    885: int type;
                    886: 
                    887: for(p = extsymtab ; p<nextext ; ++p)
                    888:        if(p->extstg==STGCOMMON)
                    889:                {
                    890: #ifdef SDB
                    891:                if(sdbflag)
                    892:                        prstab(varstr(XL,p->extname), N_BCOMM, 0, 0);
                    893: #endif
                    894:                for(q = p->extp ; q ; q = q->nextp)
                    895:                        {
                    896:                        v = (Namep) (q->datap);
                    897:                        if(v->vdcldone == NO)
                    898:                                vardcl(v);
                    899:                        type = v->vtype;
                    900:                        if(p->extleng % typealign[type] != 0)
                    901:                                {
                    902:                                dclerr("common alignment", v);
                    903:                                p->extleng = roundup(p->extleng, typealign[type]);
                    904:                                }
                    905:                        v->voffset = p->extleng;
                    906:                        v->vardesc.varno = p - extsymtab;
                    907:                        if(type == TYCHAR)
                    908:                                size = v->vleng->constblock.const.ci;
                    909:                        else    size = typesize[type];
                    910:                        if(t = v->vdim)
                    911:                                if( (neltp = t->nelt) && ISCONST(neltp) )
                    912:                                        size *= neltp->constblock.const.ci;
                    913:                                else
                    914:                                        dclerr("adjustable array in common", v);
                    915:                        p->extleng += size;
                    916: #ifdef SDB
                    917:                        if(sdbflag)
                    918:                                {
                    919:                                namestab(v);
                    920:                                }
                    921: #endif
                    922:                        }
                    923: 
                    924:                frchain( &(p->extp) );
                    925: #ifdef SDB
                    926:                if(sdbflag)
                    927:                        prstab(varstr(XL,p->extname), N_ECOMM, 0, 0);
                    928: #endif
                    929:                }
                    930: }
                    931: 
                    932: 
                    933: 
                    934: 
                    935: 
                    936: LOCAL docomleng()
                    937: {
                    938: register struct Extsym *p;
                    939: 
                    940: for(p = extsymtab ; p < nextext ; ++p)
                    941:        if(p->extstg == STGCOMMON)
                    942:                {
                    943:                if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng
                    944:                    && !eqn(XL,"_BLNK__ ",p->extname) )
                    945:                        warn1("incompatible lengths for common block %s",
                    946:                                nounder(XL, p->extname) );
                    947:                if(p->maxleng < p->extleng)
                    948:                        p->maxleng = p->extleng;
                    949:                p->extleng = 0;
                    950:        }
                    951: }
                    952: 
                    953: 
                    954: 
                    955: 
                    956: /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */
                    957: 
                    958: /*  frees a temporary block  */
                    959: 
                    960: frtemp(p)
                    961: Tempp p;
                    962: {
                    963: Addrp t;
                    964: 
                    965: if (optimflag)
                    966:        {
                    967:        if (p->tag != TTEMP)
                    968:                badtag ("frtemp",p->tag);
                    969:        t = p->memalloc;
                    970:        }
                    971: else
                    972:        t = (Addrp) p;
                    973: 
                    974: /* restore clobbered character string lengths */
                    975: if(t->vtype==TYCHAR && t->varleng!=0)
                    976:        {
                    977:        frexpr(t->vleng);
                    978:        t->vleng = ICON(t->varleng);
                    979:        }
                    980: 
                    981: /* put block on chain of temps to be reclaimed */
                    982: holdtemps = mkchain(t, holdtemps);
                    983: }
                    984: 
                    985: 
                    986: 
                    987: /* allocate an automatic variable slot */
                    988: 
                    989: Addrp autovar(nelt, t, lengp)
                    990: register int nelt, t;
                    991: expptr lengp;
                    992: {
                    993: ftnint leng;
                    994: register Addrp q;
                    995: 
                    996: if(lengp)
                    997:        if( ISICON(lengp) )
                    998:                leng = lengp->constblock.const.ci;
                    999:        else    {
                   1000:                fatal("automatic variable of nonconstant length");
                   1001:                }
                   1002: else
                   1003:        leng = typesize[t];
                   1004: autoleng = roundup( autoleng, typealign[t]);
                   1005: 
                   1006: q = ALLOC(Addrblock);
                   1007: q->tag = TADDR;
                   1008: q->vtype = t;
                   1009: if(lengp)
                   1010:        {
                   1011:        q->vleng = ICON(leng);
                   1012:        q->varleng = leng;
                   1013:        }
                   1014: q->vstg = STGAUTO;
                   1015: q->memno = newlabel();
                   1016: q->ntempelt = nelt;
                   1017: #if TARGET==PDP11 || TARGET==VAX
                   1018:        /* stack grows downward */
                   1019:        autoleng += nelt*leng;
                   1020:        q->memoffset = ICON( - autoleng );
                   1021: #else
                   1022:        q->memoffset = ICON( autoleng );
                   1023:        autoleng += nelt*leng;
                   1024: #endif
                   1025: 
                   1026: return(q);
                   1027: }
                   1028: 
                   1029: 
                   1030: 
                   1031: /*
                   1032:  *  create a temporary block (TTEMP) when optimizing,
                   1033:  *  an ordinary TADDR block when not optimizing
                   1034:  */
                   1035: 
                   1036: Tempp mktmpn(nelt, type, lengp)
                   1037: int nelt;
                   1038: register int type;
                   1039: expptr lengp;
                   1040: {
                   1041: ftnint leng;
                   1042: chainp p, oldp;
                   1043: register Tempp q;
                   1044: Addrp altemp;
                   1045: 
                   1046: if (! optimflag)
                   1047:        return ( (Tempp) mkaltmpn(nelt,type,lengp) );
                   1048: if(type==TYUNKNOWN || type==TYERROR)
                   1049:        badtype("mktmpn", type);
                   1050: 
                   1051: if(type==TYCHAR)
                   1052:        if( ISICON(lengp) )
                   1053:                leng = lengp->constblock.const.ci;
                   1054:        else    {
                   1055:                err("adjustable length");
                   1056:                return( (Tempp) errnode() );
                   1057:                }
                   1058: else
                   1059:        leng = typesize[type];
                   1060: 
                   1061: q = ALLOC(Tempblock);
                   1062: q->tag = TTEMP;
                   1063: q->vtype = type;
                   1064: if(type == TYCHAR)
                   1065:        {
                   1066:        q->vleng = ICON(leng);
                   1067:        q->varleng = leng;
                   1068:        }
                   1069: 
                   1070: altemp = ALLOC(Addrblock);
                   1071: altemp->tag = TADDR;
                   1072: altemp->vstg = STGUNKNOWN;
                   1073: q->memalloc = altemp;
                   1074: 
                   1075: q->ntempelt = nelt;
                   1076: q->istemp = YES;
                   1077: return(q);
                   1078: }
                   1079: 
                   1080: 
                   1081: 
                   1082: Addrp mktemp(type, lengp)
                   1083: int type;
                   1084: expptr lengp;
                   1085: {
                   1086: return( (Addrp) mktmpn(1,type,lengp) );
                   1087: }
                   1088: 
                   1089: 
                   1090: 
                   1091: /*  allocate a temporary location for the given temporary block;
                   1092:     if already allocated, return its location  */
                   1093: 
                   1094: Addrp altmpn(tp)
                   1095: Tempp tp;
                   1096: 
                   1097: {
                   1098: Addrp t, q;
                   1099: 
                   1100: if (tp->tag != TTEMP)
                   1101:        badtag ("altmpn",tp->tag);
                   1102: 
                   1103: t = tp->memalloc;
                   1104: if (t->vstg != STGUNKNOWN)
                   1105:        {
                   1106:        if (tp->vtype == TYCHAR)
                   1107:                {
                   1108:                /*
                   1109:                 * Unformatted I/O parameters are treated like character
                   1110:                 *      strings (sigh) -- propagate type and length.
                   1111:                 */
                   1112:                t = (Addrp) cpexpr(t);
                   1113:                t->vtype = tp->vtype;
                   1114:                t->vleng = tp->vleng;
                   1115:                t->varleng = tp->varleng;
                   1116:                }
                   1117:        return (t);
                   1118:        }
                   1119: 
                   1120: q = mkaltmpn (tp->ntempelt, tp->vtype, tp->vleng);
                   1121: cpn (sizeof(struct Addrblock), (char*)q, (char*)t);
                   1122: free ( (charptr) q);
                   1123: return(t);
                   1124: }
                   1125: 
                   1126: 
                   1127: 
                   1128: /*  create and allocate space immediately for a temporary  */
                   1129: 
                   1130: Addrp mkaltemp(type,lengp)
                   1131: int type;
                   1132: expptr lengp;
                   1133: {
                   1134: return (mkaltmpn(1,type,lengp));
                   1135: }
                   1136: 
                   1137: 
                   1138: 
                   1139: Addrp mkaltmpn(nelt,type,lengp)
                   1140: int nelt;
                   1141: register int type;
                   1142: expptr lengp;
                   1143: {
                   1144: ftnint leng;
                   1145: chainp p, oldp;
                   1146: register Addrp q;
                   1147: 
                   1148: if(type==TYUNKNOWN || type==TYERROR)
                   1149:        badtype("mkaltmpn", type);
                   1150: 
                   1151: if(type==TYCHAR)
                   1152:        if( ISICON(lengp) )
                   1153:                leng = lengp->constblock.const.ci;
                   1154:        else    {
                   1155:                err("adjustable length");
                   1156:                return( (Addrp) errnode() );
                   1157:                }
                   1158: 
                   1159: /*
                   1160:  * if a temporary of appropriate shape is on the templist,
                   1161:  * remove it from the list and return it
                   1162:  */
                   1163: 
                   1164: #ifdef notdef
                   1165: /*
                   1166:  * This code is broken until SKFRTEMP slots can be processed in putopt()
                   1167:  *     instead of in optimize() -- all kinds of things in putpcc.c can
                   1168:  *     bomb because of this.  Sigh.
                   1169:  */
                   1170: for(oldp=CHNULL, p=templist  ;  p  ;  oldp=p, p=p->nextp)
                   1171:        {
                   1172:        q = (Addrp) (p->datap);
                   1173:        if(q->vtype==type && q->ntempelt==nelt &&
                   1174:            (type!=TYCHAR || q->vleng->constblock.const.ci==leng) )
                   1175:                {
                   1176:                if(oldp)
                   1177:                        oldp->nextp = p->nextp;
                   1178:                else
                   1179:                        templist = p->nextp;
                   1180:                free( (charptr) p);
                   1181: 
                   1182:                if (debugflag[14])
                   1183:                        fprintf(diagfile,"mkaltmpn reusing offset %d\n",
                   1184:                                q->memoffset->constblock.const.ci);
                   1185:                return(q);
                   1186:                }
                   1187:        }
                   1188: #endif notdef
                   1189: q = autovar(nelt, type, lengp);
                   1190: q->istemp = YES;
                   1191: 
                   1192: if (debugflag[14])
                   1193:        fprintf(diagfile,"mkaltmpn new offset %d\n",
                   1194:                q->memoffset->constblock.const.ci);
                   1195: return(q);
                   1196: }
                   1197: 
                   1198: 
                   1199: 
                   1200: /*  The following routine is a patch which is only needed because the  */
                   1201: /*  code for processing actual arguments for calls does not allocate   */
                   1202: /*  the temps it needs before optimization takes place.  A better      */
                   1203: /*  solution is possible, but I do not have the time to implement it   */
                   1204: /*  now.                                                               */
                   1205: /*                                                                     */
                   1206: /*                                     Robert P. Corbett               */
                   1207: 
                   1208: Addrp
                   1209: mkargtemp(type, lengp)
                   1210: int type;
                   1211: expptr lengp;
                   1212: {
                   1213:   ftnint leng;
                   1214:   chainp oldp, p;
                   1215:   Addrp q;
                   1216: 
                   1217:   if (type == TYUNKNOWN || type == TYERROR)
                   1218:     badtype("mkargtemp", type);
                   1219: 
                   1220:   if (type == TYCHAR)
                   1221:     {
                   1222:       if (ISICON(lengp))
                   1223:        leng = lengp->constblock.const.ci;
                   1224:       else
                   1225:        {
                   1226:          err("adjustable length");
                   1227:          return ((Addrp) errnode());
                   1228:        }
                   1229:     }
                   1230: 
                   1231:   oldp = CHNULL;
                   1232:   p = argtemplist;
                   1233: 
                   1234:   while (p)
                   1235:     {
                   1236:       q = (Addrp) (p->datap);
                   1237:       if (q->vtype == type
                   1238:          && (type != TYCHAR || q->vleng->constblock.const.ci == leng))
                   1239:        {
                   1240:          if (oldp)
                   1241:            oldp->nextp = p->nextp;
                   1242:          else
                   1243:            argtemplist = p->nextp;
                   1244: 
                   1245:          p->nextp = activearglist;
                   1246:          activearglist = p;
                   1247: 
                   1248:          return ((Addrp) cpexpr(q));
                   1249:        }
                   1250: 
                   1251:       oldp = p;
                   1252:       p = p->nextp;
                   1253:     }
                   1254: 
                   1255:   q = autovar(1, type, lengp);
                   1256:   activearglist = mkchain(q, activearglist);
                   1257:   return ((Addrp) cpexpr(q));
                   1258: }
                   1259: 
                   1260: /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */
                   1261: 
                   1262: struct Extsym *comblock(len, s)
                   1263: register int len;
                   1264: register char *s;
                   1265: {
                   1266: struct Extsym *p;
                   1267: 
                   1268: if(len == 0)
                   1269:        {
                   1270:        s = BLANKCOMMON;
                   1271:        len = strlen(s);
                   1272:        }
                   1273: p = mkext( varunder(len, s) );
                   1274: if(p->extstg == STGUNKNOWN)
                   1275:        p->extstg = STGCOMMON;
                   1276: else if(p->extstg != STGCOMMON)
                   1277:        {
                   1278:        errstr("%s cannot be a common block name", s);
                   1279:        return(0);
                   1280:        }
                   1281: 
                   1282: return( p );
                   1283: }
                   1284: 
                   1285: 
                   1286: incomm(c, v)
                   1287: struct Extsym *c;
                   1288: Namep v;
                   1289: {
                   1290: if(v->vstg != STGUNKNOWN)
                   1291:        dclerr("incompatible common declaration", v);
                   1292: else
                   1293:        {
                   1294:        if(c == (struct Extsym *) 0)
                   1295:                return;         /* Illegal common block name upstream */
                   1296:        v->vstg = STGCOMMON;
                   1297:        c->extp = hookup(c->extp, mkchain(v,CHNULL) );
                   1298:        }
                   1299: }
                   1300: 
                   1301: 
                   1302: 
                   1303: 
                   1304: settype(v, type, length)
                   1305: register Namep  v;
                   1306: register int type;
                   1307: register int length;
                   1308: {
                   1309: if(type == TYUNKNOWN)
                   1310:        return;
                   1311: 
                   1312: if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG)
                   1313:        {
                   1314:        v->vtype = TYSUBR;
                   1315:        frexpr(v->vleng);
                   1316:        }
                   1317: else if(type < 0)      /* storage class set */
                   1318:        {
                   1319:        if(v->vstg == STGUNKNOWN)
                   1320:                v->vstg = - type;
                   1321:        else if(v->vstg != -type)
                   1322:                dclerr("incompatible storage declarations", v);
                   1323:        }
                   1324: else if(v->vtype == TYUNKNOWN)
                   1325:        {
                   1326:        if( (v->vtype = lengtype(type, length))==TYCHAR )
                   1327:                {
                   1328:                if(length >= 0)
                   1329:                        v->vleng = ICON(length);
                   1330:                else if(!(v->vstg == STGARG || v->vclass == CLENTRY ||
                   1331:                          (v->vclass == CLPROC && v->vprocclass == PTHISPROC)))
                   1332:                        {
                   1333:                        dclerr("illegal adjustable length character variable", v);
                   1334:                        v->vleng = ICON(0);
                   1335:                        }
                   1336:                }
                   1337:        }
                   1338: else if(v->vtype!=type || (type==TYCHAR && v->vleng->constblock.const.ci!=length) )
                   1339:        dclerr("incompatible type declarations", v);
                   1340: }
                   1341: 
                   1342: 
                   1343: 
                   1344: 
                   1345: 
                   1346: lengtype(type, length)
                   1347: register int type;
                   1348: register int length;
                   1349: {
                   1350: switch(type)
                   1351:        {
                   1352:        case TYREAL:
                   1353:                if(length == 8)
                   1354:                        return(TYDREAL);
                   1355:                if(length == 4)
                   1356:                        goto ret;
                   1357:                break;
                   1358: 
                   1359:        case TYCOMPLEX:
                   1360:                if(length == 16)
                   1361:                        return(TYDCOMPLEX);
                   1362:                if(length == 8)
                   1363:                        goto ret;
                   1364:                break;
                   1365: 
                   1366:        case TYSHORT:
                   1367:        case TYDREAL:
                   1368:        case TYDCOMPLEX:
                   1369:        case TYCHAR:
                   1370:        case TYUNKNOWN:
                   1371:        case TYSUBR:
                   1372:        case TYERROR:
                   1373:                goto ret;
                   1374: 
                   1375:        case TYLOGICAL:
                   1376:                if(length == typesize[TYLOGICAL])
                   1377:                        goto ret;
                   1378:                break;
                   1379: 
                   1380:        case TYLONG:
                   1381:                if(length == 0)
                   1382:                        return(tyint);
                   1383:                if(length == 2)
                   1384:                        return(TYSHORT);
                   1385:                if(length == 4)
                   1386:                        goto ret;
                   1387:                break;
                   1388:        default:
                   1389:                badtype("lengtype", type);
                   1390:        }
                   1391: 
                   1392: if(length != 0)
                   1393:        err("incompatible type-length combination");
                   1394: 
                   1395: ret:
                   1396:        return(type);
                   1397: }
                   1398: 
                   1399: 
                   1400: 
                   1401: 
                   1402: 
                   1403: setintr(v)
                   1404: register Namep  v;
                   1405: {
                   1406: register int k;
                   1407: 
                   1408: if(v->vstg == STGUNKNOWN)
                   1409:        v->vstg = STGINTR;
                   1410: else if(v->vstg!=STGINTR)
                   1411:        dclerr("incompatible use of intrinsic function", v);
                   1412: if(v->vclass==CLUNKNOWN)
                   1413:        v->vclass = CLPROC;
                   1414: if(v->vprocclass == PUNKNOWN)
                   1415:        v->vprocclass = PINTRINSIC;
                   1416: else if(v->vprocclass != PINTRINSIC)
                   1417:        dclerr("invalid intrinsic declaration", v);
                   1418: if(k = intrfunct(v->varname))
                   1419:        v->vardesc.varno = k;
                   1420: else
                   1421:        dclerr("unknown intrinsic function", v);
                   1422: }
                   1423: 
                   1424: 
                   1425: 
                   1426: setext(v)
                   1427: register Namep  v;
                   1428: {
                   1429: if(v->vclass == CLUNKNOWN)
                   1430:        v->vclass = CLPROC;
                   1431: else if(v->vclass != CLPROC)
                   1432:        dclerr("conflicting declarations", v);
                   1433: 
                   1434: if(v->vprocclass == PUNKNOWN)
                   1435:        v->vprocclass = PEXTERNAL;
                   1436: else if(v->vprocclass != PEXTERNAL)
                   1437:        dclerr("conflicting declarations", v);
                   1438: }
                   1439: 
                   1440: 
                   1441: 
                   1442: 
                   1443: /* create dimensions block for array variable */
                   1444: 
                   1445: setbound(v, nd, dims)
                   1446: register Namep  v;
                   1447: int nd;
                   1448: struct { expptr lb, ub; } dims[ ];
                   1449: {
                   1450: register expptr q, t;
                   1451: register struct Dimblock *p;
                   1452: int i;
                   1453: 
                   1454: if(v->vclass == CLUNKNOWN)
                   1455:        v->vclass = CLVAR;
                   1456: else if(v->vclass != CLVAR)
                   1457:        {
                   1458:        dclerr("only variables may be arrays", v);
                   1459:        return;
                   1460:        }
                   1461: if(v->vdim)
                   1462:        {
                   1463:        dclerr("redimensioned array", v);
                   1464:        return;
                   1465:        }
                   1466: 
                   1467: v->vdim = p = (struct Dimblock *)
                   1468:                ckalloc( sizeof(int) + (3+6*nd)*sizeof(expptr) );
                   1469: p->ndim = nd;
                   1470: p->nelt = ICON(1);
                   1471: 
                   1472: for(i=0 ; i<nd ; ++i)
                   1473:        {
                   1474: #ifdef SDB
                   1475:         if(sdbflag) {
                   1476: /* Save the bounds trees built up by the grammar routines for use in stabs */
                   1477: 
                   1478:                if(dims[i].lb == NULL) p->dims[i].lb=ICON(1);
                   1479:                else p->dims[i].lb= (expptr) cpexpr(dims[i].lb);
                   1480:                 if(ISCONST(p->dims[i].lb)) p->dims[i].lbaddr = (expptr) PNULL;
                   1481:                 else p->dims[i].lbaddr = (expptr) autovar(1, tyint, PNULL);
                   1482: 
                   1483:                if(dims[i].ub == NULL) p->dims[i].ub=ICON(1);
                   1484:                else p->dims[i].ub = (expptr) cpexpr(dims[i].ub);
                   1485:                 if(ISCONST(p->dims[i].ub)) p->dims[i].ubaddr = (expptr) PNULL;
                   1486:                 else p->dims[i].ubaddr = (expptr) autovar(1, tyint, PNULL);
                   1487:        }
                   1488: #endif
                   1489:        if( (q = dims[i].ub) == NULL)
                   1490:                {
                   1491:                if(i == nd-1)
                   1492:                        {
                   1493:                        frexpr(p->nelt);
                   1494:                        p->nelt = NULL;
                   1495:                        }
                   1496:                else
                   1497:                        err("only last bound may be asterisk");
                   1498:                p->dims[i].dimsize = ICON(1);;
                   1499:                p->dims[i].dimexpr = NULL;
                   1500:                }
                   1501:        else
                   1502:                {
                   1503:                if(dims[i].lb)
                   1504:                        {
                   1505:                        q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb));
                   1506:                        q = mkexpr(OPPLUS, q, ICON(1) );
                   1507:                        }
                   1508:                if( ISCONST(q) )
                   1509:                        {
                   1510:                        if (!ISINT(q->headblock.vtype)) {
                   1511:                           dclerr("dimension bounds must be integer expression", v);
                   1512:                           frexpr(q);
                   1513:                           q = ICON(0);
                   1514:                           }
                   1515:                        if ( q->constblock.const.ci <= 0)
                   1516:                           {
                   1517:                           dclerr("array bounds out of sequence", v);
                   1518:                           frexpr(q);
                   1519:                           q = ICON(0);
                   1520:                           }
                   1521:                        p->dims[i].dimsize = q;
                   1522:                        p->dims[i].dimexpr = (expptr) PNULL;
                   1523:                        }
                   1524:                else    {
                   1525:                        p->dims[i].dimsize = (expptr) autovar(1, tyint, PNULL);
                   1526:                        p->dims[i].dimexpr = q;
                   1527:                        }
                   1528:                if(p->nelt)
                   1529:                        p->nelt = mkexpr(OPSTAR, p->nelt,
                   1530:                                        cpexpr(p->dims[i].dimsize) );
                   1531:                }
                   1532:        }
                   1533: 
                   1534: q = dims[nd-1].lb;
                   1535: if(q == NULL)
                   1536:        q = ICON(1);
                   1537: 
                   1538: for(i = nd-2 ; i>=0 ; --i)
                   1539:        {
                   1540:        t = dims[i].lb;
                   1541:        if(t == NULL)
                   1542:                t = ICON(1);
                   1543:        if(p->dims[i].dimsize)
                   1544:                q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) );
                   1545:        }
                   1546: 
                   1547: if( ISCONST(q) )
                   1548:        {
                   1549:        p->baseoffset = q;
                   1550:        p->basexpr = NULL;
                   1551:        }
                   1552: else
                   1553:        {
                   1554:        p->baseoffset = (expptr) autovar(1, tyint, PNULL);
                   1555:        p->basexpr = q;
                   1556:        }
                   1557: }
                   1558: 
                   1559: 
                   1560: 
                   1561: /*
                   1562:  * Check the dimensions of q to ensure that they are appropriately defined.
                   1563:  */
                   1564: LOCAL chkdim(q)
                   1565: register Namep q;
                   1566: {
                   1567:   register struct Dimblock *p;
                   1568:   register int i;
                   1569:   expptr e;
                   1570: 
                   1571:   if (q == NULL)
                   1572:     return;
                   1573:   if (q->vclass != CLVAR)
                   1574:     return;
                   1575:   if (q->vdim == NULL)
                   1576:     return;
                   1577:   p = q->vdim;
                   1578:   for (i = 0; i < p->ndim; ++i)
                   1579:     {
                   1580: #ifdef SDB
                   1581:       if (sdbflag)
                   1582:        {
                   1583:          if (e = p->dims[i].lb)
                   1584:            chkdime(e, q);
                   1585:          if (e = p->dims[i].ub)
                   1586:            chkdime(e, q);
                   1587:        }
                   1588:       else
                   1589: #endif SDB
                   1590:       if (e = p->dims[i].dimexpr)
                   1591:        chkdime(e, q);
                   1592:     }
                   1593: }
                   1594: 
                   1595: 
                   1596: 
                   1597: /*
                   1598:  * The actual checking for chkdim() -- examines each expression.
                   1599:  */
                   1600: LOCAL chkdime(expr, q)
                   1601: expptr expr;
                   1602: Namep q;
                   1603: {
                   1604:   register expptr e;
                   1605: 
                   1606:   e = fixtype(cpexpr(expr));
                   1607:   if (!ISINT(e->exprblock.vtype))
                   1608:     dclerr("non-integer dimension", q);
                   1609:   else if (!safedim(e))
                   1610:     dclerr("undefined dimension", q);
                   1611:   frexpr(e);
                   1612:   return;
                   1613: }
                   1614: 
                   1615: 
                   1616: 
                   1617: /*
                   1618:  * A recursive routine to find undefined variables in dimension expressions.
                   1619:  */
                   1620: LOCAL safedim(e)
                   1621: expptr e;
                   1622: {
                   1623:   chainp cp;
                   1624: 
                   1625:   if (e == NULL)
                   1626:     return 1;
                   1627:   switch (e->tag)
                   1628:     {
                   1629:       case TEXPR:
                   1630:        if (e->exprblock.opcode == OPCALL || e->exprblock.opcode == OPCCALL)
                   1631:          return 0;
                   1632:        return safedim(e->exprblock.leftp) && safedim(e->exprblock.rightp);
                   1633:       case TADDR:
                   1634:        switch (e->addrblock.vstg)
                   1635:          {
                   1636:            case STGCOMMON:
                   1637:            case STGARG:
                   1638:            case STGCONST:
                   1639:            case STGEQUIV:
                   1640:              if (e->addrblock.isarray)
                   1641:                return 0;
                   1642:              return safedim(e->addrblock.memoffset);
                   1643:            default:
                   1644:              return 0;
                   1645:          }
                   1646:       case TCONST:
                   1647:       case TTEMP:
                   1648:        return 1;
                   1649:     }
                   1650:   return 0;
                   1651: }
                   1652: 
                   1653: 
                   1654: 
                   1655: LOCAL enlist(size, np, ep)
                   1656: ftnint size;
                   1657: Namep np;
                   1658: struct Equivblock *ep;
                   1659: {
                   1660:   register sizelist *sp;
                   1661:   register sizelist *t;
                   1662:   register varlist *p;
                   1663: 
                   1664:   sp = varsizes;
                   1665: 
                   1666:   if (sp == NULL)
                   1667:     {
                   1668:       sp = ALLOC(SizeList);
                   1669:       sp->size = size;
                   1670:       varsizes = sp;
                   1671:     }
                   1672:   else
                   1673:     {
                   1674:       while (sp->size != size)
                   1675:        {
                   1676:          if (sp->next != NULL && sp->next->size <= size)
                   1677:            sp = sp->next;
                   1678:          else
                   1679:            {
                   1680:              t = sp;
                   1681:              sp = ALLOC(SizeList);
                   1682:              sp->size = size;
                   1683:              sp->next = t->next;
                   1684:              t->next = sp;
                   1685:            }
                   1686:        }
                   1687:     }
                   1688: 
                   1689:   p = ALLOC(VarList);
                   1690:   p->next = sp->vars;
                   1691:   p->np = np;
                   1692:   p->ep = ep;
                   1693: 
                   1694:   sp->vars = p;
                   1695: 
                   1696:   return;
                   1697: }
                   1698: 
                   1699: 
                   1700: 
                   1701: outlocvars()
                   1702: {
                   1703: 
                   1704:   register varlist *first, *last;
                   1705:   register varlist *vp, *t;
                   1706:   register sizelist *sp, *sp1;
                   1707:   register Namep np;
                   1708:   register struct Equivblock *ep;
                   1709:   register int i;
                   1710:   register int alt;
                   1711:   register int type;
                   1712:   char sname[100];
                   1713:   char setbuff[100];
                   1714: 
                   1715:   sp = varsizes;
                   1716:   if (sp == NULL)
                   1717:     return;
                   1718: 
                   1719:   vp = sp->vars;
                   1720:   if (vp->np != NULL)
                   1721:     {
                   1722:       np = vp->np;
                   1723:       sprintf(setbuff, "\t.set\tv.%d,v.%d\n", bsslabel,
                   1724:              np->vardesc.varno);
                   1725:     }
                   1726:   else
                   1727:     {
                   1728:       i = vp->ep - eqvclass;
                   1729:       sprintf(setbuff, "\t.set\tv.%d,q.%d\n", bsslabel, i + eqvstart);
                   1730:     }
                   1731: 
                   1732:   first = last = NULL;
                   1733:   alt = NO;
                   1734: 
                   1735:   while (sp != NULL)
                   1736:     {
                   1737:       vp = sp->vars;
                   1738:       while (vp != NULL)
                   1739:        {
                   1740:          t = vp->next;
                   1741:          if (alt == YES)
                   1742:            {
                   1743:              alt = NO;
                   1744:              vp->next = first;
                   1745:              first = vp;
                   1746:            }
                   1747:          else
                   1748:            {
                   1749:              alt = YES;
                   1750:              if (last != NULL)
                   1751:                last->next = vp;
                   1752:              else
                   1753:                first = vp;
                   1754:              vp->next = NULL;
                   1755:              last = vp;
                   1756:            }
                   1757:          vp = t;
                   1758:        }
                   1759:       sp1 = sp;
                   1760:       sp = sp->next;
                   1761:       free((char *) sp1);
                   1762:     }
                   1763: 
                   1764:   vp = first;
                   1765:   while(vp != NULL)
                   1766:     {
                   1767:       if (vp->np != NULL)
                   1768:        {
                   1769:          np = vp->np;
                   1770:          sprintf(sname, "v.%d", np->vardesc.varno);
                   1771:          if (np->init)
                   1772:            prlocdata(sname, np->varsize, np->vtype, np->initoffset,
                   1773:                      &(np->inlcomm));
                   1774:          else
                   1775:            {
                   1776:              pralign(typealign[np->vtype]);
                   1777:              fprintf(initfile, "%s:\n", sname);
                   1778:              prspace(np->varsize);
                   1779:            }
                   1780:          np->inlcomm = NO;
                   1781:        }
                   1782:       else
                   1783:        {
                   1784:          ep = vp->ep;
                   1785:          i = ep - eqvclass;
                   1786:          if (ep->eqvleng >= 8)
                   1787:            type = TYDREAL;
                   1788:          else if (ep->eqvleng >= 4)
                   1789:            type = TYLONG;
                   1790:          else if (ep->eqvleng >= 2)
                   1791:            type = TYSHORT;
                   1792:          else
                   1793:            type = TYCHAR;
                   1794:          sprintf(sname, "q.%d", i + eqvstart);
                   1795:          if (ep->init)
                   1796:            prlocdata(sname, ep->eqvleng, type, ep->initoffset,
                   1797:                      &(ep->inlcomm));
                   1798:          else
                   1799:            {
                   1800:              pralign(typealign[type]);
                   1801:              fprintf(initfile, "%s:\n", sname);
                   1802:              prspace(ep->eqvleng);
                   1803:            }
                   1804:          ep->inlcomm = NO;
                   1805:        }
                   1806:       t = vp;
                   1807:       vp = vp->next;
                   1808:       free((char *) t);
                   1809:     }
                   1810:   fprintf(initfile, "%s\n", setbuff);
                   1811:   return;
                   1812: }

unix.superglobalmegacorp.com

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