461 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			461 lines
		
	
	
	
		
			7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Id$ */
 | 
						|
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
/* @(#)comm7.c	1.10 */
 | 
						|
/*
 | 
						|
 * miscellaneous
 | 
						|
 */
 | 
						|
 | 
						|
#include <errno.h>
 | 
						|
#include "comm0.h"
 | 
						|
#include "comm1.h"
 | 
						|
#include "y.tab.h"
 | 
						|
#include <stdarg.h>
 | 
						|
#include <object.h>
 | 
						|
 | 
						|
valu_t load(const item_t* ip)
 | 
						|
{
 | 
						|
#ifdef ASLD
 | 
						|
	int typ;
 | 
						|
 | 
						|
	typ = ip->i_type & S_TYP;
 | 
						|
	if ((typ -= S_MIN) < 0) /* S_UND or S_ABS */
 | 
						|
		return (ip->i_valu);
 | 
						|
	return (ip->i_valu + sect[typ].s_base);
 | 
						|
#else
 | 
						|
	if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM))
 | 
						|
	{
 | 
						|
		if (pass == PASS_3)
 | 
						|
		{
 | 
						|
			if (relonami != 0)
 | 
						|
				serror("relocation error (relonami=%d, type=%08x)", relonami, ip->i_type);
 | 
						|
			relonami = ip->i_valu + 1;
 | 
						|
		}
 | 
						|
		return (0);
 | 
						|
	}
 | 
						|
	return (ip->i_valu);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
int store(item_t* ip, valu_t val)
 | 
						|
{
 | 
						|
#ifdef ASLD
 | 
						|
	int typ;
 | 
						|
 | 
						|
	typ = ip->i_type & S_TYP;
 | 
						|
	if ((typ -= S_MIN) >= 0)
 | 
						|
		val -= sect[typ].s_base;
 | 
						|
#else
 | 
						|
	if ((ip->i_type & S_TYP) == S_UND)
 | 
						|
		return (0);
 | 
						|
#endif
 | 
						|
	assert(pass != PASS_3 || (ip->i_type & S_VAR) || ip->i_valu == val);
 | 
						|
	ip->i_valu = val;
 | 
						|
	return (1);
 | 
						|
}
 | 
						|
 | 
						|
char* remember(char* s)
 | 
						|
{
 | 
						|
	char* p;
 | 
						|
	int n;
 | 
						|
	static int nleft = 0;
 | 
						|
	static char* next;
 | 
						|
 | 
						|
	p = s;
 | 
						|
	n = 0;
 | 
						|
	do
 | 
						|
		n++;
 | 
						|
	while (*p++);
 | 
						|
	if ((nleft -= n) < 0)
 | 
						|
	{
 | 
						|
		next = malloc(MEMINCR);
 | 
						|
		if (next == 0)
 | 
						|
			fatal("out of memory");
 | 
						|
		nleft = (MEMINCR / sizeof(char)) - n;
 | 
						|
		assert(nleft >= 0);
 | 
						|
	}
 | 
						|
	p = next;
 | 
						|
	while (*p++ = *s++)
 | 
						|
		;
 | 
						|
	s = next;
 | 
						|
	next = p;
 | 
						|
	return (s);
 | 
						|
}
 | 
						|
 | 
						|
