294 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			294 lines
		
	
	
	
		
			5.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#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))
 | 
						|
		{
 | 
						|
			printf("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); 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); 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);
 | 
						|
}
 |