Add original unix v6
This commit is contained in:
+343
@@ -0,0 +1,343 @@
|
||||
#
|
||||
/*
|
||||
* 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)<<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(tree, lbl, cond)
|
||||
struct tnode *tree;
|
||||
{
|
||||
rcexpr(block(1,CBRANCH,tree,lbl,cond));
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out a tree.
|
||||
*/
|
||||
rcexpr(tree)
|
||||
struct tnode *tree;
|
||||
{
|
||||
|
||||
treeout(tree);
|
||||
outcode("BN", EXPR, line);
|
||||
}
|
||||
|
||||
treeout(atree)
|
||||
struct tnode *atree;
|
||||
{
|
||||
register struct tnode *tree;
|
||||
|
||||
if ((tree = atree) == 0)
|
||||
return;
|
||||
switch(tree->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");
|
||||
}
|
||||
Reference in New Issue
Block a user