# 2.11BSD#431 - /usr/src/lib/ccom/c01.c

##### Functions

    Dblock            X
    Tblock            X
    assignop          X
    block             X
    build             X
    cblock            X
    chkfun            X
    chklval           X
    chkw              X
    conexp            X
    convert           X
    disarray          X
    endtree           X
    error             X
    fblock            X
    fold              X
    gentemp           X
    lintyp            X
    nblock            X
    setype            X
    starttree         X
    structident       X
    werror            X

       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:     /*
      94: 	 * Bug fix, because copying type is not enough,
      95: 	 * i.e. t = (t, t) + 1;
      96: 	 * Original code was:
      97: 	 *	case SEQNC:
      98: 	 *		t = t2;
      99: 	 *	case COMMA:
     100: 	 */
     101:     case SEQNC:
     102:         *cp++ = block(op, t2, p2->t.subsp, p2->t.strp, p1, p2);
     103:         return;
     104:
     105:     case COMMA:
     106:     case LOGAND:
     107:     case LOGOR:
     108:         *cp++ = block(op, t, p2->t.subsp, p2->t.strp, p1, p2);
     109:         return;
     110:
     111:     case EXCLA:
     112:         t1 = INT;
     113:         break;
     114:
     115:     case CALL:
     116:         if ((t1&XTYPE) == PTR && (decref(t1)&XTYPE) == FUNC) {
     117:             /*
     118: 			 * Modification to allow calling a function via a
     119: 			 * pointer to a function ("f") without explicitly
     120: 			 * dereferencing the pointer.  That is: f(...) is now
     121: 			 * legal as well as (*f)(...).  The insistence that
     122: 			 * decref(t1) be FUNC prevents pointers to pointers to
     123: 			 * functions and so on from being automatically
     124: 			 * dereferenced which would be incorrect and introduce
     125: 			 * porting problems.  Note that for purity FUNC's
     126: 			 * should really always be referenced (as in pcc) and
     127: 			 * that the new notation is actually more consistent
     128: 			 * with the rest of C ...
     129: 			 */
     130:             *cp++ = p1;
     131:             build(STAR);
     132:             *cp++ = p2;
     133:             build(CALL);
     134:             return;
     135:         }
     136:         if ((t1&XTYPE) != FUNC)
     137:             error("Call of non-function");
     138:         *cp++ = block(CALL,decref(t1),p1->t.subsp,p1->t.strp,p1,p2);
     139:         return;
     140:
     141:     case STAR:
     142:         if ((t1&XTYPE) == FUNC)
     143:             error("Illegal indirection");
     144:         *cp++ = block(STAR, decref(t1), p1->t.subsp, p1->t.strp, p1, TNULL);
     145:         return;
     146:
     147:     case AMPER:
     148:         if (p1->t.op==NAME || p1->t.op==STAR) {
     149:             *cp++ = block(op,incref(p1->t.type),p1->t.subsp,p1->t.strp,p1,TNULL);
     150:             return;
     151:         }
     152:         error("Illegal lvalue");
     153:         break;
     154:
     155:     /*
     156: 	 * a.b goes to (&a)->b
     157: 	 */
     158:     case DOT:
     159:         if (p1->t.op==CALL && t1==STRUCT) {
     160:             t1 = incref(t1);
     161:             setype(p1, t1, p1);
     162:         } else {
     163:             *cp++ = p1;
     164:             build(AMPER);
     165:             p1 = *--cp;
     166:         }
     167:
     168:     /*
     169: 	 * In a->b, a is given the type ptr-to-structure element;
     170: 	 * then the offset is added in without conversion;
     171: 	 * then * is tacked on to access the member.
     172: 	 */
     173:     case ARROW:
     174:         if (p2->t.op!=NAME || p2->t.tr1->n.hclass!=MOS) {
     175:             error("Illegal structure ref");
     176:             *cp++ = p1;
     177:             return;
     178:         }
     179:         p2 = structident(p1, p2);
     180:         t2 = p2->n.htype;
     181:         if (t2==INT && p2->t.tr1->n.hflag&FFIELD)
     182:             t2 = UNSIGN;
     183:         t = incref(t2);
     184:         chkw(p1, -1);
     185:         setype(p1, t, p2);
     186:         *cp++ = block(PLUS, t, p2->t.subsp, p2->t.strp,
     187:            p1, cblock(p2->t.tr1->n.hoffset));
     188:         build(STAR);
     189:         if (p2->t.tr1->n.hflag&FFIELD)
     190:             *cp++ = block(FSEL, UNSIGN, (int *)NULL, (union str *)NULL,
     191:                 *--cp, p2->t.tr1->n.hstrp);
     192:         return;
     193:     }
     194:     if ((dope&LVALUE)!=0)
     195:         chklval(p1);
     196:     if ((dope&LWORD)!=0)
     197:         chkw(p1, LONG);
     198:     if ((dope&RWORD)!=0)
     199:         chkw(p2, LONG);
     200:     if ((t1==VOID && op!=CAST) || (t2==VOID && (op!=CAST || t1!=VOID))) {
     201:         error("Illegal use of void object");
     202:         t = t1 = t2 = INT;
     203:     }
     204:     if ((dope&BINARY)==0) {
     205:         if (op==ITOF)
     206:             t1 = DOUBLE;
     207:         else if (op==FTOI)
     208:             t1 = INT;
     209:         if (!fold(op, p1, (union tree *)NULL))
     210:             *cp++ = block(op, t1, p1->t.subsp, p1->t.strp, p1,TNULL);
     211:         return;
     212:     }
     213:     cvn = 0;
     214:     if (t1==STRUCT || t2==STRUCT) {
     215:         if (t1!=t2 || p1->t.strp != p2->t.strp)
     216:             error("Incompatible structures");
     217:         cvn = 0;
     218:     } else
     219:         cvn = cvtab[lintyp(t1)][lintyp(t2)];
     220:     leftc = (cvn>>4)&017;
     221:     cvn &= 017;
     222:     t = leftc? t2:t1;
     223:     if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN))
     224:         t = UNSIGN;
     225:     if (dope&ASSGOP || op==CAST) {
     226:         /*
     227: 		 * Weird "lhs op= rhs" requiring a temporary to evaluate as
     228: 		 * "lhs = lhs op rhs" so lhs can be converted up for the
     229: 		 * operation and then the result converted back down for
     230: 		 * the assignment.  As a special sub case, "(int) op= (long)"
     231: 		 * doesn't require a temporary except for /= and %= ...
     232: 		 */
     233:         if (leftc && op>=ASPLUS && op<=ASXOR
     234:             && (leftc!=LTI || op==ASDIV || op==ASMOD)) {
     235:             assignop(op, p1, p2);
     236:             return;
     237:         }
     238:         t = t1;
     239:         if (op==ASSIGN) {
     240:             if (cvn==PTI) {
     241:                 if (t1!=t2 || ((t1&TYPE)==STRUCT && p1->t.strp!=p2->t.strp))
     242:                     werror("mixed pointer assignment");
     243:                 cvn = leftc = 0;
     244:             } if ((cvn==ITP || cvn==LTP)
     245:                && (p2->t.op!=CON || p2->c.value!=0)
     246:                && (p2->t.op!=LCON || p2->l.lvalue!=0)) {
     247:             /*
     248: 			 * Allow "i = p" and "p = i" with a warning, where
     249: 			 * i is some form of integer (not 0) and p is a
     250: 			 * pointer.  Note that in both this patch and the
     251: 			 * similar one for "?:" below, code from the CAST
     252: 			 * immediately below and the illegal conversion
     253: 			 * check farther below is simply stolen.  It would
     254: 			 * require either a recursive call to build or a
     255: 			 * fairly large rewrite to eliminate the
     256: 			 * duplication.
     257: 			 */
     258:                 werror("illegal combination of pointer and integer, op =");
     259:                 if (cvn==ITP)
     260:                     cvn = leftc = 0;
     261:                 else
     262:                     if (leftc==0)
     263:                         cvn = LTI;
     264:                     else {
     265:                         cvn = ITL;
     266:                         leftc = 0;
     267:                     }
     268:             }
     269:         } else if (op==CAST) {
     270:             if (cvn==ITP||cvn==PTI)
     271:                 cvn = leftc = 0;
     272:             else if (cvn==LTP) {
     273:                 if (leftc==0)
     274:                     cvn = LTI;
     275:                 else {
     276:                     cvn = ITL;
     277:                     leftc = 0;
     278:                 }
     279:             }
     280:         }
     281:         if (leftc)
     282:             cvn = leftc;
     283:         leftc = 0;
     284:     } else if (op==COLON || op==MAX || op==MIN) {
     285:         if (t1>=PTR && t1==t2)
     286:             cvn = 0;
     287:         if (op!=COLON && (t1>=PTR || t2>=PTR))
     288:             op += MAXP-MAX;
     289:         /*
     290: 		 * Allow "e ? i : p" and "e ? p : i" with warning.
     291: 		 */
     292:         if (op==COLON && (cvn==ITP || cvn==LTP)) {
     293:             p3 = leftc? p1: p2;
     294:             if ((p3->t.op!=CON || p3->c.value!=0)
     295:              && (p3->t.op!=LCON || p3->l.lvalue!=0)) {
     296:                 werror("illegal combination of pointer and integer, op :");
     297:                 if (cvn==ITP)
     298:                     cvn = leftc = 0;
     299:                 else
     300:                     if (leftc==0)
     301:                         cvn = LTI;
     302:                     else {
     303:                         cvn = ITL;
     304:                         leftc = 0;
     305:                     }
     306:             }
     307:         }
     308:     } else if (dope&RELAT) {
     309:         if (op>=LESSEQ && (t1>=PTR||t2>=PTR||(t1==UNSIGN||t1==UNLONG||t2==UNSIGN||t2==UNLONG)
     310:          && (t==INT||t==CHAR||t==UNSIGN||t==UNLONG)))
     311:             op += LESSEQP-LESSEQ;
     312:         if (cvn==ITP || cvn==PTI)
     313:             cvn = 0;
     314:     }
     315:     if (cvn==PTI) {
     316:         cvn = 0;
     317:         if (op==MINUS) {
     318:             pcvn++;
     319:             p1 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p1, TNULL);
     320:             p2 = block(ITOL, LONG, (int *)NULL, (union str *)NULL, p2, TNULL);
     321:             t = LONG;
     322:         } else {
     323:             if (t1!=t2 || (t1!=(PTR+CHAR) && t1!=(PTR+UNCHAR)))
     324:                 cvn = XX;
     325:         }
     326:     }
     327:     if (cvn) {
     328:         if ((cvn==ITP || cvn==LTP) && (opdope[op]&PCVOK)==0) {
     329:             p3 = leftc? p1: p2;
     330:             if ((p3->t.op!=CON || p3->c.value!=0)
     331:              && (p3->t.op!=LCON || p3->l.lvalue!=0))
     332:                 cvn = XX;
     333:             else
     334:                 cvn = 0;
     335:         }
     336:         t1 = plength(p1);
     337:         t2 = plength(p2);
     338:         if (cvn==XX || (cvn==PTI&&t1!=t2))
     339:             error("Illegal conversion");
     340:         else if (leftc)
     341:             p1 = convert(p1, t, cvn, t2);
     342:         else
     343:             p2 = convert(p2, t, cvn, t1);
     344:     }
     345:     if (dope&RELAT)
     346:         t = INT;
     347:     if (t==FLOAT)
     348:         t = DOUBLE;
     349:     if (t==CHAR)
     350:         t = INT;
     351:     if (op==CAST) {
     352:         if (t!=DOUBLE && (t!=INT || p2->t.type!=CHAR || p2->t.type!=UNCHAR)) {
     353:             p2->t.type = t;
     354:             p2->t.subsp = p1->t.subsp;
     355:             p2->t.strp = p1->t.strp;
     356:         }
     357:         if (t==INT && p1->t.type==CHAR)
     358:             p2 = block(ITOC, INT, (int *)NULL, (union str *)NULL, p2, TNULL);
     359:         *cp++ = p2;
     360:         return;
     361:     }
     362:     if (pcvn)
     363:         t2 = plength(p1->t.tr1);
     364:     if (fold(op, p1, p2)==0) {
     365:         p3 = leftc?p2:p1;
     366:         *cp++ = block(op, t, p3->t.subsp, p3->t.strp, p1, p2);
     367:     }
     368:     if (pcvn) {
     369:         p1 = *--cp;
     370:         *cp++ = convert(p1, 0, PTI, t2);
     371:     }
     372: }
     373:
     374: union tree *
     375: structident(p1, p2)
     376: register union tree *p1, *p2;
     377: {
     378:     register struct nmlist *np;
     379:     int vartypes = 0, namesame = 1;
     380:
     381:     np = (struct nmlist *)p2->t.tr1;
     382:     for (;;) {
     383:         if (namesame && p1->t.type==STRUCT+PTR && p1->t.strp == np->sparent) {
     384:             p2->t.type = np->htype;
     385:             p2->t.strp = np->hstrp;
     386:             p2->t.subsp = np->hsubsp;
     387:             p2->t.tr1 = (union tree *)np;
     388:             return(p2);
     389:         }
     390:         np = np->nextnm;
     391:         if (np==NULL)
     392:             break;
     393:         namesame = 0;
     394:         if (strcmp(p2->t.tr1->n.name, np->name) != 0)
     395:             continue;
     396:         if ((p2->t.tr1->n.hflag&FKIND) != (np->hflag&FMOS))
     397:             continue;
     398:         namesame = 1;
     399:         if (p2->t.tr1->n.htype==np->htype && p2->t.tr1->n.hoffset==np->hoffset)
     400:             continue;
     401:         vartypes++;
     402:     }
     403:     if (vartypes)
     404:         error("Ambiguous structure reference for %s",p2->t.tr1->n.name);
     405:     else
     406:         werror("%s not member of cited struct/union",p2->t.tr1->n.name);
     407:     return(p2);
     408: }
     409:
     410: /*
     411:  * Generate the appropriate conversion operator.
     412:  */
     413: union tree *
     414: convert(p, t, cvn, len)
     415: union tree *p;
     416: {
     417:     register int op;
     418:
     419:     if (cvn==0)
     420:         return(p);
     421:     op = cvntab[cvn];
     422:     if (opdope[op]&BINARY) {
     423:         if (len==0)
     424:             error("Illegal conversion");
     425:         return(block(op, t, (int *)NULL, (union str *)NULL, p, cblock(len)));
     426:     }
     427:     return(block(op, t, (int *)NULL, (union str *)NULL, p, TNULL));
     428: }
     429:
     430: /*
     431:  * Traverse an expression tree, adjust things
     432:  * so the types of things in it are consistent
     433:  * with the view that its top node has
     434:  * type at.
     435:  * Used with structure references.
     436:  */
     437: setype(p, t, newp)
     438: register union tree *p, *newp;
     439: register t;
     440: {
     441:     for (;; p = p->t.tr1) {
     442:         p->t.subsp = newp->t.subsp;
     443:         p->t.strp = newp->t.strp;
     444:         p->t.type = t;
     445:         if (p->t.op==AMPER)
     446:             t = decref(t);
     447:         else if (p->t.op==STAR)
     448:             t = incref(t);
     449:         else if (p->t.op!=PLUS)
     450:             break;
     451:     }
     452: }
     453:
     454: /*
     455:  * A mention of a function name is turned into
     456:  * a pointer to that function.
     457:  */
     458: union tree *
     459: chkfun(p)
     460: register union tree *p;
     461: {
     462:     register int t;
     463:
     464:     if (((t = p->t.type)&XTYPE)==FUNC && p->t.op!=ETYPE)
     465:         return(block(AMPER,incref(t),p->t.subsp,p->t.strp,p,TNULL));
     466:     return(p);
     467: }
     468:
     469: /*
     470:  * A mention of an array is turned into
     471:  * a pointer to the base of the array.
     472:  */
     473: union tree *
     474: disarray(p)
     475: register union tree *p;
     476: {
     477:     register int t;
     478:
     479:     if (p==NULL)
     480:         return(p);
     481:     /* check array & not MOS and not typer */
     482:     if (((t = p->t.type)&XTYPE)!=ARRAY
     483:      || p->t.op==NAME && p->t.tr1->n.hclass==MOS
     484:      || p->t.op==ETYPE)
     485:         return(p);
     486:     p->t.subsp++;
     487:     *cp++ = p;
     488:     setype(p, decref(t), p);
     489:     build(AMPER);
     490:     return(*--cp);
     491: }
     492:
     493: /*
     494:  * make sure that p is a ptr to a node
     495:  * with type int or char or 'okt.'
     496:  * okt might be nonexistent or 'long'
     497:  * (e.g. for <<).
     498:  */
     499: chkw(p, okt)
     500: union tree *p;
     501: {
     502:     register int t = p->t.type;
     503:
     504:     if (t == UNLONG)
     505:         t = LONG;
     506:     if (t!=INT && t<PTR && t!=CHAR && t!=UNCHAR && t!=UNSIGN && t!=okt)
     507:         error("Illegal type of operand");
     508:     return;
     509: }
     510:
     511: /*
     512:  *'linearize' a type for looking up in the
     513:  * conversion table
     514:  */
     515: lintyp(t)
     516: {
     517:     switch(t) {
     518:
     519:     case INT:
     520:     case CHAR:
     521:     case UNSIGN:
     522:     case UNCHAR:
     523:         return(0);
     524:
     525:     case FLOAT:
     526:     case DOUBLE:
     527:         return(1);
     528:
     529:     case UNLONG:
     530:     case LONG:
     531:         return(2);
     532:
     533:     default:
     534:         return(3);
     535:     }
     536: }
     537:
     538: /*
     539:  * Report an error.
     540:  */
     541:
     542: extern int Wflag = 0;   /* Non-zero means do not print warnings */
     543:
     544: /* VARARGS1 */
     545: werror(s, p1, p2, p3, p4, p5, p6)
     546: char *s;
     547: {
     548:     if (Wflag)
     549:         return;
     550:     if (filename[0])
     551:         fprintf(stderr, "%s:", filename);
     552:     fprintf(stderr, "%d: warning: ", line);
     553:     fprintf(stderr, s, p1, p2, p3, p4, p5, p6);
     554:     fprintf(stderr, "\n");
     555: }
     556:
     557: /* VARARGS1 */
     558: error(s, p1, p2, p3, p4, p5, p6)
     559: char *s;
     560: {
     561:     nerror++;
     562:     if (filename[0])
     563:         fprintf(stderr, "%s:", filename);
     564:     fprintf(stderr, "%d: ", line);
     565:     fprintf(stderr, s, p1, p2, p3, p4, p5, p6);
     566:     fprintf(stderr, "\n");
     567: }
     568:
     569: /*
     570:  * Generate a node in an expression tree,
     571:  * setting the operator, type, dimen/struct table ptrs,
     572:  * and the operands.
     573:  */
     574: union tree *
     575: block(op, t, subs, str, p1,p2)
     576: int *subs;
     577: union str *str;
     578: union tree *p1, *p2;
     579: {
     580:     register union tree *p;
     581:
     582:     p = (union tree *)Tblock(sizeof(struct tnode));
     583:     p->t.op = op;
     584:     p->t.type = t;
     585:     p->t.subsp = subs;
     586:     p->t.strp = str;
     587:     p->t.tr1 = p1;
     588:     if (opdope[op]&BINARY)
     589:         p->t.tr2 = p2;
     590:     else
     591:         p->t.tr2 = NULL;
     592:     return(p);
     593: }
     594:
     595: union tree *
     596: nblock(ds)
     597: register struct nmlist *ds;
     598: {
     599:     return(block(NAME, ds->htype, ds->hsubsp, ds->hstrp, (union tree *)ds, TNULL));
     600: }
     601:
     602: /*
     603:  * Generate a block for a constant
     604:  */
     605: union tree *
     606: cblock(v)
     607: {
     608:     register union tree *p;
     609:
     610:     p = (union tree *)Tblock(sizeof(struct cnode));
     611:     p->c.op = CON;
     612:     p->c.type = INT;
     613:     p->c.subsp = NULL;
     614:     p->c.strp = NULL;
     615:     p->c.value = v;
     616:     return(p);
     617: }
     618:
     619: /*
     620:  * A block for a float constant
     621:  */
     622: union tree *
     623: fblock(t, string)
     624: char *string;
     625: {
     626:     register union tree *p;
     627:
     628:     p = (union tree *)Tblock(sizeof(struct fnode));
     629:     p->f.op = FCON;
     630:     p->f.type = t;
     631:     p->f.subsp = NULL;
     632:     p->f.strp = NULL;
     633:     p->f.cstr = string;
     634:     return(p);
     635: }
     636:
     637: /*
     638:  * Assign a block for use in the
     639:  * expression tree.
     640:  */
     641: char *
     642: Tblock(n)
     643: {
     644:     register char *p;
     645:
     646:     p = treebase;
     647:     if (p==NULL) {
     648:         error("c0 internal error: Tblock");
     649:         exit(1);
     650:     }
     651:     if ((treebase += n) >= coremax) {
     652:         if (sbrk(1024) == (char *)-1) {
     653:             error("Out of space");
     654:             exit(1);
     655:         }
     656:         coremax += 1024;
     657:     }
     658:     return(p);
     659: }
     660:
     661: char *
     662: starttree()
     663: {
     664:     register char *st;
     665:
     666:     st = treebase;
     667:     if (st==NULL)
     668:         treebot = treebase = locbase+DCLSLOP;
     669:     return(st);
     670: }
     671:
     672: endtree(tp)
     673: char *tp;
     674: {
     675:     treebase = tp;
     676:     if (tp==NULL)
     677:         treebot = NULL;
     678: }
     679:
     680: /*
     681:  * Assign a block for use in a declaration
     682:  */
     683: char *
     684: Dblock(n)
     685: {
     686:     register char *p;
     687:
     688:     p = locbase;
     689:     locbase += n;
     690:     if (treebot && locbase > treebot) {
     691:         error("Too much declaring in an expression");
     692:         exit(1);
     693:     }
     694:     if (locbase > coremax) {
     695:         if (sbrk(1024) == (char *)-1) {
     696:             error("out of space");
     697:             exit(1);
     698:         }
     699:         coremax += 1024;
     700:     }
     701:     return(p);
     702: }
     703:
     704: /*
     705:  * Check that a tree can be used as an lvalue.
     706:  */
     707: chklval(p)
     708: register union tree *p;
     709: {
     710:     if (p->t.op==FSEL)
     711:         p = p->t.tr1;
     712:     if (p->t.op!=NAME && p->t.op!=STAR)
     713:         error("Lvalue required");
     714: }
     715:
     716: /*
     717:  * reduce some forms of `constant op constant'
     718:  * to a constant.  More of this is done in the next pass
     719:  * but this is used to allow constant expressions
     720:  * to be used in switches and array bounds.
     721:  */
     722: fold(op, p1, p2)
     723: register union tree *p1;
     724: union tree *p2;
     725: {
     726:     register int v1, v2;
     727:     int unsignf;
     728:
     729:     if (p1->t.op!=CON)
     730:         return(0);
     731:     unsignf = p1->c.type==UNSIGN;
     732:     unsignf |= p1->c.type==UNLONG;
     733:     if (op==QUEST) {
     734:         if (p2->t.tr1->t.op==CON && p2->t.tr2->t.op==CON) {
     735:             p1->c.value = p1->c.value? p2->t.tr1->c.value: p2->t.tr2->c.value;
     736:             *cp++ = p1;
     737:             p1->t.type = p2->t.type;
     738:             return(1);
     739:         }
     740:         return(0);
     741:     }
     742:     if (p2) {
     743:         if (p2->t.op!=CON)
     744:             return(0);
     745:         v2 = p2->c.value;
     746:         unsignf |= p2->c.type==UNSIGN;
     747:         unsignf |= p2->c.type==UNLONG;
     748:     }
     749:     v1 = p1->c.value;
     750:     switch (op) {
     751:
     752:     case PLUS:
     753:         v1 += v2;
     754:         break;
     755:
     756:     case MINUS:
     757:         v1 -= v2;
     758:         break;
     759:
     760:     case TIMES:
     761:         v1 *= v2;
     762:         break;
     763:
     764:     case DIVIDE:
     765:         if (v2==0)
     766:             goto divchk;
     767:         if (unsignf) {
     768:             if (v2==1)
     769:                 break;
     770:             if (v2<0) {
     771:                 v1 = (unsigned)v1 >= (unsigned)v2;
     772:                 break;
     773:             }
     774:             v1 = (unsigned)v1 / v2;
     775:             break;
     776:         }
     777:         v1 /= v2;
     778:         break;
     779:
     780:     case MOD:
     781:         if (v2==0)
     782:             goto divchk;
     783:         if (unsignf) {
     784:             if (v2==1) {
     785:                 v1 = 0;
     786:                 break;
     787:             }
     788:             if (v2<0) {
     789:                 if ((unsigned)v1 >= (unsigned)v2)
     790:                     v1 -= v2;
     791:                 break;
     792:             }
     793:             v1 = (unsigned)v1 % v2;
     794:             break;
     795:         }
     796:         v1 %= v2;
     797:         break;
     798:
     799:     case AND:
     800:         v1 &= v2;
     801:         break;
     802:
     803:     case OR:
     804:         v1 |= v2;
     805:         break;
     806:
     807:     case EXOR:
     808:         v1 ^= v2;
     809:         break;
     810:
     811:     case NEG:
     812:         v1 = - v1;
     813:         break;
     814:
     815:     case COMPL:
     816:         v1 = ~ v1;
     817:         break;
     818:
     819:     case LSHIFT:
     820:         v1 <<= v2;
     821:         break;
     822:
     823:     case RSHIFT:
     824:         if (unsignf) {
     825:             v1 = (unsigned)v1 >> v2;
     826:             break;
     827:         }
     828:         v1 >>= v2;
     829:         break;
     830:
     831:     case EQUAL:
     832:         v1 = v1==v2;
     833:         break;
     834:
     835:     case NEQUAL:
     836:         v1 = v1!=v2;
     837:         break;
     838:
     839:     case LESS:
     840:         v1 = v1<v2;
     841:         break;
     842:
     843:     case GREAT:
     844:         v1 = v1>v2;
     845:         break;
     846:
     847:     case LESSEQ:
     848:         v1 = v1<=v2;
     849:         break;
     850:
     851:     case GREATEQ:
     852:         v1 = v1>=v2;
     853:         break;
     854:
     855:     case LESSP:
     856:         v1 = (unsigned)v1<v2;
     857:         break;
     858:
     859:     case GREATP:
     860:         v1 = (unsigned)v1>v2;
     861:         break;
     862:
     863:     case LESSEQP:
     864:         v1 = (unsigned)v1<=v2;
     865:         break;
     866:
     867:     case GREATQP:
     868:         v1 = (unsigned)v1>=v2;
     869:         break;
     870:
     871:     divchk:
     872:         error("Divide check");
     873:         nerror--;
     874:     default:
     875:         return(0);
     876:     }
     877:     p1->c.value = v1;
     878:     *cp++ = p1;
     879:     if (unsignf)
     880:         p1->t.type = UNSIGN;
     881:     return(1);
     882: }
     883:
     884: /*
     885:  * Compile an expression expected to have constant value,
     886:  * for example an array bound or a case value.
     887:  */
     888: conexp()
     889: {
     890:     register union tree *t;
     891:
     892:     initflg++;
     893:     if (t = tree(1))
     894:         if (t->t.op != CON)
     895:             error("Constant required");
     896:     initflg--;
     897:     return(t->c.value);
     898: }
     899:
     900: /*
     901:  * Handle peculiar assignment ops that need a temporary.
     902:  */
     903: assignop(op, p1, p2)
     904: register union tree *p1, *p2;
     905: {
     906:     register struct nmlist *np;
     907:
     908:     op += PLUS - ASPLUS;
     909:     if (p1->t.op==NAME) {
     910:         *cp++ = p1;
     911:         *cp++ = p1;
     912:         *cp++ = p2;
     913:         build(op);
     914:         build(ASSIGN);
     915:         return;
     916:     }
     917:     np = gentemp(incref(p1->t.type));
     918:     *cp++ = nblock(np);
     919:     *cp++ = p1;
     920:     build(AMPER);
     921:     build(ASSIGN);
     922:     *cp++ = nblock(np);
     923:     build(STAR);
     924:     *cp++ = nblock(np);
     925:     build(STAR);
     926:     *cp++ = p2;
     927:     build(op);
     928:     build(ASSIGN);
     929:     build(SEQNC);
     930: }
     931:
     932: /*
     933:  * Generate an automatic temporary for
     934:  * use in certain assignment ops
     935:  */
     936: struct nmlist *
     937: gentemp(type)
     938: {
     939:     register struct nmlist *tp;
     940:
     941:     tp = (struct nmlist *)Tblock(sizeof(struct nmlist));
     942:     tp->hclass = AUTO;
     943:     tp->htype = type;
     944:     tp->hflag = 0;
     945:     tp->hsubsp = NULL;
     946:     tp->hstrp = NULL;
     947:     tp->hblklev = blklev;
     948:     autolen -= rlength((union tree *)tp);
     949:     tp->hoffset = autolen;
     950:     if (autolen < maxauto)
     951:         maxauto = autolen;
     952:     return(tp);
     953: }

