Annotation of researchv10no/cmd/PDP11/11c/c01.c, revision 1.1.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.