299 lines
5.8 KiB
C
299 lines
5.8 KiB
C
/*
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
*/
|
|
#include "bem.h"
|
|
|
|
#ifndef NORSCID
|
|
static char rcs_id[] = "$Header$" ;
|
|
#endif
|
|
|
|
|
|
List *forwardlabel=0;
|
|
|
|
Linerecord *firstline,
|
|
*currline,
|
|
*lastline;
|
|
|
|
List *newlist()
|
|
{
|
|
List *l;
|
|
/*NOSTRICT*/ l= (List *) salloc(sizeof(List));
|
|
return(l);
|
|
}
|
|
|
|
/* Line management is handled here */
|
|
|
|
Linerecord *srchline(nr)
|
|
int nr;
|
|
{
|
|
Linerecord *l;
|
|
for(l=firstline;l && l->linenr<=nr;l= l->nextline)
|
|
if( l->linenr== nr) return(l);
|
|
return(0);
|
|
}
|
|
List *srchforward(nr)
|
|
int nr;
|
|
{
|
|
List *l;
|
|
for(l=forwardlabel;l ;l=l->nextlist)
|
|
if( l->linenr== nr) return(l);
|
|
return(0);
|
|
}
|
|
linewarnings()
|
|
{
|
|
List *l;
|
|
extern int errorcnt;
|
|
l= forwardlabel;
|
|
while(l)
|
|
{
|
|
if( !srchline(l->linenr))
|
|
{
|
|
fprintf(stderr,"ERROR: line %d not defined\n",l->linenr);
|
|
errorcnt++;
|
|
}
|
|
l=l->nextlist;
|
|
}
|
|
}
|
|
|
|
newblock(nr)
|
|
int nr;
|
|
{
|
|
Linerecord *l;
|
|
List *frwrd;
|
|
|
|
if( debug) printf("newblock at %d\n",nr);
|
|
if( nr>0 && currline && currline->linenr>= nr)
|
|
{
|
|
if( debug) printf("old line:%d\n",currline->linenr);
|
|
error("Lines out of sequence");
|
|
}
|
|
|
|
frwrd=srchforward(nr);
|
|
if( frwrd && debug) printf("forward found %d\n",frwrd->emlabel);
|
|
l= srchline(nr);
|
|
if( l)
|
|
{
|
|
error("Line redefined");
|
|
nr= -genlabel();
|
|
}
|
|
|
|
/* make new EM block structure */
|
|
/*NOSTRICT*/ l= (Linerecord *) salloc(sizeof(*l));
|
|
l->emlabel= frwrd? frwrd->emlabel: genlabel();
|
|
l->linenr= nr;
|
|
/* save offset into Tmpfile too */
|
|
l->offset = (long) ftell(Tmpfile);
|
|
l->codelines= emlinecount;
|
|
|
|
/* insert this record */
|
|
if( firstline)
|
|
{
|
|
currline->nextline=l;
|
|
l->prevline= currline;
|
|
lastline= currline=l;
|
|
} else
|
|
firstline = lastline =currline=l;
|
|
}
|
|
|
|
gotolabel(nr)
|
|
int nr;
|
|
{
|
|
/* simulate a goto statement in the line record table */
|
|
Linerecord *l1;
|
|
List *ll;
|
|
|
|
if(debug) printf("goto label %d\n",nr);
|
|
/* update currline */
|
|
ll= newlist();
|
|
ll-> linenr=nr;
|
|
ll-> nextlist= currline->gotos;
|
|
currline->gotos= ll;
|
|
|
|
/* try to generate code */
|
|
l1= srchline(nr);
|
|
if( (ll=srchforward(nr))!=0)
|
|
nr= ll->emlabel;
|
|
else
|
|
if( l1==0)
|
|
{
|
|
/* declare forward label */
|
|
if(debug) printf("declare forward %d\n",nr);
|
|
ll= newlist();
|
|
ll->emlabel= genlabel();
|
|
ll-> linenr=nr;
|
|
ll->nextlist= forwardlabel;
|
|
forwardlabel= ll;
|
|
nr= ll->emlabel;
|
|
} else
|
|
nr= l1->emlabel;
|
|
return(nr);
|
|
}
|
|
gotostmt(nr)
|
|
int nr;
|
|
{
|
|
emcode("bra",instrlabel(gotolabel(nr)));
|
|
}
|
|
/* GOSUB-return, assume that proper entries are made to subroutines
|
|
only. The return statement is triggered by a fake constant label */
|
|
|
|
List *gosubhead, *gotail;
|
|
int gosubcnt=1;
|
|
|
|
List *gosublabel()
|
|
{
|
|
List *l;
|
|
|
|
l= newlist();
|
|
l->nextlist=0;
|
|
l->emlabel=genlabel();
|
|
if( gotail){
|
|
gotail->nextlist=l;
|
|
gotail=l;
|
|
} else gotail= gosubhead=l;
|
|
gosubcnt++;
|
|
return(l);
|
|
}
|
|
gosubstmt(lab)
|
|
int lab;
|
|
{
|
|
List *l;
|
|
int nr,n;
|
|
|
|
n=gosubcnt;
|
|
l= gosublabel();
|
|
nr=gotolabel(lab);
|
|
emcode("loc",itoa(n)); /*return index */
|
|
emcode("cal","$_gosub"); /* administer legal return */
|
|
emcode("asp",EMINTSIZE);
|
|
emcode("bra",instrlabel(nr));
|
|
fprintf(Tmpfile,"%d\n",l->emlabel);
|
|
emlinecount++;
|
|
}
|
|
genreturns()
|
|
{
|
|
int nr;
|
|
nr= genlabel();
|
|
fprintf(emfile,"returns\n");
|
|
fprintf(emfile," rom *%d,1,%d\n",nr,gosubcnt-1);
|
|
while( gosubhead)
|
|
{
|
|
fprintf(emfile," rom *%d\n",gosubhead->emlabel);
|
|
gosubhead= gosubhead->nextlist;
|
|
}
|
|
fprintf(emfile,"%d\n",nr);
|
|
fprintf(emfile," loc 1\n");
|
|
fprintf(emfile," cal $error\n");
|
|
}
|
|
returnstmt()
|
|
{
|
|
emcode("cal","$_retstmt"); /* ensure legal return*/
|
|
emcode("lfr",EMINTSIZE);
|
|
fprintf(Tmpfile," lae returns\n");
|
|
emlinecount++;
|
|
emcode("csa",EMINTSIZE);
|
|
}
|
|
/* compound goto-gosub statements */
|
|
List *jumphead,*jumptail;
|
|
int jumpcnt;
|
|
|
|
jumpelm(nr)
|
|
int nr;
|
|
{
|
|
List *l;
|
|
|
|
l= newlist();
|
|
l->emlabel= gotolabel(nr);
|
|
l->nextlist=0;
|
|
if( jumphead==0) jumphead= jumptail= l;
|
|
else {
|
|
jumptail->nextlist=l;
|
|
jumptail=l;
|
|
}
|
|
jumpcnt++;
|
|
}
|
|
ongotostmt(type)
|
|
int type;
|
|
{
|
|
/* generate the code itself, index in on top of the stack */
|
|
/* blurh, store the number of entries in the descriptor */
|
|
int firstlabel;
|
|
int descr;
|
|
List *l;
|
|
/* create descriptor first */
|
|
descr= genlabel();
|
|
firstlabel=genlabel();
|
|
fprintf(Tmpfile,"l%d\n",descr); emlinecount++;
|
|
fprintf(Tmpfile," rom *%d,1,%d\n",firstlabel,jumpcnt-1); emlinecount++;
|
|
l= jumphead;
|
|
while( l)
|
|
{
|
|
fprintf(Tmpfile," rom *%d\n",l->emlabel); emlinecount++;
|
|
l= l->nextlist;
|
|
}
|
|
jumphead= jumptail=0; jumpcnt=0;
|
|
if(debug) printf("ongotst:%d labels\n", jumpcnt);
|
|
conversion(type,INTTYPE);
|
|
emcode("lae",datalabel(descr));
|
|
emcode("csa",EMINTSIZE);
|
|
fprintf(Tmpfile,"%d\n",firstlabel); emlinecount++;
|
|
}
|
|
ongosubstmt(type)
|
|
int type;
|
|
{
|
|
List *l;
|
|
int firstlabel;
|
|
int descr;
|
|
/* create descriptor first */
|
|
descr= genlabel();
|
|
firstlabel=genlabel();
|
|
fprintf(Tmpfile,"l%d\n",descr); emlinecount++;
|
|
fprintf(Tmpfile," rom *%d,1,%d\n",firstlabel,jumpcnt-1); emlinecount++;
|
|
l= jumphead;
|
|
while( l)
|
|
{
|
|
fprintf(Tmpfile," rom *%d\n",l->emlabel); emlinecount++;
|
|
l= l->nextlist;
|
|
}
|
|
jumphead= jumptail=0; jumpcnt=0;
|
|
|
|
l= newlist();
|
|
l->nextlist=0;
|
|
l->emlabel=firstlabel;
|
|
if( gotail){
|
|
gotail->nextlist=l;
|
|
gotail=l;
|
|
} else gotail= gosubhead=l;
|
|
/* save the return point of the gosub */
|
|
emcode("loc",itoa(gosubcnt));
|
|
emcode("cal","$_gosub");
|
|
emcode("asp",EMINTSIZE);
|
|
gosubcnt++;
|
|
/* generate gosub */
|
|
conversion(type,INTTYPE);
|
|
emcode("lae",datalabel(descr));
|
|
emcode("csa",EMINTSIZE);
|
|
fprintf(Tmpfile,"%d\n",firstlabel);
|
|
emlinecount++;
|
|
}
|
|
|
|
/* REGION ANALYSIS and FINAL VERSION GENERATION */
|
|
|
|
simpleprogram()
|
|
{
|
|
char buf[512];
|
|
int length;
|
|
|
|
/* a small EM programs has been found */
|
|
prologcode();
|
|
prolog2();
|
|
(void) fclose(Tmpfile);
|
|
Tmpfile= fopen(tmpfname,"r");
|
|
if( Tmpfile==NULL)
|
|
fatal("tmp file disappeared");
|
|
while( (length=fread(buf,1,512,Tmpfile)) != 0)
|
|
(void) fwrite(buf,1,length,emfile);
|
|
epilogcode();
|
|
(void) unlink(tmpfname);
|
|
}
|