1: #
   2: /*
   3:  * C compiler
   4:  *
   5:  *
   6:  */
   7: 
   8: #include "c0.h"
   9: 
  10: /*
  11:  * Called from tree, this routine takes the top 1, 2, or 3
  12:  * operands on the expression stack, makes a new node with
  13:  * the operator op, and puts it on the stack.
  14:  * Essentially all the work is in inserting
  15:  * appropriate conversions.
  16:  */
  17: build(op)
  18: {
  19:     register int t1;
  20:     int t2, t;
  21:     register struct tnode *p1, *p2;
  22:     struct tnode *p3;
  23:     int dope, leftc, cvn, pcvn;
  24: 
  25:     /*
  26: 	 * a[i] => *(a+i)
  27: 	 */
  28:     if (op==LBRACK) {
  29:         build(PLUS);
  30:         op = STAR;
  31:     }
  32:     dope = opdope[op];
  33:     if ((dope&BINARY)!=0) {
  34:         p2 = chkfun(disarray(*--cp));
  35:         t2 = p2->type;
  36:     }
  37:     p1 = *--cp;
  38:     /*
  39: 	 * sizeof gets turned into a number here.
  40: 	 */
  41:     if (op==SIZEOF) {
  42:         t1 = cblock(length(p1));
  43:         t1->type = UNSIGN;
  44:         *cp++ = t1;
  45:         return;
  46:     }
  47:     if (op!=AMPER) {
  48:         p1 = disarray(p1);
  49:         if (op!=CALL)
  50:             p1 = chkfun(p1);
  51:     }
  52:     t1 = p1->type;
  53:     pcvn = 0;
  54:     t = INT;
  55:     switch (op) {
  56: 
  57:     case CAST:
  58:         if ((t1&XTYPE)==FUNC || (t1&XTYPE)==ARRAY)
  59:             error("Disallowed conversion");
  60:         if (t1==UNSIGN && t2==CHAR) {
  61:             t2 = INT;
  62:             p2 = block(AND,INT,NULL,NULL,p2,cblock(0377));
  63:         }
  64:         break;
  65: 
  66:     /* end of expression */
  67:     case 0:
  68:         *cp++ = p1;
  69:         return;
  70: 
  71:     /* no-conversion operators */
  72:     case QUEST:
  73:         if (p2->op!=COLON)
  74:             error("Illegal conditional");
  75:         else
  76:             if (fold(QUEST, p1, p2))
  77:                 return;
  78: 
  79:     case SEQNC:
  80:         t = t2;
  81: 
  82:     case COMMA:
  83:     case LOGAND:
  84:     case LOGOR:
  85:         *cp++ = block(op, t, NULL, NULL, p1, p2);
  86:         return;
  87: 
  88:     case EXCLA:
  89:         t1 = INT;
  90:         break;
  91: 
  92:     case CALL:
  93:         if ((t1&XTYPE) != FUNC)
  94:             error("Call of non-function");
  95:         *cp++ = block(CALL,decref(t1),p1->subsp,p1->strp,p1,p2);
  96:         return;
  97: 
  98:     case STAR:
  99:         if ((t1&XTYPE) == FUNC)
 100:             error("Illegal indirection");
 101:         *cp++ = block(STAR, decref(t1), p1->subsp, p1->strp, p1);
 102:         return;
 103: 
 104:     case AMPER:
 105:         if (p1->op==NAME || p1->op==STAR) {
 106:             *cp++ = block(op,incref(t1),p1->subsp,p1->strp,p1);
 107:             return;
 108:         }
 109:         error("Illegal lvalue");
 110:         break;
 111: 
 112:     /*
 113: 	 * a.b goes to (&a)->b
 114: 	 */
 115:     case DOT:
 116:         if (p1->op==CALL && t1==STRUCT) {
 117:             t1 = incref(t1);
 118:             setype(p1, t1, p1);
 119:         } else {
 120:             *cp++ = p1;
 121:             build(AMPER);
 122:             p1 = *--cp;
 123:         }
 124: 
 125:     /*
 126: 	 * In a->b, a is given the type ptr-to-structure element;
 127: 	 * then the offset is added in without conversion;
 128: 	 * then * is tacked on to access the member.
 129: 	 */
 130:     case ARROW:
 131:         if (p2->op!=NAME || p2->tr1->hclass!=MOS) {
 132:             error("Illegal structure ref");
 133:             *cp++ = p1;
 134:             return;
 135:         }
 136:         if (t2==INT && p2->tr1->hflag&FFIELD)
 137:             t2 = UNSIGN;
 138:         t = incref(t2);
 139:         chkw(p1, -1);
 140:         setype(p1, t, p2);
 141:         *cp++ = block(PLUS,t,p2->subsp,p2->strp,p1,cblock(p2->tr1->hoffset));
 142:         build(STAR);
 143:         if (p2->tr1->hflag&FFIELD)
 144:             *cp++ = block(FSEL,UNSIGN,NULL,NULL,*--cp,p2->tr1->hstrp);
 145:         return;
 146:     }
 147:     if ((dope&LVALUE)!=0)
 148:         chklval(p1);
 149:     if ((dope&LWORD)!=0)
 150:         chkw(p1, LONG);
 151:     if ((dope&RWORD)!=0)
 152:         chkw(p2, LONG);
 153:     if ((dope&BINARY)==0) {
 154:         if (op==ITOF)
 155:             t1 = DOUBLE;
 156:         else if (op==FTOI)
 157:             t1 = INT;
 158:         if (!fold(op, p1, 0))
 159:             *cp++ = block(op,t1,p1->subsp,p1->strp,p1);
 160:         return;
 161:     }
 162:     cvn = 0;
 163:     if (t1==STRUCT || t2==STRUCT) {
 164:         if (t1!=t2 || p1->strp != p2->strp)
 165:             error("Incompatible structures");
 166:         cvn = 0;
 167:     } else
 168:         cvn = cvtab[lintyp(t1)][lintyp(t2)];
 169:     leftc = (cvn>>4)&017;
 170:     cvn =& 017;
 171:     t = leftc? t2:t1;
 172:     if ((t==INT||t==CHAR) && (t1==UNSIGN||t2==UNSIGN))
 173:         t = UNSIGN;
 174:     if (dope&ASSGOP || op==CAST) {
 175:         t = t1;
 176:         if (op==ASSIGN || op==CAST) {
 177:             if (cvn==ITP||cvn==PTI)
 178:                 cvn = leftc = 0;
 179:             else if (cvn==LTP) {
 180:                 if (leftc==0)
 181:                     cvn = LTI;
 182:                 else {
 183:                     cvn = ITL;
 184:                     leftc = 0;
 185:                 }
 186:             }
 187:         }
 188:         if (leftc)
 189:             cvn = leftc;
 190:         leftc = 0;
 191:     } else if (op==COLON || op==MAX || op==MIN) {
 192:         if (t1>=PTR && t1==t2)
 193:             cvn = 0;
 194:         if (op!=COLON && (t1>=PTR || t2>=PTR))
 195:             op =+ MAXP-MAX;
 196:     } else if (dope&RELAT) {
 197:         if (op>=LESSEQ && (t1>=PTR||t2>=PTR||(t1==UNSIGN||t2==UNSIGN)
 198:          && (t==INT||t==CHAR||t==UNSIGN)))
 199:             op =+ LESSEQP-LESSEQ;
 200:         if (cvn==ITP || cvn==PTI)
 201:             cvn = 0;
 202:     }
 203:     if (cvn==PTI) {
 204:         cvn = 0;
 205:         if (op==MINUS) {
 206:             t = INT;
 207:             pcvn++;
 208:         } else {
 209:             if (t1!=t2 || t1!=(PTR+CHAR))
 210:                 cvn = XX;
 211:         }
 212:     }
 213:     if (cvn) {
 214:         t1 = plength(p1);
 215:         t2 = plength(p2);
 216:         if (cvn==XX || (cvn==PTI&&t1!=t2))
 217:             error("Illegal conversion");
 218:         else if (leftc)
 219:             p1 = convert(p1, t, cvn, t2);
 220:         else
 221:             p2 = convert(p2, t, cvn, t1);
 222:     }
 223:     if (dope&RELAT)
 224:         t = INT;
 225:     if (t==FLOAT)
 226:         t = DOUBLE;
 227:     if (t==CHAR)
 228:         t = INT;
 229:     if (op==CAST) {
 230:         if (t!=DOUBLE && (t!=INT || p2->type!=CHAR)) {
 231:             p2->type = t;
 232:             p2->subsp = p1->subsp;
 233:             p2->strp = p1->strp;
 234:         }
 235:         if (t==INT && p1->type==CHAR)
 236:             p2 = block(ITOC, INT, NULL, NULL, p2);
 237:         *cp++ = p2;
 238:         return;
 239:     }
 240:     if (fold(op, p1, p2)==0) {
 241:         p3 = leftc?p2:p1;
 242:         *cp++ = block(op, t, p3->subsp, p3->strp, p1, p2);
 243:     }
 244:     if (pcvn && t1!=(PTR+CHAR)) {
 245:         p1 = *--cp;
 246:         *cp++ = convert(p1, 0, PTI, plength(p1->tr1));
 247:     }
 248: }
 249: 
 250: /*
 251:  * Generate the appropriate conversion operator.
 252:  */
 253: struct tnode *
 254: convert(p, t, cvn, len)
 255: struct tnode *p;
 256: {
 257:     register int op;
 258: 
 259:     op = cvntab[cvn];
 260:     if (opdope[op]&BINARY) {
 261:         if (len==0)
 262:             error("Illegal conversion");
 263:         return(block(op, t, NULL, NULL, p, cblock(len)));
 264:     }
 265:     return(block(op, t, NULL, NULL, p));
 266: }
 267: 
 268: /*
 269:  * Traverse an expression tree, adjust things
 270:  * so the types of things in it are consistent
 271:  * with the view that its top node has
 272:  * type at.
 273:  * Used with structure references.
 274:  */
 275: setype(ap, at, anewp)
 276: struct tnode *ap, *anewp;
 277: {
 278:     register struct tnode *p, *newp;
 279:     register t;
 280: 
 281:     p = ap;
 282:     t = at;
 283:     newp = anewp;
 284:     for (;; p = p->tr1) {
 285:         p->subsp = newp->subsp;
 286:         p->strp = newp->strp;
 287:         p->type = t;
 288:         if (p->op==AMPER)
 289:             t = decref(t);
 290:         else if (p->op==STAR)
 291:             t = incref(t);
 292:         else if (p->op!=PLUS)
 293:             break;
 294:     }
 295: }
 296: 
 297: /*
 298:  * A mention of a function name is turned into
 299:  * a pointer to that function.
 300:  */
 301: struct tnode *
 302: chkfun(ap)
 303: struct tnode *ap;
 304: {
 305:     register struct tnode *p;
 306:     register int t;
 307: 
 308:     p = ap;
 309:     if (((t = p->type)&XTYPE)==FUNC && p->op!=ETYPE)
 310:         return(block(AMPER,incref(t),p->subsp,p->strp,p));
 311:     return(p);
 312: }
 313: 
 314: /*
 315:  * A mention of an array is turned into
 316:  * a pointer to the base of the array.
 317:  */
 318: struct tnode *
 319: disarray(ap)
 320: struct tnode *ap;
 321: {
 322:     register int t;
 323:     register struct tnode *p;
 324: 
 325:     p = ap;
 326:     /* check array & not MOS and not typer */
 327:     if (((t = p->type)&XTYPE)!=ARRAY || p->op==NAME&&p->tr1->hclass==MOS
 328:      || p->op==ETYPE)
 329:         return(p);
 330:     p->subsp++;
 331:     *cp++ = p;
 332:     setype(p, decref(t), p);
 333:     build(AMPER);
 334:     return(*--cp);
 335: }
 336: 
 337: /*
 338:  * make sure that p is a ptr to a node
 339:  * with type int or char or 'okt.'
 340:  * okt might be nonexistent or 'long'
 341:  * (e.g. for <<).
 342:  */
 343: chkw(p, okt)
 344: struct tnode *p;
 345: {
 346:     register int t;
 347: 
 348:     if ((t=p->type)!=INT && t<PTR && t!=CHAR && t!=UNSIGN && t!=okt)
 349:         error("Illegal type of operand");
 350:     return;
 351: }
 352: 
 353: /*
 354:  *'linearize' a type for looking up in the
 355:  * conversion table
 356:  */
 357: lintyp(t)
 358: {
 359:     switch(t) {
 360: 
 361:     case INT:
 362:     case CHAR:
 363:     case UNSIGN:
 364:         return(0);
 365: 
 366:     case FLOAT:
 367:     case DOUBLE:
 368:         return(1);
 369: 
 370:     case LONG:
 371:         return(2);
 372: 
 373:     default:
 374:         return(3);
 375:     }
 376: }
 377: 
 378: /*
 379:  * Report an error.
 380:  */
 381: error(s, p1, p2, p3, p4, p5, p6)
 382: {
 383:     nerror++;
 384:     if (filename[0])
 385:         fprintf(stderr, "%s:", filename);
 386:     fprintf(stderr, "%d: ", line);
 387:     fprintf(stderr, s, p1, p2, p3, p4, p5, p6);
 388:     fprintf(stderr, "\n");
 389: }
 390: 
 391: /*
 392:  * Generate a node in an expression tree,
 393:  * setting the operator, type, dimen/struct table ptrs,
 394:  * and the operands.
 395:  */
 396: struct tnode *
 397: block(op, t, subs, str, p1,p2)
 398: int *subs;
 399: struct str *str;
 400: struct tnode *p1, *p2;
 401: {
 402:     register struct tnode *p;
 403: 
 404:     p = gblock(sizeof(*p));
 405:     p->op = op;
 406:     p->type = t;
 407:     p->subsp = subs;
 408:     p->strp = str;
 409:     p->tr1 = p1;
 410:     if (opdope[op]&BINARY)
 411:         p->tr2 = p2;
 412:     else
 413:         p->tr2 = NULL;
 414:     return(p);
 415: }
 416: 
 417: struct tnode *
 418: nblock(ads)
 419: struct hshtab *ads;
 420: {
 421:     register struct hshtab *ds;
 422: 
 423:     ds = ads;
 424:     return(block(NAME, ds->htype, ds->hsubsp, ds->hstrp, ds));
 425: }
 426: 
 427: /*
 428:  * Generate a block for a constant
 429:  */
 430: struct cnode *
 431: cblock(v)
 432: {
 433:     register struct cnode *p;
 434: 
 435:     p = gblock(sizeof(*p));
 436:     p->op = CON;
 437:     p->type = INT;
 438:     p->subsp = NULL;
 439:     p->strp = NULL;
 440:     p->value = v;
 441:     return(p);
 442: }
 443: 
 444: /*
 445:  * A block for a float or long constant
 446:  */
 447: struct fnode *
 448: fblock(t, string)
 449: char *string;
 450: {
 451:     register struct fnode *p;
 452: 
 453:     p = gblock(sizeof(*p));
 454:     p->op = FCON;
 455:     p->type = t;
 456:     p->subsp = NULL;
 457:     p->strp = NULL;
 458:     p->cstr = string;
 459:     return(p);
 460: }
 461: 
 462: /*
 463:  * Assign a block for use in the
 464:  * expression tree.
 465:  */
 466: char *
 467: gblock(n)
 468: {
 469:     register int *p;
 470: 
 471:     p = curbase;
 472:     if ((curbase =+ n) >= coremax) {
 473:         if (sbrk(1024) == -1) {
 474:             error("Out of space");
 475:             exit(1);
 476:         }
 477:         coremax =+ 1024;
 478:     }
 479:     return(p);
 480: }
 481: 
 482: /*
 483:  * Check that a tree can be used as an lvalue.
 484:  */
 485: chklval(ap)
 486: struct tnode *ap;
 487: {
 488:     register struct tnode *p;
 489: 
 490:     p = ap;
 491:     if (p->op==FSEL)
 492:         p = p->tr1;
 493:     if (p->op!=NAME && p->op!=STAR)
 494:         error("Lvalue required");
 495: }
 496: 
 497: /*
 498:  * reduce some forms of `constant op constant'
 499:  * to a constant.  More of this is done in the next pass
 500:  * but this is used to allow constant expressions
 501:  * to be used in switches and array bounds.
 502:  */
 503: fold(op, ap1, ap2)
 504: struct tnode *ap1, *ap2;
 505: {
 506:     register struct tnode *p1;
 507:     register int v1, v2;
 508:     int unsignf;
 509: 
 510:     p1 = ap1;
 511:     if (p1->op!=CON)
 512:         return(0);
 513:     unsignf = p1->type==UNSIGN;
 514:     if (op==QUEST) {
 515:         if (ap2->tr1->op==CON && ap2->tr2->op==CON) {
 516:             p1->value = p1->value? ap2->tr1->value: ap2->tr2->value;
 517:             *cp++ = p1;
 518:             return(1);
 519:         }
 520:         return(0);
 521:     }
 522:     if (ap2) {
 523:         if (ap2->op!=CON)
 524:             return(0);
 525:         v2 = ap2->value;
 526:         unsignf |= ap2->type==UNSIGN;
 527:     }
 528:     v1 = p1->value;
 529:     switch (op) {
 530: 
 531:     case PLUS:
 532:         v1 =+ v2;
 533:         break;
 534: 
 535:     case MINUS:
 536:         v1 =- v2;
 537:         break;
 538: 
 539:     case TIMES:
 540:         v1 =* v2;
 541:         break;
 542: 
 543:     case DIVIDE:
 544:         if (v2==0)
 545:             goto divchk;
 546:         if (unsignf) {
 547:             v1 = (unsigned)v1 / v2;
 548:             break;
 549:         }
 550:         v1 =/ v2;
 551:         break;
 552: 
 553:     case MOD:
 554:         if (v2==0)
 555:             goto divchk;
 556:         if (unsignf) {
 557:             v1 = (unsigned)v1 % v2;
 558:             break;
 559:         }
 560:         v1 =% v2;
 561:         break;
 562: 
 563:     case AND:
 564:         v1 =& v2;
 565:         break;
 566: 
 567:     case OR:
 568:         v1 =| v2;
 569:         break;
 570: 
 571:     case EXOR:
 572:         v1 =^ v2;
 573:         break;
 574: 
 575:     case NEG:
 576:         v1 = - v1;
 577:         break;
 578: 
 579:     case COMPL:
 580:         v1 = ~ v1;
 581:         break;
 582: 
 583:     case LSHIFT:
 584:         v1 =<< v2;
 585:         break;
 586: 
 587:     case RSHIFT:
 588:         if (unsignf) {
 589:             v1 = (unsigned)v1 >> v2;
 590:             break;
 591:         }
 592:         v1 =>> v2;
 593:         break;
 594: 
 595:     case EQUAL:
 596:         v1 = v1==v2;
 597:         break;
 598: 
 599:     case NEQUAL:
 600:         v1 = v1!=v2;
 601:         break;
 602: 
 603:     case LESS:
 604:         v1 = v1<v2;
 605:         break;
 606: 
 607:     case GREAT:
 608:         v1 = v1>v2;
 609:         break;
 610: 
 611:     case LESSEQ:
 612:         v1 = v1<=v2;
 613:         break;
 614: 
 615:     case GREATEQ:
 616:         v1 = v1>=v2;
 617:         break;
 618: 
 619:     divchk:
 620:         error("Divide check");
 621:     default:
 622:         return(0);
 623:     }
 624:     p1->value = v1;
 625:     *cp++ = p1;
 626:     return(1);
 627: }
 628: 
 629: /*
 630:  * Compile an expression expected to have constant value,
 631:  * for example an array bound or a case value.
 632:  */
 633: conexp()
 634: {
 635:     register struct tnode *t;
 636: 
 637:     initflg++;
 638:     if (t = tree())
 639:         if (t->op != CON)
 640:             error("Constant required");
 641:     initflg--;
 642:     curbase = funcbase;
 643:     return(t->value);
 644: }

Defined functions

block defined in line 396; used 20 times
build defined in line 17; used 13 times
cblock defined in line 430; used 8 times
chkfun defined in line 301; used 3 times
chklval defined in line 485; used 1 times
chkw defined in line 343; used 5 times
conexp defined in line 633; used 4 times
convert defined in line 253; used 4 times
disarray defined in line 318; used 3 times
error defined in line 381; used 106 times
fblock defined in line 447; used 2 times
fold defined in line 503; used 3 times
gblock defined in line 466; used 15 times
lintyp defined in line 357; used 2 times
  • in line 168(2)
nblock defined in line 417; used 4 times
setype defined in line 275; used 6 times
Last modified: 1979-01-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1269
Valid CSS Valid XHTML 1.0 Strict