1: # 2: /* 3: * C compiler 4: * 5: * 6: */ 7: 8: #include "c0h.c" 9: 10: /* 11: * Reduce the degree-of-reference by one. 12: * e.g. turn "ptr-to-int" into "int". 13: */ 14: decref(at) 15: { 16: register t; 17: 18: t = at; 19: if ((t & ~TYPE) == 0) { 20: error("Illegal indirection"); 21: return(t); 22: } 23: return((t>>TYLEN) & ~TYPE | t&TYPE); 24: } 25: 26: /* 27: * Increase the degree of reference by 28: * one; e.g. turn "int" to "ptr-to-int". 29: */ 30: incref(t) 31: { 32: return(((t&~TYPE)<<TYLEN) | (t&TYPE) | PTR); 33: } 34: 35: /* 36: * Make a tree that causes a branch to lbl 37: * if the tree's value is non-zero together with the cond. 38: */ 39: cbranch(tree, lbl, cond) 40: struct tnode *tree; 41: { 42: rcexpr(block(1,CBRANCH,tree,lbl,cond)); 43: } 44: 45: /* 46: * Write out a tree. 47: */ 48: rcexpr(tree) 49: struct tnode *tree; 50: { 51: 52: treeout(tree); 53: outcode("BN", EXPR, line); 54: } 55: 56: treeout(atree) 57: struct tnode *atree; 58: { 59: register struct tnode *tree; 60: 61: if ((tree = atree) == 0) 62: return; 63: switch(tree->op) { 64: 65: case 0: 66: outcode("B", NULL); 67: return; 68: 69: case NAME: 70: outcode("BNN", NAME, tree->class, tree->type); 71: if (tree->class==EXTERN) 72: outcode("S", tree->nname); 73: else 74: outcode("N", tree->nloc); 75: return; 76: 77: case CON: 78: case FCON: 79: case SFCON: 80: outcode("BNN", tree->op, tree->type, tree->value); 81: return; 82: 83: case FSEL: 84: treeout(tree->tr1); 85: outcode("BNN", tree->op, tree->type, tree->tr2); 86: return; 87: 88: case CBRANCH: 89: treeout(tree->btree); 90: outcode("BNN", tree->op, tree->lbl, tree->cond); 91: return; 92: 93: default: 94: treeout(tree->tr1); 95: if (opdope[tree->op]&BINARY) 96: treeout(tree->tr2); 97: outcode("BN", tree->op, tree->type); 98: return; 99: } 100: } 101: 102: /* 103: * Generate a branch 104: */ 105: branch(lab) { 106: outcode("BN", BRANCH, lab); 107: } 108: 109: /* 110: * Generate a label 111: */ 112: label(l) { 113: outcode("BN", LABEL, l); 114: } 115: 116: /* 117: * ap is a tree node whose type 118: * is some kind of pointer; return the size of the object 119: * to which the pointer points. 120: */ 121: plength(ap) 122: struct tname *ap; 123: { 124: register t, l; 125: register struct tname *p; 126: 127: p = ap; 128: if (p==0 || ((t=p->type)&~TYPE) == 0) /* not a reference */ 129: return(1); 130: p->type = decref(t); 131: l = length(p); 132: p->type = t; 133: return(l); 134: } 135: 136: /* 137: * return the number of bytes in the object 138: * whose tree node is acs. 139: */ 140: length(acs) 141: struct tnode *acs; 142: { 143: register t, n; 144: register struct tnode *cs; 145: 146: cs = acs; 147: t = cs->type; 148: n = 1; 149: while ((t&XTYPE) == ARRAY) { 150: t = decref(t); 151: n = dimtab[cs->ssp&0377]; 152: } 153: if ((t&~TYPE)==FUNC) 154: return(0); 155: if (t>=PTR) 156: return(2*n); 157: switch(t&TYPE) { 158: 159: case INT: 160: return(2*n); 161: 162: case CHAR: 163: return(n); 164: 165: case FLOAT: 166: case LONG: 167: return(4*n); 168: 169: case DOUBLE: 170: return(8*n); 171: 172: case STRUCT: 173: return(n * dimtab[cs->lenp&0377]); 174: 175: case RSTRUCT: 176: error("Bad structure"); 177: return(0); 178: } 179: error("Compiler error (length)"); 180: } 181: 182: /* 183: * The number of bytes in an object, rounded up to a word. 184: */ 185: rlength(cs) 186: struct tnode *cs; 187: { 188: return((length(cs)+ALIGN) & ~ALIGN); 189: } 190: 191: /* 192: * After an "if (...) goto", look to see if the transfer 193: * is to a simple label. 194: */ 195: simplegoto() 196: { 197: register struct hshtab *csp; 198: 199: if ((peeksym=symbol())==NAME && nextchar()==';') { 200: csp = csym; 201: if (csp->hclass==0 && csp->htype==0) { 202: csp->htype = ARRAY; 203: if (csp->hoffset==0) 204: csp->hoffset = isn++; 205: } 206: if ((csp->hclass==0||csp->hclass==STATIC) 207: && csp->htype==ARRAY) { 208: peeksym = -1; 209: return(csp->hoffset); 210: } 211: } 212: return(0); 213: } 214: 215: /* 216: * Return the next non-white-space character 217: */ 218: nextchar() 219: { 220: while (spnextchar()==' ') 221: peekc = 0; 222: return(peekc); 223: } 224: 225: /* 226: * Return the next character, translating all white space 227: * to blank and handling line-ends. 228: */ 229: spnextchar() 230: { 231: register c; 232: 233: if ((c = peekc)==0) 234: c = getchar(); 235: if (c=='\t') 236: c = ' '; 237: else if (c=='\n') { 238: c = ' '; 239: if (inhdr==0) 240: line++; 241: inhdr = 0; 242: } else if (c=='\001') { /* SOH, insert marker */ 243: inhdr++; 244: c = ' '; 245: } 246: peekc = c; 247: return(c); 248: } 249: 250: /* 251: * is a break or continue legal? 252: */ 253: chconbrk(l) 254: { 255: if (l==0) 256: error("Break/continue error"); 257: } 258: 259: /* 260: * The goto statement. 261: */ 262: dogoto() 263: { 264: register struct tnode *np; 265: 266: *cp++ = tree(); 267: build(STAR); 268: chkw(np = *--cp, -1); 269: rcexpr(block(1,JUMP,0,0,np)); 270: } 271: 272: /* 273: * The return statement, which has to convert 274: * the returned object to the function's type. 275: */ 276: doret() 277: { 278: register struct tnode *t; 279: 280: if (nextchar() != ';') { 281: t = tree(); 282: *cp++ = &funcblk; 283: *cp++ = t; 284: build(ASSIGN); 285: cp[-1] = cp[-1]->tr2; 286: build(RFORCE); 287: rcexpr(*--cp); 288: } 289: branch(retlab); 290: } 291: 292: /* 293: * write out a character to the usual output 294: * or to the string file 295: */ 296: putchar(c) 297: { 298: write(1, &c, 1); 299: } 300: 301: outcode(s, a) 302: char *s; 303: { 304: register char *sp; 305: register *ap, *bufp; 306: int n; 307: char *np; 308: 309: bufp = obuf; 310: if (strflg) 311: bufp = sbuf; 312: ap = &a; 313: for (;;) switch(*s++) { 314: case 'B': 315: putw(*ap++ | (0376<<8), bufp); 316: continue; 317: 318: case 'N': 319: putw(*ap++, bufp); 320: continue; 321: 322: case 'S': 323: np = *ap++; 324: n = ncps; 325: while (n-- && *np) { 326: putc(*np++, bufp); 327: } 328: putc(0, bufp); 329: continue; 330: 331: case '1': 332: putw(1, bufp); 333: continue; 334: 335: case '0': 336: putw(0, bufp); 337: continue; 338: 339: case '\0': 340: return; 341: } 342: error("Botch in outcode"); 343: }