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

Defined functions

block defined in line 397; used 20 times
build defined in line 18; used 13 times
cblock defined in line 431; used 8 times
chkfun defined in line 302; used 3 times
chklval defined in line 486; used 1 times
chkw defined in line 344; used 5 times
conexp defined in line 634; used 4 times
convert defined in line 254; used 4 times
disarray defined in line 319; used 3 times
error defined in line 382; used 106 times
fblock defined in line 448; used 2 times
fold defined in line 504; used 3 times
gblock defined in line 467; used 15 times
lintyp defined in line 358; used 2 times
  • in line 169(2)
nblock defined in line 418; used 4 times
setype defined in line 276; used 6 times
Last modified: 1981-07-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1544
Valid CSS Valid XHTML 1.0 Strict