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
Tblock defined in line 641; used 8 times
assignop defined in line 903; used 1 times
block defined in line 574; used 25 times
build defined in line 14; used 28 times
cblock defined in line 605; used 9 times
chkfun defined in line 458; used 3 times
chklval defined in line 707; used 1 times
chkw defined in line 499; used 5 times
conexp defined in line 888; used 4 times
convert defined in line 413; used 4 times
disarray defined in line 473; used 3 times
endtree defined in line 672; used 10 times
error defined in line 558; used 115 times
fblock defined in line 622; used 2 times
fold defined in line 722; used 3 times
gentemp defined in line 936; used 2 times
lintyp defined in line 515; used 2 times
  • in line 219(2)
nblock defined in line 595; used 7 times
setype defined in line 437; used 3 times
structident defined in line 374; used 2 times
werror defined in line 545; used 8 times
Last modified: 1993-07-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4700
Valid CSS Valid XHTML 1.0 Strict