home *** CD-ROM | disk | FTP | other *** search
- #
- /*
- * C compiler
- *
- *
- */
-
- #include "c0.h"
-
- /*
- * 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)<<TYLEN) | (t&TYPE) | PTR);
- }
-
- /*
- * Make a tree that causes a branch to lbl
- * if the tree's value is non-zero together with the cond.
- */
- cbranch(t, lbl, cond)
- struct tnode *t;
- {
- treeout(t, 0);
- outcode("BNNN", CBRANCH, lbl, cond, line);
- }
-
- /*
- * Write out a tree.
- */
- rcexpr(atp)
- struct tnode *atp;
- {
- register struct tnode *tp;
-
- /*
- * Special optimization
- */
- if ((tp=atp)->op==INIT && tp->tr1->op==CON) {
- if (tp->type==CHAR) {
- outcode("B1N0", BDATA, tp->tr1->value);
- return;
- } else if (tp->type==INT || tp->type==UNSIGN) {
- outcode("BN", SINIT, tp->tr1->value);
- return;
- }
- }
- treeout(tp, 0);
- outcode("BN", EXPR, line);
- }
-
- treeout(atp, isstruct)
- struct tnode *atp;
- {
- register struct tnode *tp;
- register struct hshtab *hp;
- register nextisstruct;
-
- if ((tp = atp) == 0) {
- outcode("B", NULLOP);
- return;
- }
- nextisstruct = tp->type==STRUCT;
- switch(tp->op) {
-
- case NAME:
- hp = tp->tr1;
- if (hp->hclass==TYPEDEF)
- error("Illegal use of type name");
- outcode("BNN", NAME, hp->hclass==0?STATIC:hp->hclass, tp->type);
- if (hp->hclass==EXTERN)
- outcode("S", hp->name);
- else
- outcode("N", hp->hoffset);
- break;
-
- case LCON:
- outcode("BNNN", tp->op, tp->type, tp->lvalue);
- break;
-
- case CON:
- outcode("BNN", tp->op, tp->type, tp->value);
- break;
-
- case FCON:
- outcode("BNF", tp->op, tp->type, tp->cstr);
- break;
-
- case STRING:
- outcode("BNNN", NAME, STATIC, tp->type, tp->tr1);
- break;
-
- case FSEL:
- treeout(tp->tr1, nextisstruct);
- outcode("BNNN",tp->op,tp->type,tp->tr2->bitoffs,tp->tr2->flen);
- break;
-
- case ETYPE:
- error("Illegal use of type");
- break;
-
- case AMPER:
- treeout(tp->tr1, 1);
- outcode("BN", tp->op, tp->type);
- break;
-
-
- case CALL:
- treeout(tp->tr1, 1);
- treeout(tp->tr2, 0);
- outcode("BN", CALL, tp->type);
- break;
-
- default:
- treeout(tp->tr1, nextisstruct);
- if (opdope[tp->op]&BINARY)
- treeout(tp->tr2, nextisstruct);
- outcode("BN", tp->op, tp->type);
- break;
- }
- if (nextisstruct && isstruct==0)
- outcode("BNN", STRASG, STRUCT, tp->strp->ssize);
- }
-
- /*
- * 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 tnode *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, elsz;
- long n;
- register struct tnode *cs;
- int nd;
-
- cs = acs;
- t = cs->type;
- n = 1;
- nd = 0;
- while ((t&XTYPE) == ARRAY) {
- t = decref(t);
- n =* cs->subsp[nd++];
- }
- if ((t&~TYPE)==FUNC)
- return(0);
- if (t>=PTR)
- elsz = SZPTR;
- else switch(t&TYPE) {
-
- case INT:
- case UNSIGN:
- elsz = SZINT;
- break;
-
- case CHAR:
- elsz = 1;
- break;
-
- case FLOAT:
- elsz = SZFLOAT;
- break;
-
- case LONG:
- elsz = SZLONG;
- break;
-
- case DOUBLE:
- elsz = SZDOUB;
- break;
-
- case STRUCT:
- if ((elsz = cs->strp->ssize) == 0)
- error("Undefined structure");
- break;
- default:
- error("Compiler error (length)");
- return(0);
- }
- n *= elsz;
- if (n >= (unsigned)50000) {
- error("Warning: very large data structure");
- nerror--;
- }
- return(n);
- }
-
- /*
- * 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->hblklev == 0)
- pushdecl(csp);
- if (csp->hclass==0 && csp->htype==0) {
- csp->htype = ARRAY;
- csp->hflag =| FLABL;
- 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=='\014') /* FF */
- 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(JUMP,0,NULL,NULL,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;
- if (funcblk.type==CHAR)
- cp[-1] = block(ITOC, INT, NULL, NULL, cp[-1]);
- build(RFORCE);
- rcexpr(*--cp);
- }
- branch(retlab);
- }
-
- /*
- * Write a character on the error output.
- */
- /*
- * Coded output:
- * B: beginning of line; an operator
- * N: a number
- * S: a symbol (external)
- * 1: number 1
- * 0: number 0
- */
- outcode(s, a)
- char *s;
- {
- register *ap;
- register FILE *bufp;
- int n;
- register char *np;
-
- bufp = stdout;
- if (strflg)
- bufp = sbufp;
- ap = &a;
- for (;;) switch(*s++) {
- case 'B':
- putc(*ap++, bufp);
- putc(0376, bufp);
- continue;
-
- case 'N':
- putc(*ap, bufp);
- putc(*ap++>>8, bufp);
- continue;
-
- case 'F':
- n = 1000;
- np = *ap++;
- goto str;
-
- case 'S':
- n = NCPS;
- np = *ap++;
- if (*np)
- putc('_', bufp);
- str:
- while (n-- && *np) {
- putc(*np++&0177, bufp);
- }
- putc(0, bufp);
- continue;
-
- case '1':
- putc(1, bufp);
- putc(0, bufp);
- continue;
-
- case '0':
- putc(0, bufp);
- putc(0, bufp);
- continue;
-
- case '\0':
- if (ferror(bufp)) {
- error("Write error on temp");
- exit(1);
- }
- return;
-
- default:
- error("Botch in outcode");
- }
- }
-