340 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			340 lines
		
	
	
	
		
			5.4 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))
 | |
| 		{
 | |
| 			fprint(STDERR, "ERROR: line %d not defined\n",l->linenr);
 | |
| 			errorcnt++;
 | |
| 		}
 | |
| 		l=l->nextlist;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| newblock(nr)
 | |
| int	nr;
 | |
| {
 | |
| 	Linerecord	*l;
 | |
| 	List		*frwrd;
 | |
| 
 | |
| 	if ( debug) print("newblock at %d\n",nr);
 | |
| 	if ( nr>0 && currline && currline->linenr>= nr)
 | |
| 	{
 | |
| 		if ( debug) print("old line:%d\n",currline->linenr);
 | |
| 		error("Lines out of sequence");
 | |
| 	}
 | |
| 
 | |
| 	frwrd=srchforward(nr);
 | |
| 	if ( frwrd && debug) print("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;
 | |
| 
 | |
| 	/* 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) print("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) print("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;
 | |
| {
 | |
|            C_bra((label) 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);
 | |
| 	/*return index */
 | |
|         C_loc((arith) n);
 | |
| 	/* administer legal return */
 | |
|         C_cal("_gosub");
 | |
|         C_asp((arith) BEMINTSIZE);
 | |
|         C_bra((label) nr);
 | |
| 	C_df_ilb((label)l->emlabel);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| genreturns()
 | |
| {
 | |
| 	int nr;
 | |
| 
 | |
| 	nr= genlabel();
 | |
|         C_df_dnam("returns");
 | |
|         C_rom_ilb((label) nr);
 | |
|         C_rom_cst((arith)1);
 | |
|         C_rom_cst((arith) (gosubcnt-1));
 | |
| 
 | |
| 	while ( gosubhead)
 | |
| 	{
 | |
|                 C_rom_ilb((label) gosubhead->emlabel);
 | |
| 		gosubhead= gosubhead->nextlist;
 | |
| 	}
 | |
|         C_df_ilb((label) nr);
 | |
|         C_loc((arith) 1);
 | |
|         C_cal("error");
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| returnstmt()
 | |
| {
 | |
|         C_cal("_retstmt");
 | |
|         C_lfr((arith) BEMINTSIZE);
 | |
|         C_lae_dnam("returns",(arith)0);
 | |
|         C_csa((arith) BEMINTSIZE);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| /* 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();
 | |
| 	C_df_dlb((label)descr);
 | |
|         C_rom_ilb((label)firstlabel);
 | |
| 	C_rom_cst((arith) 1);
 | |
| 	C_rom_cst((arith)(jumpcnt-1));
 | |
| 	l= jumphead;
 | |
| 	while (l)
 | |
| 	{
 | |
| 		C_rom_ilb((label)l->emlabel);
 | |
| 		l= l->nextlist;
 | |
| 	}
 | |
| 	jumphead= jumptail=0; jumpcnt=0;
 | |
| 	if (debug) print("ongotst:%d labels\n", jumpcnt);
 | |
| 	conversion(type,INTTYPE);
 | |
| 	C_dup((arith) BEMINTSIZE);
 | |
| 	C_zlt(err_goto_label);
 | |
|         C_lae_dlb((label) descr,(arith) 0);
 | |
|         C_csa((arith) BEMINTSIZE);
 | |
| 	C_df_ilb((label)firstlabel);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| ongosubstmt(type)
 | |
| int type;
 | |
| {
 | |
| 	List *l;
 | |
| 	int firstlabel;
 | |
| 	int descr;
 | |
| 
 | |
| 	/* create descriptor first */
 | |
| 	descr= genlabel();
 | |
| 	firstlabel=genlabel();
 | |
| 	C_df_dlb((label)descr);
 | |
| 	C_rom_ilb((label)firstlabel);
 | |
| 	C_rom_cst((arith)1);
 | |
| 	C_rom_cst((arith)(jumpcnt-1));
 | |
| 	l= jumphead;
 | |
| 
 | |
| 	while (l)
 | |
| 	{
 | |
| 		C_rom_ilb((label)l->emlabel);
 | |
| 		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 */
 | |
|         C_loc((arith) gosubcnt);
 | |
|         C_cal("_gosub");
 | |
|         C_asp((arith) BEMINTSIZE);
 | |
| 	gosubcnt++;
 | |
| 	/* generate gosub */
 | |
| 	conversion(type,INTTYPE);
 | |
| 	C_dup((arith) BEMINTSIZE);
 | |
| 	C_zlt(err_goto_label);
 | |
|         C_lae_dlb((label) descr,(arith) 0);
 | |
|         C_csa((arith)  BEMINTSIZE);
 | |
|         C_df_ilb((label)firstlabel);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /* REGION ANALYSIS and FINAL VERSION GENERATION */
 | |
| 
 | |
| 
 |