int combine(int typ1, int typ2, int op)
 | 
						|
{
 | 
						|
	switch (op)
 | 
						|
	{
 | 
						|
		case '+':
 | 
						|
			if (typ1 == S_ABS)
 | 
						|
				return (typ2);
 | 
						|
			if (typ2 == S_ABS)
 | 
						|
				return (typ1);
 | 
						|
			break;
 | 
						|
		case '-':
 | 
						|
			if (typ2 == S_ABS)
 | 
						|
				return (typ1);
 | 
						|
			if ((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND)
 | 
						|
				return (S_ABS | S_VAR);
 | 
						|
			break;
 | 
						|
		case '>':
 | 
						|
			if (typ1 == S_ABS && typ2 == S_ABS)
 | 
						|
				return (S_ABS);
 | 
						|
			if (((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) || (typ1 == S_ABS)
 | 
						|
			    || (typ2 == S_ABS))
 | 
						|
				return (S_ABS | S_VAR);
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			if (typ1 == S_ABS && typ2 == S_ABS)
 | 
						|
				return (S_ABS);
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	if (pass != PASS_1)
 | 
						|
		serror("illegal operator");
 | 
						|
	return (S_UND);
 | 
						|
}
 | 
						|
 | 
						|
#ifdef LISTING
 | 
						|
int printx(int ndig, valu_t val)
 | 
						|
{
 | 
						|
	static char buf[8];
 | 
						|
	char* p;
 | 
						|
	int c, n;
 | 
						|
 | 
						|
	p = buf;
 | 
						|
	n = ndig;
 | 
						|
	do
 | 
						|
	{
 | 
						|
		*p++ = (int)val & 017;
 | 
						|
		val >>= 4;
 | 
						|
	} while (--n);
 | 
						|
	do
 | 
						|
	{
 | 
						|
		c = "0123456789ABCDEF"[*--p];
 | 
						|
		putchar(c);
 | 
						|
	} while (p > buf);
 | 
						|
	return (ndig);
 | 
						|
}
 | 
						|
 | 
						|
void listline(int textline)
 | 
						|
{
 | 
						|
	int c;
 | 
						|
 | 
						|
	if ((listflag & 4) && (c = getc(listfile)) != '\n' && textline)
 | 
						|
	{
 | 
						|
		if (listcolm >= 24)
 | 
						|
			printf(" \\\n\t\t\t");
 | 
						|
		else
 | 
						|
			do
 | 
						|
			{
 | 
						|
				putchar('\t');
 | 
						|
				listcolm += 8;
 | 
						|
			} while (listcolm < 24);
 | 
						|
		do
 | 
						|
		{
 | 
						|
			assert(c != EOF);
 | 
						|
			putchar(c);
 | 
						|
		} while ((c = getc(listfile)) != '\n');
 | 
						|
	}
 | 
						|
	if (listflag & 7)
 | 
						|
	{
 | 
						|
		putchar('\n');
 | 
						|
		fflush(stdout);
 | 
						|
	}
 | 
						|
	listeoln = 1;
 | 
						|
	listcolm = 0;
 | 
						|
	listflag = listtemp;
 | 
						|
}
 | 
						|
#endif /* LISTING */
 | 
						|
 | 
						|
/* ---------- code optimization ---------- */
 | 
						|
 | 
						|
#ifdef THREE_PASS
 | 
						|
#define PBITTABSZ 128
 | 
						|
static char* pbittab[PBITTABSZ];
 | 
						|
 | 
						|
int small(int fitsmall, int gain)
 | 
						|
{
 | 
						|
	int bit;
 | 
						|
	char* p;
 | 
						|
 | 
						|
	if (DOTSCT == NULL)
 | 
						|
		nosect();
 | 
						|
	if (bflag)
 | 
						|
		return (0);
 | 
						|
	if (nbits == BITCHUNK)
 | 
						|
	{
 | 
						|
		bitindex++;
 | 
						|
		nbits = 0;
 | 
						|
		if (bitindex == PBITTABSZ)
 | 
						|
		{
 | 
						|
			static int w_given;
 | 
						|
			if (pass == PASS_1 && !w_given)
 | 
						|
			{
 | 
						|
				w_given = 1;
 | 
						|
				warning("bit table overflow");
 | 
						|
			}
 | 
						|
			return (0);
 | 
						|
		}
 | 
						|
		if (pbittab[bitindex] == 0 && pass == PASS_1)
 | 
						|
		{
 | 
						|
			if ((pbittab[bitindex] = calloc(MEMINCR, 1)) == 0)
 | 
						|
			{
 | 
						|
				static int w2_given;
 | 
						|
 | 
						|
				if (!w2_given)
 | 
						|
				{
 | 
						|
					w2_given = 1;
 | 
						|
					warning("out of space for bit table");
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (pbittab[bitindex] == 0)
 | 
						|
			return (0);
 | 
						|
	}
 | 
						|
	bit = 1 << (nbits & 7);
 | 
						|
	p = pbittab[bitindex] + (nbits >> 3);
 | 
						|
	nbits++;
 | 
						|
	switch (pass)
 | 
						|
	{
 | 
						|
		case PASS_1:
 | 
						|
			return (0);
 | 
						|
		case PASS_2:
 | 
						|
			if (fitsmall)
 | 
						|
			{
 | 
						|
				DOTGAIN += gain;
 | 
						|
				*p |= bit;
 | 
						|
			}
 | 
						|
			return (fitsmall);
 | 
						|
		case PASS_3:
 | 
						|
			assert(fitsmall || (*p & bit) == 0);
 | 
						|
			return (*p & bit);
 | 
						|
	}
 | 
						|
	/*NOTREACHED*/
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* ---------- output ---------- */
 | 
						|
 | 
						|
void emit1(int arg)
 | 
						|
{
 | 
						|
	static int olddottyp = -1;
 | 
						|
#ifdef LISTING
 | 
						|
	if (listeoln)
 | 
						|
	{
 | 
						|
		if (listflag & 1)
 | 
						|
		{
 | 
						|
			listcolm += printx(VALWIDTH, (valu_t)DOTVAL);
 | 
						|
			listcolm++;
 | 
						|
			putchar(' ');
 | 
						|
		}
 | 
						|
		listeoln = 0;
 | 
						|
	}
 | 
						|
	if (listflag & 2)
 | 
						|
		listcolm += printx(2, (valu_t)arg);
 | 
						|
#endif
 | 
						|
	switch (pass)
 | 
						|
	{
 | 
						|
		case PASS_1:
 | 
						|
			if (DOTSCT == NULL)
 | 
						|
				nosect();
 | 
						|
			/* no break */
 | 
						|
		case PASS_2:
 | 
						|
			DOTSCT->s_zero = 0;
 | 
						|
			break;
 | 
						|
		case PASS_3:
 | 
						|
			if (DOTTYP != olddottyp)
 | 
						|
			{
 | 
						|
				wr_outsect(DOTTYP - S_MIN);
 | 
						|
				olddottyp = DOTTYP;
 | 
						|
			}
 | 
						|
			while (DOTSCT->s_zero)
 | 
						|
			{
 | 
						|
				wr_putc(0);
 | 
						|
				DOTSCT->s_zero--;
 | 
						|
			}
 | 
						|
			wr_putc(arg);
 | 
						|
			break;
 | 
						|
	}
 | 
						|
	DOTVAL++;
 | 
						|
}
 | 
						|
 | 
						|
void emit2(int arg)
 | 
						|
{
 | 
						|
#ifdef BYTES_REVERSED
 | 
						|
	emit1((arg >> 8));
 | 
						|
	emit1(arg);
 | 
						|
#else
 | 
						|
	emit1(arg);
 | 
						|
	emit1((arg >> 8));
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void emit4(long arg)
 | 
						|
{
 | 
						|
#ifdef WORDS_REVERSED
 | 
						|
	emit2((int)(arg >> 16));
 | 
						|
	emit2((int)(arg));
 | 
						|
#else
 | 
						|
	emit2((int)(arg));
 | 
						|
	emit2((int)(arg >> 16));
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
void emitx(valu_t val, int n)
 | 
						|
{
 | 
						|
	switch (n)
 | 
						|
	{
 | 
						|
		case RELO1:
 | 
						|
			emit1((int)val);
 | 
						|
			break;
 | 
						|
		case RELO2:
 | 
						|
#ifdef BYTES_REVERSED
 | 
						|
			emit1(((int)val >> 8));
 | 
						|
			emit1((int)val);
 | 
						|
#else
 | 
						|
			emit1((int)val);
 | 
						|
			emit1(((int)val >> 8));
 | 
						|
#endif
 | 
						|
			break;
 | 
						|
		case RELO4:
 | 
						|
#ifdef WORDS_REVERSED
 | 
						|
			emit2((int)(val >> 16));
 | 
						|
			emit2((int)(val));
 | 
						|
#else
 | 
						|
			emit2((int)(val));
 | 
						|
			emit2((int)(val >> 16));
 | 
						|
#endif
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			assert(0);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void emitstr(int zero)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	char* p;
 | 
						|
 | 
						|
	p = stringbuf;
 | 
						|
	i = stringlen;
 | 
						|
	while (--i >= 0)
 | 
						|
		emit1(*p++);
 | 
						|
	if (zero)
 | 
						|
		emit1(0);
 | 
						|
}
 | 
						|
 | 
						|
#define CODE_EXPANDER
 | 
						|
 | 
						|
#if !defined IEEEFLOAT && !defined PDPFLOAT
 | 
						|
	#define IEEEFLOAT
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined WORDS_REVERSED
 | 
						|
	#define FL_MSL_AT_LOW_ADDRESS 1
 | 
						|
	#define FL_MSW_AT_LOW_ADDRESS 1
 | 
						|
#else
 | 
						|
	#define FL_MSL_AT_LOW_ADDRESS 0
 | 
						|
	#define FL_MSW_AT_LOW_ADDRESS 0
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined BYTES_REVERSED
 | 
						|
	#define FL_MSB_AT_LOW_ADDRESS 1
 | 
						|
#else
 | 
						|
	#define FL_MSB_AT_LOW_ADDRESS 0
 | 
						|
#endif
 | 
						|
 | 
						|
#define gen1 emit1
 | 
						|
#include <con_float>
 | 
						|
 | 
						|
void emitf(int size, int negative)
 | 
						|
{
 | 
						|
	char buffer[40];
 | 
						|
 | 
						|
	if (stringlen > sizeof(buffer)-1)
 | 
						|
		fatal("floating point constant too long");
 | 
						|
 | 
						|
	if (negative)
 | 
						|
	{
 | 
						|
		buffer[0] = '-';
 | 
						|
		strcpy(buffer+1, stringbuf);
 | 
						|
		con_float(buffer, size);
 | 
						|
	}
 | 
						|
	else
 | 
						|
		con_float(stringbuf, size);
 | 
						|
}
 | 
						|
 | 
						|
/* ---------- Error handling ---------- */
 | 
						|
 | 
						|
/* ARGSUSED */
 | 
						|
void yyerror(const char* message)
 | 
						|
{
 | 
						|
} /* we will do our own error printing */
 | 
						|
 | 
						|
void nosect(void)
 | 
						|
{
 | 
						|
	fatal("no sections");
 | 
						|
}
 | 
						|
 | 
						|
void wr_fatal(void)
 | 
						|
{
 | 
						|
	fatal("write error");
 | 
						|
}
 | 
						|
 | 
						|
static void diag(const char* tail, const char* s, va_list ap)
 | 
						|
{
 | 
						|
	fflush(stdout);
 | 
						|
	if (modulename)
 | 
						|
		fprintf(stderr, "\"%s\", line %ld: ", modulename, lineno);
 | 
						|
	else
 | 
						|
		fprintf(stderr, "%s: ", progname);
 | 
						|
	vfprintf(stderr, s, ap);
 | 
						|
	fprintf(stderr, "%s", tail);
 | 
						|
}
 | 
						|
 | 
						|
/* VARARGS1 */
 | 
						|
void fatal(const char* s, ...)
 | 
						|
{
 | 
						|
	va_list ap;
 | 
						|
	va_start(ap, s);
 | 
						|
 | 
						|
	nerrors++;
 | 
						|
	diag(" (fatal)\n", s, ap);
 | 
						|
	stop();
 | 
						|
 | 
						|
	va_end(ap);
 | 
						|
}
 | 
						|
 | 
						|
/* VARARGS1 */
 | 
						|
void serror(const char* s, ...)
 | 
						|
{
 | 
						|
	va_list ap;
 | 
						|
	va_start(ap, s);
 | 
						|
 | 
						|
	nerrors++;
 | 
						|
	diag("\n", s, ap);
 | 
						|
	stop();
 | 
						|
 | 
						|
	va_end(ap);
 | 
						|
}
 | 
						|
 | 
						|
/* VARARGS1 */
 | 
						|
void warning(const char* s, ...)
 | 
						|
{
 | 
						|
	va_list ap;
 | 
						|
	va_start(ap, s);
 | 
						|
 | 
						|
	nerrors++;
 | 
						|
	diag(" (warning)\n", s, ap);
 | 
						|
	stop();
 | 
						|
 | 
						|
	va_end(ap);
 | 
						|
}
 | 
						|
 | 
						|
void nofit(void)
 | 
						|
{
 | 
						|
	if (pass == PASS_3)
 | 
						|
		warning("too big");
 | 
						|
}
 |