#### Defined functions

Dblock defined in line 683; used 9 times

- in /usr/src/lib/ccom/c0.h line 479
- in /usr/src/lib/ccom/c00.c line 153, 164
- in /usr/src/lib/ccom/c03.c line 185, 191, 225, 411, 456, 543

Tblock defined in line 641; used 8 times

- in line 582, 610, 628, 941
- in /usr/src/lib/ccom/c0.h line 480
- in /usr/src/lib/ccom/c00.c line 634, 674, 896

assignop defined in line 903; used 1 times

- in line 235

block defined in line 574; used 25 times

- in line 67, 76, 102, 108, 138, 144-149(2), 186-190(2), 210, 319-320(2), 358, 366, 425-427(2), 465, 599
- in /usr/src/lib/ccom/c0.h line 476
- in /usr/src/lib/ccom/c00.c line 677, 836, 887
- in /usr/src/lib/ccom/c02.c line 205, 487
- in /usr/src/lib/ccom/c04.c line 324

build defined in line 14; used 28 times

- in line 25, 70-72(2), 131-133(2), 164, 188, 489, 913-914(2), 920-929(7)
- in /usr/src/lib/ccom/c00.c line 779-780(2), 819, 832, 856-859(2)
- in /usr/src/lib/ccom/c02.c line 197, 709
- in /usr/src/lib/ccom/c04.c line 322, 340-342(2)

