You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

506 lines
8.2 KiB

extdef() {
extern eof, cval, defsym;
extern csym, strflg, xdflg, peeksym, fcval;
int o, c, cs[], type, csym[], width, nel, ninit, defsym[];
char s[];
float sf;
double fcval;
if(((o=symbol())==0) | o==1) /* EOF */
return;
type = 0;
if (o==19) { /* keyword */
if ((type=cval)>4)
goto syntax; /* not type */
} else {
if (o==20)
csym[4] =| 0200; /* remember name */
peeksym = o;
}
defsym = 0;
xdflg++;
tdeclare(type, 0, 0);
if (defsym==0)
return;
*defsym = 6;
cs = &defsym[4];
printf(".globl %p\n", cs);
strflg = 1;
xdflg = 0;
type = defsym[1];
if ((type&030)==020) { /* a function */
printf(".text\n%p:\nmov r5,-(sp); mov sp,r5\n", cs);
declist(0);
strflg = 0;
c = 0;
if ((peeksym=symbol())!=2) { /* { */
blkhed();
c++;
}
statement(1);
retseq();
if (c)
blkend();
return;
}
width = length(defsym);
if ((type&030)==030) /* array */
width = plength(defsym);
nel = defsym[8];
ninit = 0;
if ((peeksym=symbol()) == 1) { /* ; */
printf(".comm %p,%o\n", &defsym[4], nel*width);
peeksym = -1;
return;
}
printf(".data\n%p:", &defsym[4]);
loop: {
ninit++;
switch(o=symbol()) {
case 22: /* string */
if (width!=2)
bxdec();
printf("L%d\n", cval);
break;
case 41: /* - const */
if ((o=symbol())==23) { /* float */
fcval = -fcval;
goto case23;
}
if (o!=21)
goto syntax;
cval = -cval;
case 21: /* const */
if (width==1)
printf(".byte ");
if (width>2) {
fcval = cval;
goto case23;
}
printf("%o\n", cval);
break;
case 20: /* name */
if (width!=2)
bxdec();
printf("%p\n", &csym[4]);
break;
case 23:
case23:
if (width==4) {
sf = fcval;
printf("%o;%o\n", sf);
break;
}
if (width==8) {
printf("%o;%o;%o;%o\n", fcval);
break;
}
bxdec();
break;
default:
goto syntax;
}
} if ((o=symbol())==9) goto loop; /* , */
if (o==1) { /* ; */
done:
if (ninit<nel)
printf(".=.+%d.\n", (nel-ninit)*width);
return;
}
syntax:
error("External definition syntax");
errflush(o);
statement(0);
}
bxdec()
{
error("Inconsistent external initialization");
}
statement(d) {
extern symbol, error, blkhed, eof, peeksym;
extern blkend, csym[], rcexpr, block[], tree[], regtab[];
extern retseq, jumpc, jump, label, contlab, brklab, cval;
extern swp[], isn, pswitch, peekc;
extern efftab[], deflab, errflush, swtab[], swsiz, branch;
int o, o1, o2, o3, np[];
stmt:
switch(o=symbol()) {
/* EOF */
case 0:
error("Unexpected EOF");
/* ; */
case 1:
/* } */
case 3:
return;
/* { */
case 2: {
if(d)
blkhed();
while (!eof) {
if ((o=symbol())==3) /* } */
goto bend;
peeksym = o;
statement(0);
}
error("Missing '}'");
bend:
return;
}
/* keyword */
case 19:
switch(cval) {
/* goto */
case 10:
np = tree();
if ((np[1]&030)!=030) /* not array */
np = block(1, 36, 1, np[2]+1, np);
rcexpr(block(1,102,0,0,np), regtab);
goto semi;
/* return */
case 11:
if((peeksym=symbol())==6) /* ( */
rcexpr(block(1,110,0,0,pexpr()), regtab);
retseq();
goto semi;
/* if */
case 12:
jumpc(pexpr(), o1=isn++, 0);
statement(0);
if ((o=symbol())==19 & cval==14) { /* else */
o2 = isn++;
(easystmt()?branch:jump)(o2);
label(o1);
statement(0);
label(o2);
return;
}
peeksym = o;
label(o1);
return;
/* while */
case 13:
o1 = contlab;
o2 = brklab;
label(contlab = isn++);
jumpc(pexpr(), brklab=isn++, 0);
o3 = easystmt();
statement(0);
(o3?branch:jump)(contlab);
label(brklab);
contlab = o1;
brklab = o2;
return;
/* break */
case 17:
if(brklab==0)
error("Nothing to break from");
jump(brklab);
goto semi;
/* continue */
case 18:
if(contlab==0)
error("Nothing to continue");
jump(contlab);
goto semi;
/* do */
case 19:
o1 = contlab;
o2 = brklab;
contlab = isn++;
brklab = isn++;
label(o3 = isn++);
statement(0);
label(contlab);
contlab = o1;
if ((o=symbol())==19 & cval==13) { /* while */
jumpc(tree(), o3, 1);
label(brklab);
brklab = o2;
goto semi;
}
goto syntax;
/* case */
case 16:
if ((o=symbol())!=21) { /* constant */
if (o!=41) /* - */
goto syntax;
if ((o=symbol())!=21)
goto syntax;
cval = - cval;
}
if ((o=symbol())!=8) /* : */
goto syntax;
if (swp==0) {
error("Case not in switch");
goto stmt;
}
if(swp>=swtab+swsiz) {
error("Switch table overflow");
} else {
*swp++ = isn;
*swp++ = cval;
label(isn++);
}
goto stmt;
/* switch */
case 15:
o1 = brklab;
brklab = isn++;
np = pexpr();
if (np[1]>1 & np[1]<07)
error("Integer required");
rcexpr(block(1,110,0,0,np), regtab);
pswitch();
brklab = o1;
return;
/* default */
case 20:
if (swp==0)
error("Default not in switch");
if ((o=symbol())!=8) /* : */
goto syntax;
deflab = isn++;
label(deflab);
goto stmt;
}
error("Unknown keyword");
goto syntax;
/* name */
case 20:
if (peekc==':') {
peekc = 0;
if (csym[0]>0) {
error("Redefinition");
goto stmt;
}
csym[0] = 7;
csym[1] = 030; /* int[] */
if (csym[2]==0)
csym[2] = isn++;
label(csym[2]);
goto stmt;
}
}
peeksym = o;
rcexpr(tree(), efftab);
goto semi;
semi:
if ((o=symbol())!=1) /* ; */
goto syntax;
return;
syntax:
error("Statement syntax");
errflush(o);
goto stmt;
}
pexpr()
{
auto o, t;
if ((o=symbol())!=6) /* ( */
goto syntax;
t = tree();
if ((o=symbol())!=7) /* ) */
goto syntax;
return(t);
syntax:
error("Statement syntax");
errflush(o);
return(0);
}
pswitch() {
extern swp[], isn, swtab[], printf, deflab, statement, brklab;
extern label;
int sswp[], dl, cv, swlab;
sswp = swp;
if (swp==0)
swp = swtab;
swlab = isn++;
printf("jsr pc,bswitch; l%d\n", swlab);
dl = deflab;
deflab = 0;
statement(0);
if (!deflab) {
deflab = isn++;
label(deflab);
}
printf("L%d:.data;L%d:", brklab, swlab);
while(swp>sswp & swp>swtab) {
cv = *--swp;
printf("%o; l%d\n", cv, *--swp);
}
printf("L%d; 0\n.text\n", deflab);
deflab = dl;
swp = sswp;
}
blkhed()
{
extern symbol, cval, peeksym, paraml[], parame[];
extern error, rlength, setstk, defvec, isn, defstat;
extern stack, hshtab[], hshsiz, pssiz;
int al, pl, cs[], hl, t[];
declist(0);
stack = al = 0;
pl = 4;
while(paraml) {
*parame = 0;
paraml = *(cs = paraml);
if (cs[1]==2) /* float args -> double */
cs[1] = 3;
cs[2] = pl;
*cs = 10;
if ((cs[1]&030) == 030) /* array */
cs[1] =- 020; /* set ref */
pl =+ rlength(cs);
}
cs = hshtab;
hl = hshsiz;
while(hl--) {
if (cs[4]) {
if (cs[0]>1 & (cs[1]&07)==05) { /* referred structure */
t = cs[3];
cs[3] = t[3];
cs[1] = cs[1]&077770 | 04;
}
switch(cs[0]) {
/* sort unmentioned */
case -2:
cs[0] = 5; /* auto */
/* auto */
case 5:
al =- trlength(cs);
cs[2] = al;
break;
/* parameter */
case 10:
cs[0] = 5;
break;
/* static */
case 7:
cs[2] = isn;
printf(".bss; L%d: .=.+%o; .text\n",
isn++, trlength(cs));
break;
}
}
cs = cs+pssiz;
}
setstk(al);
}
blkend() {
extern hshtab[], hshsiz, pssiz, hshused, debug;
auto i, hl;
i = 0;
hl = hshsiz;
while(hl--) {
if(hshtab[i+4]) {
if (debug)
if (hshtab[i]!=1)
error("%p %o %o %o %o %o",
&hshtab[i+4],
hshtab[i],
hshtab[i+1],
hshtab[i+2],
hshtab[i+3],
hshtab[i+8]);
if (hshtab[i]==0)
error("%p undefined", &hshtab[i+4]);
if((hshtab[i+4]&0200)==0) { /* not top-level */
hshtab[i+4] = 0;
hshused--;
}
}
i =+ pssiz;
}
}
errflush(o) {
extern symbol, peeksym, eof;
while(o>3) /* ; { } */
o = symbol();
peeksym = o;
}
declist(mosflg)
{
extern peeksym, csym[], cval;
auto o, offset;
offset = 0;
while((o=symbol())==19 & cval<10)
if (cval<=4)
offset = tdeclare(cval, offset, mosflg);
else
scdeclare(cval);
peeksym = o;
return(offset);
}
easystmt()
{
extern peeksym, peekc, cval;
if((peeksym=symbol())==20) /* name */
return(peekc!=':'); /* not label */
if (peeksym==19) { /* keyword */
switch(cval)
case 10: /* goto */
case 11: /* return */
case 17: /* break */
case 18: /* continue */
return(1);
return(0);
}
return(peeksym!=2); /* { */
}
branch(lab)
{
printf("br L%d\n", lab);
}