Annotation of researchv10no/cmd/PDP11/11c/c01.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * C compiler
        !             3:  */
        !             4: 
        !             5: #include "c0.h"
        !             6: 
        !             7: /*
        !             8:  * Called from tree, this routine takes the top 1, 2, or 3
        !             9:  * operands on the expression stack, makes a new node with
        !            10:  * the operator op, and puts it on the stack.
        !            11:  * Essentially all the work is in inserting
        !            12:  * appropriate conversions.
        !            13:  */
        !            14: build(op)
        !            15: {
        !            16:        register int t1;
        !            17:        int t2, t;
        !            18:        register union tree *p1, *p2, *p3;
        !            19:        int dope, leftc, cvn, pcvn;
        !            20: 
        !            21:        /*
        !            22:         * a[i] => *(a+i)
        !            23:         */
        !            24:        if (op==LBRACK) {
        !            25:                build(PLUS);
        !            26:                op = STAR;
        !            27:        }
        !            28:        dope = opdope[op];
        !            29:        t2 = INT;
        !            30:        if ((dope&BINARY)!=0) {
        !            31:                p2 = chkfun(disarray(*--cp));
        !            32:                if (p2)
        !            33:                        t2 = p2->t.type;
        !            34:        }
        !            35:        p1 = *--cp;
        !            36:        /*
        !            37:         * sizeof gets turned into a number here.
        !            38:         */
        !            39:        if (op==SIZEOF) {
        !            40:                p1 = cblock(length(p1));
        !            41:                p1->c.type = UNSIGN;
        !            42:                *cp++ = p1;
        !            43:                return;
        !            44:        }
        !            45:        if (op!=AMPER) {
        !            46:                p1 = disarray(p1);
        !            47:                if (op!=CALL)
        !            48:                        p1 = chkfun(p1);
        !            49:        }
        !            50:        t1 = p1->t.type;
        !            51:        if (t1==CHAR)
        !            52:                t1 = INT;
        !            53:        else if (t1==UNCHAR)
        !            54:                t1 = UNSIGN;
        !            55:        if (t2==CHAR)
        !            56:                t2 = INT;
        !            57:        else if (t2==UNCHAR)
        !            58:                t2 = UNSIGN;
        !            59:        pcvn = 0;
        !            60:        t = INT;
        !            61:        switch (op) {
        !            62: 
        !            63:        case CAST:
        !            64:                if ((t1&XTYPE)==FUNC || (t1&XTYPE)==ARRAY)
        !            65:                        error("Disallowed conversion");
        !            66:                if (p1->t.type==UNCHAR) {
        !            67:                        *cp++ = block(ETYPE, UNSIGN, (int *)NULL, (union str *)NULL,
        !            68:                           TNULL, TNULL);
        !            69:                        *cp++ = p2;
        !            70:                        build(CAST);
        !            71:                        *cp++ = cblock(0377);
        !            72:                        build(AND);
        !            73:                        return;
        !            74:                }
        !            75:                if (p2->t.type==CHAR || p2->t.type==UNCHAR)
        !            76:                        p2 = block(PLUS, t2, (int *)NULL, (union str *)NULL,
        !            77:                           p2, cblock(0));
        !            78:                break;
        !            79: 
        !            80:        /* end of expression */
        !            81:        case 0:
        !            82:                *cp++ = p1;
        !            83:                return;
        !            84: 
        !            85:        /* no-conversion operators */
        !            86:        case QUEST:
        !            87:                if (p2->t.op!=COLON)
        !            88:                        error("Illegal conditional");
        !            89:                else
        !            90:                        if (fold(QUEST, p1, p2))
        !            91:                                return;
        !            92: 
        !            93:        case SEQNC:
        !            94:                t = t2;
        !            95: 
        !            96:        case COMMA:
        !            97:        case LOGAND:
        !            98:        case LOGOR:
        !            99:                *cp++ = block(op, t, p2->t.subsp, p2->t.strp, p1, p2);
        !           100:                return;
        !           101: 
        !           102:        case EXCLA:
        !           103:                t1 = INT;
        !           104:                break;
        !           105: 
        !           106:        case CALL:
        !           107:                if ((t1&XTYPE) != FUNC)
        !           108:                        error("Call of non-function");
        !           109:                *cp++ = block(CALL,decref(t1),p1->t.subsp,p1->t.strp,p1,p2);
        !           110:                return;
        !           111: 
        !           112:        case STAR:
        !           113:                if ((t1&XTYPE) == FUNC)
        !           114:                        error("Illegal indirection");
        !           115:                *cp++ = block(STAR, decref(t1), p1->t.subsp, p1->t.strp, p1, TNULL);
        !           116:                return;
        !           117: 
        !           118:        case AMPER:
        !           119:                if (p1->t.op==NAME || p1->t.op==STAR) {
        !           120:                        *cp++ = block(op,incref(p1->t.type),p1->t.subsp,p1->t.strp,p1,TNULL);
        !           121:                        return;
        !           122:                }
        !           123:                error("Illegal lvalue");
        !           124:                break;
        !           125: 
        !           126:        /*
        !           127:         * a.b goes to (&a)->b
        !           128:         */
        !           129:        case DOT:
        !           130:                if (p1->t.op==CALL && t1==STRUCT) {
        !           131:                        t1 = incref(t1);
        !           132:                        setype(p1, t1, p1);
        !           133:                } else {
        !           134:                        *cp++ = p1;
        !           135:                        build(AMPER);
        !           136:                        p1 = *--cp;
        !           137:                }
        !           138: 
        !           139:        /*
        !           140:         * In a->b, a is given the type ptr-to-structure element;
        !           141:         * then the offset is added in without conversion;
        !           142:         * then * is tacked on to access the member.
        !           143:         */
        !           144:        case ARROW:
        !           145:                if (p2->t.op!=NAME || p2->t.tr1->n.hclass!=MOS) {
        !           146:                        error("Illegal structure ref");
        !           147:                        *cp++ = p1;
        !           148:                        return;
        !           149:                }
        !           150:                p2 = structident(p1, p2);
        !           151:                t2 = p2->n.htype;
        !           152:                if (t2==INT && p2->t.tr1->n.hflag&FFIELD)
        !           153:                        t2 = UNSIGN;
        !           154:                t = incref(t2);
        !           155:                chkw(p1, -1);
        !           156:                setype(p1, t, p2);
        !           157:                *cp++ = block(PLUS, t, p2->t.subsp, p2->t.strp,
        !           158:                   p1, cblock(p2->t.tr1->n.hoffset));
        !           159:                build(STAR);
        !           160:                if (p2->t.tr1->n.hflag&FFIELD)
        !           161:                        *cp++ = block(FSEL, UNSIGN, (int *)NULL, (union str *)NULL, 
        !           162:                            *--cp, p2->t.tr1->n.hstrp);
        !           163:                return;
        !           164:        }
        !           165:        if ((dope&LVALUE)!=0)
        !           166:                chklval(p1);
        !           167:        if ((dope&LWORD)!=0)
        !           168:                chkw(p1, LONG);
        !           169:        if ((dope&RWORD)!=0)
        !           170:                chkw(p2, LONG);
        !           171:        if ((t1==VOID && op!=CAST) || (t2==VOID && (op!=CAST || t1!=VOID))) {
        !           172:                error("Illegal use of void object");
        !           173:                t = t1 = t2 = INT;
        !           174:        }
        !           175:        if ((dope&BINARY)==0) {
        !           176:                if (op==ITOF)
        !           177:                        t1 = DOUBLE;
        !           178:                else if (op==FTOI)
        !           179:                        t1 = INT;
        !           180:                if (!fold(op, p1, (union tree *)NULL))
        !           181:                        *cp++ = block(op, t1, p1->t.subsp, p1->t.strp, p1,TNULL);
        !           182:                return;
        !           183:        }
        !           184:        cvn = 0;
        !           185:        if (t1==STRUCT || t2==STRUCT) {
        !           186:                if (t1!=t2 || p1->t.strp != p2->t.strp)
        !           187:                        error("Incompatible structures");
        !           188:                cvn = 0;
        !           189:        } else
        !           190:                cvn = cvtab[lintyp(t1)][lintyp(t2)];
        !           191:        leftc = (cvn>>4)&017;
        !           192:        cvn &= 017;
        !           193:        t = leftc? t2:t1;
        !           194:        if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN))
        !           195:                t = UNSIGN;
        !           196:        if (dope&ASSGOP || op==CAST) {
        !           197:                if (leftc && (op>=ASPLUS && op<=ASXOR)) {
        !           198:                        assignop(op, p1, p2);
        !           199:                        return;
        !           200:                }
        !           201:                t = t1;
        !           202:                if (op==ASSIGN) {
        !           203:                        if (cvn==PTI) {
        !           204:                                if (t1!=t2 || ((t1&TYPE)==STRUCT && p1->t.strp!=p2->t.strp)) {
        !           205:                                        error("Warning: mixed pointer assignment");
        !           206:                                        nerror--;
        !           207:                                }
        !           208:                                cvn = leftc = 0;
        !           209:                        }
        !           210:                } else if (op==CAST) {
        !           211:                        if (cvn==ITP||cvn==PTI)
        !           212:                                cvn = leftc = 0;
        !           213:                        else if (cvn==LTP) {
        !           214:                                if (leftc==0)
        !           215:                                        cvn = LTI;
        !           216:                                else {
        !           217:                                        cvn = ITL;
        !           218:                                        leftc = 0;
        !           219:                                }
        !           220:                        }
        !           221:                }
        !           222:                if (leftc)
        !           223:                        cvn = leftc;
        !           224:                leftc = 0;
        !           225:        } else if (op==COLON || op==MAX || op==MIN) {
        !           226:                if (t1>=PTR && t1==t2)
        !           227:                        cvn = 0;
        !           228:                if (op!=COLON && (t1>=PTR || t2>=PTR))
        !           229:                        op += MAXP-MAX;
        !           230:        } else if (dope&RELAT) {
        !           231:                if (op>=LESSEQ && (t1>=PTR||t2>=PTR||(t1==UNSIGN||t2==UNSIGN)
        !           232:                 && (t==INT||t==CHAR||t==UNSIGN)))
        !           233:                        op += LESSEQP-LESSEQ;
        !           234:                if (cvn==ITP || cvn==PTI)
        !           235:                        cvn = 0;
        !           236:        }
        !           237:        if (cvn==PTI) {
        !           238:                cvn = 0;
        !           239:                if (op==MINUS) {
        !           240:                        pcvn++;
        !           241:                        p1 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p1, TNULL);
        !           242:                        p2 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p2, TNULL);
        !           243:                        t = LONG;
        !           244:                } else {
        !           245:                        if (t1!=t2 || (t1!=(PTR+CHAR) && t1!=(PTR+UNCHAR)))
        !           246:                                cvn = XX;
        !           247:                }
        !           248:        }
        !           249:        if (cvn) {
        !           250:                if ((cvn==ITP || cvn==LTP) && (opdope[op]&PCVOK)==0) {
        !           251:                        p3 = leftc? p1: p2;
        !           252:                        if ((p3->t.op!=CON || p3->c.value!=0)
        !           253:                         && (p3->t.op!=LCON || p3->l.lvalue!=0))
        !           254:                                cvn = XX;
        !           255:                        else
        !           256:                                cvn = 0;
        !           257:                }
        !           258:                t1 = plength(p1);
        !           259:                t2 = plength(p2);
        !           260:                if (cvn==XX || (cvn==PTI&&t1!=t2))
        !           261:                        error("Illegal conversion");
        !           262:                else if (leftc)
        !           263:                        p1 = convert(p1, t, cvn, t2);
        !           264:                else
        !           265:                        p2 = convert(p2, t, cvn, t1);
        !           266:        }
        !           267:        if (dope&RELAT)
        !           268:                t = INT;
        !           269:        if (t==FLOAT)
        !           270:                t = DOUBLE;
        !           271:        if (t==CHAR)
        !           272:                t = INT;
        !           273:        if (op==CAST) {
        !           274:                if (t!=DOUBLE && (t!=INT || p2->t.type!=CHAR || p2->t.type!=UNCHAR)) {
        !           275:                        p2->t.type = t;
        !           276:                        p2->t.subsp = p1->t.subsp;
        !           277:                        p2->t.strp = p1->t.strp;
        !           278:                }
        !           279:                if (t==INT && p1->t.type==CHAR)
        !           280:                        p2 = block(ITOC, INT, (int *)NULL, (union str *)NULL, p2, TNULL);
        !           281:                *cp++ = p2;
        !           282:                return;
        !           283:        }
        !           284:        if (pcvn)
        !           285:                t2 = plength(p1->t.tr1);
        !           286:        if (fold(op, p1, p2)==0) {
        !           287:                p3 = leftc?p2:p1;
        !           288:                *cp++ = block(op, t, p3->t.subsp, p3->t.strp, p1, p2);
        !           289:        }
        !           290:        if (pcvn) {
        !           291:                p1 = *--cp;
        !           292:                *cp++ = convert(p1, 0, PTI, t2);
        !           293:        }
        !           294: }
        !           295: 
        !           296: union tree *
        !           297: structident(p1, p2)
        !           298: register union tree *p1, *p2;
        !           299: {
        !           300:        register struct nmlist *np;
        !           301:        int vartypes = 0, namesame = 1;
        !           302: 
        !           303:        np = (struct nmlist *)p2->t.tr1;
        !           304:        for (;;) {
        !           305:                if (namesame && p1->t.type==STRUCT+PTR && p1->t.strp == np->sparent) {
        !           306:                        p2->t.type = np->htype;
        !           307:                        p2->t.strp = np->hstrp;
        !           308:                        p2->t.subsp = np->hsubsp;
        !           309:                        p2->t.tr1 = (union tree *)np;
        !           310:                        return(p2);
        !           311:                }
        !           312:                np = np->nextnm;
        !           313:                if (np==NULL)
        !           314:                        break;
        !           315:                namesame = 0;
        !           316:                if (strncmp(p2->t.tr1->n.name, np->name, NCPS) != 0)
        !           317:                        continue;
        !           318:                if ((p2->t.tr1->n.hflag&FKIND) != (np->hflag&FMOS))
        !           319:                        continue;
        !           320:                namesame = 1;
        !           321:                if (p2->t.tr1->n.htype==np->htype && p2->t.tr1->n.hoffset==np->hoffset)
        !           322:                        continue;
        !           323:                vartypes++;
        !           324:        }
        !           325:        if (vartypes)
        !           326:                error("Ambiguous structure reference for %.8s", p2->t.tr1->n.name);
        !           327:        else {
        !           328:                error("Warning: %.8s not member of cited struct/union", p2->t.tr1->n.name);
        !           329:                nerror--;
        !           330:        }
        !           331:        return(p2);
        !           332: }
        !           333: 
        !           334: /*
        !           335:  * Generate the appropriate conversion operator.
        !           336:  */
        !           337: union tree *
        !           338: convert(p, t, cvn, len)
        !           339: union tree *p;
        !           340: {
        !           341:        register int op;
        !           342: 
        !           343:        if (cvn==0)
        !           344:                return(p);
        !           345:        op = cvntab[cvn];
        !           346:        if (opdope[op]&BINARY) {
        !           347:                if (len==0)
        !           348:                        error("Illegal conversion");
        !           349:                return(block(op, t, (int *)NULL, (union str *)NULL, p, cblock(len)));
        !           350:        }
        !           351:        return(block(op, t, (int *)NULL, (union str *)NULL, p, TNULL));
        !           352: }
        !           353: 
        !           354: /*
        !           355:  * Traverse an expression tree, adjust things
        !           356:  * so the types of things in it are consistent
        !           357:  * with the view that its top node has
        !           358:  * type at.
        !           359:  * Used with structure references.
        !           360:  */
        !           361: setype(p, t, newp)
        !           362: register union tree *p, *newp;
        !           363: register t;
        !           364: {
        !           365:        for (;; p = p->t.tr1) {
        !           366:                p->t.subsp = newp->t.subsp;
        !           367:                p->t.strp = newp->t.strp;
        !           368:                p->t.type = t;
        !           369:                if (p->t.op==AMPER)
        !           370:                        t = decref(t);
        !           371:                else if (p->t.op==STAR)
        !           372:                        t = incref(t);
        !           373:                else if (p->t.op!=PLUS)
        !           374:                        break;
        !           375:        }
        !           376: }
        !           377: 
        !           378: /*
        !           379:  * A mention of a function name is turned into
        !           380:  * a pointer to that function.
        !           381:  */
        !           382: union tree *
        !           383: chkfun(p)
        !           384: register union tree *p;
        !           385: {
        !           386:        register int t;
        !           387: 
        !           388:        if (((t = p->t.type)&XTYPE)==FUNC && p->t.op!=ETYPE)
        !           389:                return(block(AMPER,incref(t),p->t.subsp,p->t.strp,p,TNULL));
        !           390:        return(p);
        !           391: }
        !           392: 
        !           393: /*
        !           394:  * A mention of an array is turned into
        !           395:  * a pointer to the base of the array.
        !           396:  */
        !           397: union tree *
        !           398: disarray(p)
        !           399: register union tree *p;
        !           400: {
        !           401:        register int t;
        !           402: 
        !           403:        if (p==NULL)
        !           404:                return(p);
        !           405:        /* check array & not MOS and not typer */
        !           406:        if (((t = p->t.type)&XTYPE)!=ARRAY
        !           407:         || p->t.op==NAME && p->t.tr1->n.hclass==MOS
        !           408:         || p->t.op==ETYPE)
        !           409:                return(p);
        !           410:        p->t.subsp++;
        !           411:        *cp++ = p;
        !           412:        setype(p, decref(t), p);
        !           413:        build(AMPER);
        !           414:        return(*--cp);
        !           415: }
        !           416: 
        !           417: /*
        !           418:  * make sure that p is a ptr to a node
        !           419:  * with type int or char or 'okt.'
        !           420:  * okt might be nonexistent or 'long'
        !           421:  * (e.g. for <<).
        !           422:  */
        !           423: chkw(p, okt)
        !           424: union tree *p;
        !           425: {
        !           426:        register int t;
        !           427: 
        !           428:        if ((t=p->t.type)!=INT && t<PTR && t!=CHAR && t!=UNCHAR && t!=UNSIGN && t!=okt)
        !           429:                error("Illegal type of operand");
        !           430:        return;
        !           431: }
        !           432: 
        !           433: /*
        !           434:  *'linearize' a type for looking up in the
        !           435:  * conversion table
        !           436:  */
        !           437: lintyp(t)
        !           438: {
        !           439:        switch(t) {
        !           440: 
        !           441:        case INT:
        !           442:        case CHAR:
        !           443:        case UNSIGN:
        !           444:        case UNCHAR:
        !           445:                return(0);
        !           446: 
        !           447:        case FLOAT:
        !           448:        case DOUBLE:
        !           449:                return(1);
        !           450: 
        !           451:        case LONG:
        !           452:                return(2);
        !           453: 
        !           454:        default:
        !           455:                return(3);
        !           456:        }
        !           457: }
        !           458: 
        !           459: /*
        !           460:  * Report an error.
        !           461:  */
        !           462: /* VARARGS1 */
        !           463: error(s, p1, p2, p3, p4, p5, p6)
        !           464: char *s;
        !           465: {
        !           466:        nerror++;
        !           467:        if (filename[0])
        !           468:                fprintf(stderr, "%s:", filename);
        !           469:        fprintf(stderr, "%d: ", line);
        !           470:        fprintf(stderr, s, p1, p2, p3, p4, p5, p6);
        !           471:        fprintf(stderr, "\n");
        !           472: }
        !           473: 
        !           474: /*
        !           475:  * Generate a node in an expression tree,
        !           476:  * setting the operator, type, dimen/struct table ptrs,
        !           477:  * and the operands.
        !           478:  */
        !           479: union tree *
        !           480: block(op, t, subs, str, p1,p2)
        !           481: int *subs;
        !           482: union str *str;
        !           483: union tree *p1, *p2;
        !           484: {
        !           485:        register union tree *p;
        !           486: 
        !           487:        p = (union tree *)Tblock(sizeof(struct tnode));
        !           488:        p->t.op = op;
        !           489:        p->t.type = t;
        !           490:        p->t.subsp = subs;
        !           491:        p->t.strp = str;
        !           492:        p->t.tr1 = p1;
        !           493:        if (opdope[op]&BINARY)
        !           494:                p->t.tr2 = p2;
        !           495:        else
        !           496:                p->t.tr2 = NULL;
        !           497:        return(p);
        !           498: }
        !           499: 
        !           500: union tree *
        !           501: nblock(ds)
        !           502: register struct nmlist *ds;
        !           503: {
        !           504:        return(block(NAME, ds->htype, ds->hsubsp, ds->hstrp, (union tree *)ds, TNULL));
        !           505: }
        !           506: 
        !           507: /*
        !           508:  * Generate a block for a constant
        !           509:  */
        !           510: union tree *
        !           511: cblock(v)
        !           512: {
        !           513:        register union tree *p;
        !           514: 
        !           515:        p = (union tree *)Tblock(sizeof(struct cnode));
        !           516:        p->c.op = CON;
        !           517:        p->c.type = INT;
        !           518:        p->c.subsp = NULL;
        !           519:        p->c.strp = NULL;
        !           520:        p->c.value = v;
        !           521:        return(p);
        !           522: }
        !           523: 
        !           524: /*
        !           525:  * A block for a float constant
        !           526:  */
        !           527: union tree *
        !           528: fblock(t, string)
        !           529: char *string;
        !           530: {
        !           531:        register union tree *p;
        !           532: 
        !           533:        p = (union tree *)Tblock(sizeof(struct fnode));
        !           534:        p->f.op = FCON;
        !           535:        p->f.type = t;
        !           536:        p->f.subsp = NULL;
        !           537:        p->f.strp = NULL;
        !           538:        p->f.cstr = string;
        !           539:        return(p);
        !           540: }
        !           541: 
        !           542: /*
        !           543:  * Assign a block for use in the
        !           544:  * expression tree.
        !           545:  */
        !           546: char *
        !           547: Tblock(n)
        !           548: {
        !           549:        register char *p;
        !           550: 
        !           551:        p = treebase;
        !           552:        if (p==NULL) {
        !           553:                error("c0 internal error: tree not active");
        !           554:                exit(1);
        !           555:        }
        !           556:        if ((treebase += n) >= coremax) {
        !           557:                if (sbrk(1024) == (char *)-1) {
        !           558:                        error("Out of space");
        !           559:                        exit(1);
        !           560:                }
        !           561:                coremax += 1024;
        !           562:        }
        !           563:        return(p);
        !           564: }
        !           565: 
        !           566: char *
        !           567: starttree()
        !           568: {
        !           569:        register char *st;
        !           570: 
        !           571:        st = treebase;
        !           572:        if (st==NULL)
        !           573:                treebot = treebase = locbase+DCLSLOP;
        !           574:        return(st);
        !           575: }
        !           576: 
        !           577: endtree(tp)
        !           578: char *tp;
        !           579: {
        !           580:        treebase = tp;
        !           581:        if (tp==NULL)
        !           582:                treebot = NULL;
        !           583: }
        !           584: 
        !           585: /*
        !           586:  * Assign a block for use in a declaration
        !           587:  */
        !           588: char *
        !           589: Dblock(n)
        !           590: {
        !           591:        register char *p;
        !           592: 
        !           593:        p = locbase;
        !           594:        locbase += n;
        !           595:        if (treebot && locbase > treebot) {
        !           596:                error("Too much declaring in an expression");
        !           597:                exit(1);
        !           598:        }
        !           599:        if (locbase > coremax) {
        !           600:                if (sbrk(1024) == (char *)-1) {
        !           601:                        error("out of space");
        !           602:                        exit(1);
        !           603:                }
        !           604:                coremax += 1024;
        !           605:        }
        !           606:        return(p);
        !           607: }
        !           608: 
        !           609: /*
        !           610:  * Check that a tree can be used as an lvalue.
        !           611:  */
        !           612: chklval(p)
        !           613: register union tree *p;
        !           614: {
        !           615:        if (p->t.op==FSEL)
        !           616:                p = p->t.tr1;
        !           617:        if (p->t.op!=NAME && p->t.op!=STAR)
        !           618:                error("Lvalue required");
        !           619: }
        !           620: 
        !           621: /*
        !           622:  * reduce some forms of `constant op constant'
        !           623:  * to a constant.  More of this is done in the next pass
        !           624:  * but this is used to allow constant expressions
        !           625:  * to be used in switches and array bounds.
        !           626:  */
        !           627: fold(op, p1, p2)
        !           628: register union tree *p1;
        !           629: union tree *p2;
        !           630: {
        !           631:        register int v1, v2;
        !           632:        int unsignf;
        !           633: 
        !           634:        if (p1->t.op!=CON)
        !           635:                return(0);
        !           636:        unsignf = p1->c.type==UNSIGN;
        !           637:        if (op==QUEST) {
        !           638:                if (p2->t.tr1->t.op==CON && p2->t.tr2->t.op==CON) {
        !           639:                        p1->c.value = p1->c.value? p2->t.tr1->c.value: p2->t.tr2->c.value;
        !           640:                        *cp++ = p1;
        !           641:                        p1->t.type = p2->t.type;
        !           642:                        return(1);
        !           643:                }
        !           644:                return(0);
        !           645:        }
        !           646:        if (p2) {
        !           647:                if (p2->t.op!=CON)
        !           648:                        return(0);
        !           649:                v2 = p2->c.value;
        !           650:                unsignf |= p2->c.type==UNSIGN;
        !           651:        }
        !           652:        v1 = p1->c.value;
        !           653:        switch (op) {
        !           654: 
        !           655:        case PLUS:
        !           656:                v1 += v2;
        !           657:                break;
        !           658: 
        !           659:        case MINUS:
        !           660:                v1 -= v2;
        !           661:                break;
        !           662: 
        !           663:        case TIMES:
        !           664:                v1 *= v2;
        !           665:                break;
        !           666: 
        !           667:        case DIVIDE:
        !           668:                if (v2==0)
        !           669:                        goto divchk;
        !           670:                if (unsignf) {
        !           671:                        if (v2==1)
        !           672:                                break;
        !           673:                        if (v2<0) {
        !           674:                                v1 = (unsigned)v1 >= (unsigned)v2;
        !           675:                                break;
        !           676:                        }
        !           677:                        v1 = (unsigned)v1 / v2;
        !           678:                        break;
        !           679:                }
        !           680:                v1 /= v2;
        !           681:                break;
        !           682: 
        !           683:        case MOD:
        !           684:                if (v2==0)
        !           685:                        goto divchk;
        !           686:                if (unsignf) {
        !           687:                        if (v2==1) {
        !           688:                                v1 = 0;
        !           689:                                break;
        !           690:                        }
        !           691:                        if (v2<0) {
        !           692:                                if ((unsigned)v1 >= (unsigned)v2)
        !           693:                                        v1 -= v2;
        !           694:                                break;
        !           695:                        }
        !           696:                        v1 = (unsigned)v1 % v2;
        !           697:                        break;
        !           698:                }
        !           699:                v1 %= v2;
        !           700:                break;
        !           701: 
        !           702:        case AND:
        !           703:                v1 &= v2;
        !           704:                break;
        !           705: 
        !           706:        case OR:
        !           707:                v1 |= v2;
        !           708:                break;
        !           709: 
        !           710:        case EXOR:
        !           711:                v1 ^= v2;
        !           712:                break;
        !           713: 
        !           714:        case NEG:
        !           715:                v1 = - v1;
        !           716:                break;
        !           717: 
        !           718:        case COMPL:
        !           719:                v1 = ~ v1;
        !           720:                break;
        !           721: 
        !           722:        case LSHIFT:
        !           723:                v1 <<= v2;
        !           724:                break;
        !           725: 
        !           726:        case RSHIFT:
        !           727:                if (unsignf) {
        !           728:                        v1 = (unsigned)v1 >> v2;
        !           729:                        break;
        !           730:                }
        !           731:                v1 >>= v2;
        !           732:                break;
        !           733: 
        !           734:        case EQUAL:
        !           735:                v1 = v1==v2;
        !           736:                break;
        !           737: 
        !           738:        case NEQUAL:
        !           739:                v1 = v1!=v2;
        !           740:                break;
        !           741: 
        !           742:        case LESS:
        !           743:                v1 = v1<v2;
        !           744:                break;
        !           745: 
        !           746:        case GREAT:
        !           747:                v1 = v1>v2;
        !           748:                break;
        !           749: 
        !           750:        case LESSEQ:
        !           751:                v1 = v1<=v2;
        !           752:                break;
        !           753: 
        !           754:        case GREATEQ:
        !           755:                v1 = v1>=v2;
        !           756:                break;
        !           757: 
        !           758:        divchk:
        !           759:                error("Divide check");
        !           760:                nerror--;
        !           761:        default:
        !           762:                return(0);
        !           763:        }
        !           764:        p1->c.value = v1;
        !           765:        *cp++ = p1;
        !           766:        if (unsignf)
        !           767:                p1->t.type = UNSIGN;
        !           768:        return(1);
        !           769: }
        !           770: 
        !           771: /*
        !           772:  * Compile an expression expected to have constant value,
        !           773:  * for example an array bound or a case value.
        !           774:  */
        !           775: conexp()
        !           776: {
        !           777:        register union tree *t;
        !           778: 
        !           779:        initflg++;
        !           780:        if (t = tree(1))
        !           781:                if (t->t.op != CON)
        !           782:                        error("Constant required");
        !           783:        initflg--;
        !           784:        return(t->c.value);
        !           785: }
        !           786: 
        !           787: /*
        !           788:  * Handle peculiar assignment ops that need a temporary.
        !           789:  */
        !           790: assignop(op, p1, p2)
        !           791: register union tree *p1, *p2;
        !           792: {
        !           793:        register struct nmlist *np;
        !           794: 
        !           795:        op += PLUS - ASPLUS;
        !           796:        if (p1->t.op==NAME) {
        !           797:                *cp++ = p1;
        !           798:                *cp++ = p1;
        !           799:                *cp++ = p2;
        !           800:                build(op);
        !           801:                build(ASSIGN);
        !           802:                return;
        !           803:        }
        !           804:        np = gentemp(incref(p1->t.type));
        !           805:        *cp++ = nblock(np);
        !           806:        *cp++ = p1;
        !           807:        build(AMPER);
        !           808:        build(ASSIGN);
        !           809:        *cp++ = nblock(np);
        !           810:        build(STAR);
        !           811:        *cp++ = nblock(np);
        !           812:        build(STAR);
        !           813:        *cp++ = p2;
        !           814:        build(op);
        !           815:        build(ASSIGN);
        !           816:        build(SEQNC);
        !           817: }
        !           818: 
        !           819: /*
        !           820:  * Generate an automatic temporary for
        !           821:  * use in certain assignment ops
        !           822:  */
        !           823: struct nmlist *
        !           824: gentemp(type)
        !           825: {
        !           826:        register struct nmlist *tp;
        !           827: 
        !           828:        tp = (struct nmlist *)Tblock(sizeof(struct nmlist));
        !           829:        tp->hclass = AUTO;
        !           830:        tp->htype = type;
        !           831:        tp->hflag = 0;
        !           832:        tp->hsubsp = NULL;
        !           833:        tp->hstrp = NULL;
        !           834:        tp->hblklev = blklev;
        !           835:        autolen -= rlength((union tree *)tp);
        !           836:        tp->hoffset = autolen;
        !           837:        if (autolen < maxauto)
        !           838:                maxauto = autolen;
        !           839:        return(tp);
        !           840: }

unix.superglobalmegacorp.com

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