cblock defined in line 605; used 9 times

- in line 40, 71, 77, 187, 425
- in /usr/src/lib/ccom/c0.h line 477
- in /usr/src/lib/ccom/c00.c line 613, 642, 845

chkfun defined in line 458; used 3 times

- in line 31, 48
- in /usr/src/lib/ccom/c0.h line 474

chklval defined in line 707; used 1 times

- in line 195

chkw defined in line 499; used 5 times

- in line 184, 197-199(2)
- in /usr/src/lib/ccom/c02.c line 486
- in /usr/src/lib/ccom/c04.c line 323

conexp defined in line 888; used 4 times

- in /usr/src/lib/ccom/c02.c line 462
- in /usr/src/lib/ccom/c03.c line 324, 449, 631

convert defined in line 413; used 4 times

- in line 341-343(2), 370
- in /usr/src/lib/ccom/c0.h line 473

disarray defined in line 473; used 3 times

- in line 31, 46
- in /usr/src/lib/ccom/c0.h line 475

endtree defined in line 672; used 10 times

- in /usr/src/lib/ccom/c00.c line 821, 866
- in /usr/src/lib/ccom/c02.c line 207, 488, 591, 600, 607, 713
- in /usr/src/lib/ccom/c04.c line 325, 344

error defined in line 558; used 115 times

