1: /*
   2:  * C compiler
   3:  */
   4: 
   5: #include "c0.h"
   6: 
   7: /*
   8:  * Reduce the degree-of-reference by one.
   9:  * e.g. turn "ptr-to-int" into "int".
  10:  */
  11: decref(t)
  12: register int t;
  13: {
  14:     if ((t & ~TYPE) == 0) {
  15:         error("Illegal indirection");
  16:         return(t);
  17:     }
  18:     return((t>>TYLEN) & ~TYPE | t&TYPE);
  19: }
  20: 
  21: /*
  22:  * Increase the degree of reference by
  23:  * one; e.g. turn "int" to "ptr-to-int".
  24:  */
  25: incref(t)
  26: register int t;
  27: {
  28:     return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR);
  29: }
  30: 
  31: /*
  32:  * Make a tree that causes a branch to lbl
  33:  * if the tree's value is non-zero together with the cond.
  34:  */
  35: cbranch(t, lbl, cond)
  36: union tree *t;
  37: {
  38:     treeout(t, 0);
  39:     outcode("BNNN", CBRANCH, lbl, cond, line);
  40: }
  41: 
  42: /*
  43:  * Write out a tree.
  44:  */
  45: rcexpr(tp)
  46: register union tree *tp;
  47: {
  48:     /*
  49: 	 * Special optimization
  50: 	 */
  51:     if (tp->t.op==INIT && tp->t.tr1->t.op==CON) {
  52:         if (tp->t.type==CHAR || tp->t.type==UNCHAR) {
  53:             outcode("B1N0", BDATA, tp->t.tr1->c.value);
  54:             return;
  55:         } else if (tp->t.type==INT || tp->t.type==UNSIGN) {
  56:             outcode("BN", SINIT, tp->t.tr1->c.value);
  57:             return;
  58:         }
  59:     }
  60:     treeout(tp, 0);
  61:     outcode("BN", EXPR, line);
  62: }
  63: 
  64: treeout(tp, isstruct)
  65: register union tree *tp;
  66: {
  67:     register struct nmlist *hp;
  68:     register nextisstruct;
  69: 
  70:     if (tp == NULL || tp->t.op==NULLOP) {
  71:         outcode("B", XNULLOP);
  72:         return;
  73:     }
  74:     nextisstruct = tp->t.type==STRUCT;
  75:     switch(tp->t.op) {
  76: 
  77:     case NAME:
  78:         hp = &tp->t.tr1->n;
  79:         if (hp->hclass==TYPEDEF)
  80:             error("Illegal use of type name");
  81:         outcode("BNN", NAME, hp->hclass==0?STATIC:hp->hclass, tp->t.type);
  82:         if (hp->hclass==EXTERN)
  83:             outcode("S", hp->name);
  84:         else
  85:             outcode("N", hp->hoffset);
  86:         break;
  87: 
  88:     case LCON:
  89:         outcode("BNNN", tp->l.op, tp->l.type, (unsigned short)(tp->l.lvalue>>16),
  90:            (unsigned short)tp->l.lvalue);
  91:         break;
  92: 
  93:     case CON:
  94:         outcode("BNN", tp->c.op, tp->c.type, tp->c.value);
  95:         break;
  96: 
  97:     case FCON:
  98:         outcode("BNF", tp->f.op, tp->f.type, tp->f.cstr);
  99:         break;
 100: 
 101:     case STRING:
 102:         outcode("BNNN", NAME, STATIC, tp->t.type, tp->t.tr1);
 103:         break;
 104: 
 105:     case FSEL:
 106:         treeout(tp->t.tr1, nextisstruct);
 107:         outcode("BNNN", tp->t.op, tp->t.type,
 108:            tp->t.tr2->fld.bitoffs, tp->t.tr2->fld.flen);
 109:         break;
 110: 
 111:     case ETYPE:
 112:         error("Illegal use of type");
 113:         break;
 114: 
 115:     case AMPER:
 116:         treeout(tp->t.tr1, 1);
 117:         outcode("BN", tp->t.op, tp->t.type);
 118:         break;
 119: 
 120: 
 121:     case CALL:
 122:         treeout(tp->t.tr1, 1);
 123:         treeout(tp->t.tr2, 0);
 124:         outcode("BN", CALL, tp->t.type);
 125:         break;
 126: 
 127:     default:
 128:         treeout(tp->t.tr1, nextisstruct);
 129:         if (opdope[tp->t.op]&BINARY)
 130:             treeout(tp->t.tr2, nextisstruct);
 131:         outcode("BN", tp->t.op, tp->t.type);
 132:         break;
 133:     }
 134:     if (nextisstruct && isstruct==0)
 135:         outcode("BNN", STRASG, STRUCT, tp->t.strp->S.ssize);
 136: }
 137: 
 138: /*
 139:  * Generate a branch
 140:  */
 141: branch(lab)
 142: {
 143:     outcode("BN", BRANCH, lab);
 144: }
 145: 
 146: /*
 147:  * Generate a label
 148:  */
 149: label(l)
 150: {
 151:     outcode("BN", LABEL, l);
 152: }
 153: 
 154: /*
 155:  * ap is a tree node whose type
 156:  * is some kind of pointer; return the size of the object
 157:  * to which the pointer points.
 158:  */
 159: plength(p)
 160: register union tree *p;
 161: {
 162:     register t, l;
 163: 
 164:     if (p==0 || ((t=p->t.type)&~TYPE) == 0)     /* not a reference */
 165:         return(1);
 166:     p->t.type = decref(t);
 167:     l = length(p);
 168:     p->t.type = t;
 169:     return(l);
 170: }
 171: 
 172: /*
 173:  * return the number of bytes in the object
 174:  * whose tree node is acs.
 175:  */
 176: length(cs)
 177: union tree *cs;
 178: {
 179:     register t, elsz;
 180:     long n;
 181:     int nd;
 182: 
 183:     t = cs->t.type;
 184:     n = 1;
 185:     nd = 0;
 186:     while ((t&XTYPE) == ARRAY) {
 187:         t = decref(t);
 188:         n *= cs->t.subsp[nd++];
 189:     }
 190:     if ((t&~TYPE)==FUNC)
 191:         return(0);
 192:     if (t>=PTR)
 193:         elsz = SZPTR;
 194:     else switch(t&TYPE) {
 195: 
 196:     case VOID:
 197:         error("Illegal use of void object");
 198:         return(2);
 199: 
 200:     case INT:
 201:     case UNSIGN:
 202:         elsz = SZINT;
 203:         break;
 204: 
 205:     case CHAR:
 206:     case UNCHAR:
 207:         elsz = 1;
 208:         break;
 209: 
 210:     case FLOAT:
 211:         elsz = SZFLOAT;
 212:         break;
 213: 
 214:     case UNLONG:
 215:     case LONG:
 216:         elsz = SZLONG;
 217:         break;
 218: 
 219:     case DOUBLE:
 220:         elsz = SZDOUB;
 221:         break;
 222: 
 223:     case STRUCT:
 224:         if ((elsz = cs->t.strp->S.ssize) == 0)
 225:             error("Undefined structure");
 226:         break;
 227:     default:
 228:         error("Compiler error (length)");
 229:         return(0);
 230:     }
 231:     n *= elsz;
 232:     if (n >= (unsigned)50000)
 233:         werror("very large data structure");
 234:     return(n);
 235: }
 236: 
 237: /*
 238:  * The number of bytes in an object, rounded up to a word.
 239:  */
 240: rlength(cs)
 241: union tree *cs;
 242: {
 243:     return((length(cs)+ALIGN) & ~ALIGN);
 244: }
 245: 
 246: /*
 247:  * After an "if (...) goto", look to see if the transfer
 248:  * is to a simple label.
 249:  */
 250: simplegoto()
 251: {
 252:     register struct nmlist *csp;
 253: 
 254:     if ((peeksym=symbol())==NAME && nextchar()==';') {
 255:         csp = csym;
 256:         if (csp->hblklev == 0)
 257:             csp = pushdecl(csp);
 258:         if (csp->hclass==0 && csp->htype==0) {
 259:             csp->htype = ARRAY;
 260:             csp->hflag |= FLABL;
 261:             if (csp->hoffset==0)
 262:                 csp->hoffset = isn++;
 263:         }
 264:         if ((csp->hclass==0||csp->hclass==STATIC)
 265:          &&  csp->htype==ARRAY) {
 266:             peeksym = -1;
 267:             return(csp->hoffset);
 268:         }
 269:     }
 270:     return(0);
 271: }
 272: 
 273: /*
 274:  * Return the next non-white-space character
 275:  */
 276: nextchar()
 277: {
 278:     while (spnextchar()==' ')
 279:         peekc = 0;
 280:     return(peekc);
 281: }
 282: 
 283: /*
 284:  * Return the next character, translating all white space
 285:  * to blank and handling line-ends.
 286:  */
 287: spnextchar()
 288: {
 289:     register c;
 290: 
 291:     if ((c = peekc)==0)
 292:         c = getchar();
 293:     if (c=='\t' || c=='\014')   /* FF */
 294:         c = ' ';
 295:     else if (c=='\n') {
 296:         c = ' ';
 297:         line++;
 298:     }
 299:     peekc = c;
 300:     return(c);
 301: }
 302: 
 303: /*
 304:  * is a break or continue legal?
 305:  */
 306: chconbrk(l)
 307: {
 308:     if (l==0)
 309:         error("Break/continue error");
 310: }
 311: 
 312: /*
 313:  * The goto statement.
 314:  */
 315: dogoto()
 316: {
 317:     register union tree *np;
 318:     register char *st;
 319: 
 320:     st = starttree();
 321:     *cp++ = tree(0);
 322:     build(STAR);
 323:     chkw(np = *--cp, -1);
 324:     rcexpr(block(JUMP, 0, (int *)NULL, (union str *)NULL, np, TNULL));
 325:     endtree(st);
 326: }
 327: 
 328: /*
 329:  * The return statement, which has to convert
 330:  * the returned object to the function's type.
 331:  */
 332: doret()
 333: {
 334:     if (nextchar() != ';') {
 335:         register char *st;
 336: 
 337:         st = starttree();
 338:         *cp++ = (union tree *)&funcblk;
 339:         *cp++ = tree(0);
 340:         build(ASSIGN);
 341:         cp[-1] = cp[-1]->t.tr2;
 342:         build(RFORCE);
 343:         rcexpr(*--cp);
 344:         endtree(st);
 345:     }
 346:     branch(retlab);
 347: }
 348: 
 349: /*
 350:  * Write a character on the error output.
 351:  */
 352: /*
 353:  * Coded output:
 354:  *   B: beginning of line; an operator
 355:  *   N: a number
 356:  *   S: a symbol (external)
 357:  *   1: number 1
 358:  *   0: number 0
 359:  */
 360: /* VARARGS1 */
 361: outcode(s, a)
 362: char *s;
 363: {
 364:     register *ap;
 365:     register FILE *bufp;
 366:     register char *np;
 367:     int n;
 368: 
 369:     bufp = stdout;
 370:     if (strflg)
 371:         bufp = sbufp;
 372:     ap = &a;
 373:     for (;;) switch(*s++) {
 374:     case 'B':
 375:         fputc(*ap++, bufp);
 376:         fputc(0376, bufp);
 377:         continue;
 378: 
 379:     case 'N':
 380:         fputc(*ap, bufp);
 381:         fputc(*ap++>>8, bufp);
 382:         continue;
 383: 
 384:     case 'F':
 385:         np = (char *)*ap++;
 386:         n = 1000;
 387:         goto str;
 388: 
 389:     case 'S':
 390:         np = (char *)*ap++;
 391:         n = MAXCPS-1;
 392:         if (*np)
 393:             fputc('_', bufp);
 394:     str:
 395:         while(n-- && *np) {
 396:             fputc(*np++ & 0177, bufp);
 397:         }
 398:         fputc(0, bufp);
 399:         continue;
 400: 
 401:     case '1':
 402:         fputc(1, bufp);
 403:         fputc(0, bufp);
 404:         continue;
 405: 
 406:     case '0':
 407:         fputc(0, bufp);
 408:         fputc(0, bufp);
 409:         continue;
 410: 
 411:     case '\0':
 412:         if (ferror(bufp)) {
 413:             error("Write error on temp");
 414:             exit(1);
 415:         }
 416:         return;
 417: 
 418:     default:
 419:         error("Botch in outcode");
 420:     }
 421: }
 422: 
 423: unsigned int
 424: hash(sp)
 425: register char *sp;
 426: {
 427:     register unsigned int h;
 428: 
 429:     h = 0;
 430:     for (; *sp; sp++) {
 431:         h += h;
 432:         h += *sp;
 433:     }
 434:     return(h%HSHSIZ);
 435: }

Defined functions

branch defined in line 141; used 17 times
cbranch defined in line 35; used 9 times
chconbrk defined in line 306; used 3 times
decref defined in line 11; used 11 times
dogoto defined in line 315; used 2 times
doret defined in line 332; used 2 times
hash defined in line 423; used 4 times
incref defined in line 25; used 7 times
label defined in line 149; used 26 times
length defined in line 176; used 8 times
nextchar defined in line 276; used 6 times
outcode defined in line 361; used 55 times
plength defined in line 159; used 3 times
rcexpr defined in line 45; used 19 times
rlength defined in line 240; used 4 times
simplegoto defined in line 250; used 2 times
spnextchar defined in line 287; used 5 times
treeout defined in line 64; used 8 times
Last modified: 1993-07-04
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2961
Valid CSS Valid XHTML 1.0 Strict