# /* * C compiler * * */ #include "c0h.c" /* * Reduce the degree-of-reference by one. * e.g. turn "ptr-to-int" into "int". */ decref(at) { register t; t = at; if ((t & ~TYPE) == 0) { error("Illegal indirection"); return(t); } return((t>>TYLEN) & ~TYPE | t&TYPE); } /* * Increase the degree of reference by * one; e.g. turn "int" to "ptr-to-int". */ incref(t) { return(((t&~TYPE)<op) { case 0: outcode("B", NULL); return; case NAME: outcode("BNN", NAME, tree->class, tree->type); if (tree->class==EXTERN) outcode("S", tree->nname); else outcode("N", tree->nloc); return; case CON: case FCON: case SFCON: outcode("BNN", tree->op, tree->type, tree->value); return; case FSEL: treeout(tree->tr1); outcode("BNN", tree->op, tree->type, tree->tr2); return; case CBRANCH: treeout(tree->btree); outcode("BNN", tree->op, tree->lbl, tree->cond); return; default: treeout(tree->tr1); if (opdope[tree->op]&BINARY) treeout(tree->tr2); outcode("BN", tree->op, tree->type); return; } } /* * Generate a branch */ branch(lab) { outcode("BN", BRANCH, lab); } /* * Generate a label */ label(l) { outcode("BN", LABEL, l); } /* * ap is a tree node whose type * is some kind of pointer; return the size of the object * to which the pointer points. */ plength(ap) struct tname *ap; { register t, l; register struct tname *p; p = ap; if (p==0 || ((t=p->type)&~TYPE) == 0) /* not a reference */ return(1); p->type = decref(t); l = length(p); p->type = t; return(l); } /* * return the number of bytes in the object * whose tree node is acs. */ length(acs) struct tnode *acs; { register t, n; register struct tnode *cs; cs = acs; t = cs->type; n = 1; while ((t&XTYPE) == ARRAY) { t = decref(t); n = dimtab[cs->ssp&0377]; } if ((t&~TYPE)==FUNC) return(0); if (t>=PTR) return(2*n); switch(t&TYPE) { case INT: return(2*n); case CHAR: return(n); case FLOAT: case LONG: return(4*n); case DOUBLE: return(8*n); case STRUCT: return(n * dimtab[cs->lenp&0377]); case RSTRUCT: error("Bad structure"); return(0); } error("Compiler error (length)"); } /* * The number of bytes in an object, rounded up to a word. */ rlength(cs) struct tnode *cs; { return((length(cs)+ALIGN) & ~ALIGN); } /* * After an "if (...) goto", look to see if the transfer * is to a simple label. */ simplegoto() { register struct hshtab *csp; if ((peeksym=symbol())==NAME && nextchar()==';') { csp = csym; if (csp->hclass==0 && csp->htype==0) { csp->htype = ARRAY; if (csp->hoffset==0) csp->hoffset = isn++; } if ((csp->hclass==0||csp->hclass==STATIC) && csp->htype==ARRAY) { peeksym = -1; return(csp->hoffset); } } return(0); } /* * Return the next non-white-space character */ nextchar() { while (spnextchar()==' ') peekc = 0; return(peekc); } /* * Return the next character, translating all white space * to blank and handling line-ends. */ spnextchar() { register c; if ((c = peekc)==0) c = getchar(); if (c=='\t') c = ' '; else if (c=='\n') { c = ' '; if (inhdr==0) line++; inhdr = 0; } else if (c=='\001') { /* SOH, insert marker */ inhdr++; c = ' '; } peekc = c; return(c); } /* * is a break or continue legal? */ chconbrk(l) { if (l==0) error("Break/continue error"); } /* * The goto statement. */ dogoto() { register struct tnode *np; *cp++ = tree(); build(STAR); chkw(np = *--cp, -1); rcexpr(block(1,JUMP,0,0,np)); } /* * The return statement, which has to convert * the returned object to the function's type. */ doret() { register struct tnode *t; if (nextchar() != ';') { t = tree(); *cp++ = &funcblk; *cp++ = t; build(ASSIGN); cp[-1] = cp[-1]->tr2; build(RFORCE); rcexpr(*--cp); } branch(retlab); } /* * write out a character to the usual output * or to the string file */ putchar(c) { write(1, &c, 1); } outcode(s, a) char *s; { register char *sp; register *ap, *bufp; int n; char *np; bufp = obuf; if (strflg) bufp = sbuf; ap = &a; for (;;) switch(*s++) { case 'B': putw(*ap++ | (0376<<8), bufp); continue; case 'N': putw(*ap++, bufp); continue; case 'S': np = *ap++; n = ncps; while (n-- && *np) { putc(*np++, bufp); } putc(0, bufp); continue; case '1': putw(1, bufp); continue; case '0': putw(0, bufp); continue; case '\0': return; } error("Botch in outcode"); }