- in line 65, 88, 137, 143, 152, 175, 201, 216, 339, 404, 424, 507, 648-653(2), 691-696(2), 713, 872, 895
- in /usr/src/lib/ccom/c00.c line 74-83(3), 224, 238, 298, 336, 388, 401, 408, 419, 505, 535, 623, 682, 804, 863
- in /usr/src/lib/ccom/c02.c line 33, 57, 68, 83-87(2), 118, 155-160(2), 177, 194, 202, 227, 246, 258, 290, 306, 326, 466-470(2), 496-498(2), 518-522(2), 557, 634-637(2), 721, 756, 774
- in /usr/src/lib/ccom/c03.c line 53, 70, 85, 101, 123, 133, 200, 222, 326, 360, 367, 425, 467, 517, 625, 637, 661, 691, 698, 704, 714, 723
- in /usr/src/lib/ccom/c04.c line 15, 80, 112, 197, 225-228(2), 309, 413, 419
- in /usr/src/lib/ccom/c10.c line 48-57(3), 76, 211, 329, 446-451(3), 786, 1206, 1348, 1361
- in /usr/src/lib/ccom/c12.c line 208, 639, 970, 1015, 1023, 1150

fblock defined in line 622; used 2 times

- in /usr/src/lib/ccom/c0.h line 478
- in /usr/src/lib/ccom/c00.c line 630

