|
|
1.1 ! root 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 LONG: ! 215: elsz = SZLONG; ! 216: break; ! 217: ! 218: case DOUBLE: ! 219: elsz = SZDOUB; ! 220: break; ! 221: ! 222: case STRUCT: ! 223: if ((elsz = cs->t.strp->S.ssize) == 0) ! 224: error("Undefined structure"); ! 225: break; ! 226: default: ! 227: error("Compiler error (length)"); ! 228: return(0); ! 229: } ! 230: n *= elsz; ! 231: if (n >= (unsigned)50000) { ! 232: error("Warning: very large data structure"); ! 233: nerror--; ! 234: } ! 235: return(n); ! 236: } ! 237: ! 238: /* ! 239: * The number of bytes in an object, rounded up to a word. ! 240: */ ! 241: rlength(cs) ! 242: union tree *cs; ! 243: { ! 244: return((length(cs)+ALIGN) & ~ALIGN); ! 245: } ! 246: ! 247: /* ! 248: * After an "if (...) goto", look to see if the transfer ! 249: * is to a simple label. ! 250: */ ! 251: simplegoto() ! 252: { ! 253: register struct nmlist *csp; ! 254: ! 255: if ((peeksym=symbol())==NAME && nextchar()==';') { ! 256: csp = csym; ! 257: if (csp->hblklev == 0) ! 258: csp = pushdecl(csp); ! 259: if (csp->hclass==0 && csp->htype==0) { ! 260: csp->htype = ARRAY; ! 261: csp->hflag |= FLABL; ! 262: if (csp->hoffset==0) ! 263: csp->hoffset = isn++; ! 264: } ! 265: if ((csp->hclass==0||csp->hclass==STATIC) ! 266: && csp->htype==ARRAY) { ! 267: peeksym = -1; ! 268: return(csp->hoffset); ! 269: } ! 270: } ! 271: return(0); ! 272: } ! 273: ! 274: /* ! 275: * Return the next non-white-space character ! 276: */ ! 277: nextchar() ! 278: { ! 279: while (spnextchar()==' ') ! 280: peekc = 0; ! 281: return(peekc); ! 282: } ! 283: ! 284: /* ! 285: * Return the next character, translating all white space ! 286: * to blank and handling line-ends. ! 287: */ ! 288: spnextchar() ! 289: { ! 290: register c; ! 291: ! 292: if ((c = peekc)==0) ! 293: c = getchar(); ! 294: if (c=='\t' || c=='\014') /* FF */ ! 295: c = ' '; ! 296: else if (c=='\n') { ! 297: c = ' '; ! 298: line++; ! 299: } ! 300: peekc = c; ! 301: return(c); ! 302: } ! 303: ! 304: /* ! 305: * is a break or continue legal? ! 306: */ ! 307: chconbrk(l) ! 308: { ! 309: if (l==0) ! 310: error("Break/continue error"); ! 311: } ! 312: ! 313: /* ! 314: * The goto statement. ! 315: */ ! 316: dogoto() ! 317: { ! 318: register union tree *np; ! 319: register char *st; ! 320: ! 321: st = starttree(); ! 322: *cp++ = tree(0); ! 323: build(STAR); ! 324: chkw(np = *--cp, -1); ! 325: rcexpr(block(JUMP, 0, (int *)NULL, (union str *)NULL, np, TNULL)); ! 326: endtree(st); ! 327: } ! 328: ! 329: /* ! 330: * The return statement, which has to convert ! 331: * the returned object to the function's type. ! 332: */ ! 333: doret() ! 334: { ! 335: register union tree *t; ! 336: ! 337: if (nextchar() != ';') { ! 338: register char *st; ! 339: ! 340: st = starttree(); ! 341: *cp++ = (union tree *)&funcblk; ! 342: *cp++ = tree(0); ! 343: build(ASSIGN); ! 344: cp[-1] = cp[-1]->t.tr2; ! 345: build(RFORCE); ! 346: rcexpr(*--cp); ! 347: endtree(st); ! 348: } ! 349: branch(retlab); ! 350: } ! 351: ! 352: /* ! 353: * Write a character on the error output. ! 354: */ ! 355: /* ! 356: * Coded output: ! 357: * B: beginning of line; an operator ! 358: * N: a number ! 359: * S: a symbol (external) ! 360: * 1: number 1 ! 361: * 0: number 0 ! 362: */ ! 363: /* VARARGS1 */ ! 364: outcode(s, a) ! 365: char *s; ! 366: { ! 367: register *ap; ! 368: register FILE *bufp; ! 369: int n; ! 370: register char *np; ! 371: ! 372: bufp = stdout; ! 373: if (strflg) ! 374: bufp = sbufp; ! 375: ap = &a; ! 376: for (;;) switch(*s++) { ! 377: case 'B': ! 378: putc(*ap++, bufp); ! 379: putc(0376, bufp); ! 380: continue; ! 381: ! 382: case 'N': ! 383: putc(*ap, bufp); ! 384: putc(*ap++>>8, bufp); ! 385: continue; ! 386: ! 387: case 'F': ! 388: n = 1000; ! 389: np = (char *)*ap++; ! 390: goto str; ! 391: ! 392: case 'S': ! 393: n = NCPS; ! 394: np = (char *)*ap++; ! 395: if (*np) ! 396: putc('_', bufp); ! 397: str: ! 398: while (n-- && *np) { ! 399: putc(*np++&0177, bufp); ! 400: } ! 401: putc(0, bufp); ! 402: continue; ! 403: ! 404: case '1': ! 405: putc(1, bufp); ! 406: putc(0, bufp); ! 407: continue; ! 408: ! 409: case '0': ! 410: putc(0, bufp); ! 411: putc(0, bufp); ! 412: continue; ! 413: ! 414: case '\0': ! 415: if (ferror(bufp)) { ! 416: error("Write error on temp"); ! 417: exit(1); ! 418: } ! 419: return; ! 420: ! 421: default: ! 422: error("Botch in outcode"); ! 423: } ! 424: } ! 425: ! 426: unsigned ! 427: hash(sp) ! 428: register char *sp; ! 429: { ! 430: register unsigned h; ! 431: register c; ! 432: ! 433: h = 0; ! 434: c = 7; ! 435: do { ! 436: if (*sp == 0) ! 437: break; ! 438: h += h; ! 439: h += *sp++; ! 440: } while (--c != 0); ! 441: return(h%HSHSIZ); ! 442: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.