fold defined in line 722; used 3 times

- in line 90, 209, 364

gentemp defined in line 936; used 2 times

- in line 917
- in /usr/src/lib/ccom/c0.h line 488

lintyp defined in line 515; used 2 times

- in line 219(2)

nblock defined in line 595; used 7 times

- in line 918-924(3)
- in /usr/src/lib/ccom/c0.h line 489
- in /usr/src/lib/ccom/c00.c line 626
- in /usr/src/lib/ccom/c02.c line 195, 705

setype defined in line 437; used 3 times

- in line 161, 185, 488

starttree defined in line 661; used 8 times

- in /usr/src/lib/ccom/c0.h line 481
- in /usr/src/lib/ccom/c00.c line 598
- in /usr/src/lib/ccom/c02.c line 190, 484, 588, 703
- in /usr/src/lib/ccom/c04.c line 320, 337

structident defined in line 374; used 2 times

- in line 179
- in /usr/src/lib/ccom/c0.h line 487

werror defined in line 545; used 8 times

- in line 242, 258, 296, 406
- in /usr/src/lib/ccom/c02.c line 268
- in /usr/src/lib/ccom/c04.c line 233
- in /usr/src/lib/ccom/c10.c line 83
- in /usr/src/lib/ccom/c12.c line 925

Last modified: 1993-07-04 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2093 |