428 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Header$ */
 | 
						|
/*
 | 
						|
 * (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	"comm0.h"
 | 
						|
#include	"comm1.h"
 | 
						|
#include	"y.tab.h"
 | 
						|
 | 
						|
extern char	*sprintf();
 | 
						|
 | 
						|
valu_t
 | 
						|
load(ip)
 | 
						|
register item_t *ip;
 | 
						|
{
 | 
						|
#ifdef ASLD
 | 
						|
	register short 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 = ip->i_valu+1;
 | 
						|
		}
 | 
						|
		return(0);
 | 
						|
	}
 | 
						|
	return(ip->i_valu);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
store(ip, val)
 | 
						|
register item_t *ip;
 | 
						|
valu_t val;
 | 
						|
{
 | 
						|
#ifdef ASLD
 | 
						|
	register short 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(s)
 | 
						|
register char *s;
 | 
						|
{
 | 
						|
	register char *p;
 | 
						|
	register n;
 | 
						|
	static 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);
 | 
						|
}
 | 
						|
 | 
						|
combine(typ1, typ2, op)
 | 
						|
register typ1, typ2;
 | 
						|
{
 | 
						|
	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
 | 
						|
printx(ndig, val)
 | 
						|
valu_t val;
 | 
						|
{
 | 
						|
	static char buf[8];
 | 
						|
	register char *p;
 | 
						|
	register 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);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef LISTING
 | 
						|
listline(textline)
 | 
						|
{
 | 
						|
	register 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];
 | 
						|
 | 
						|
small(fitsmall, gain)
 | 
						|
{
 | 
						|
	register bit;
 | 
						|
	register 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 ---------- */
 | 
						|
 | 
						|
emit1(arg)
 | 
						|
{
 | 
						|
#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:
 | 
						|
		wr_outsect(DOTTYP-S_MIN);
 | 
						|
		while (DOTSCT->s_zero) {
 | 
						|
			wr_putc(0);
 | 
						|
			DOTSCT->s_zero--;
 | 
						|
		}
 | 
						|
		wr_putc(arg);
 | 
						|
		break;
 | 
						|
	}
 | 
						|
	DOTVAL++;
 | 
						|
}
 | 
						|
 | 
						|
emit2(arg)
 | 
						|
int arg;
 | 
						|
{
 | 
						|
#ifdef BYTES_REVERSED
 | 
						|
	emit1((arg>>8)); emit1(arg);
 | 
						|
#else
 | 
						|
	emit1(arg); emit1((arg>>8));
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
emit4(arg)
 | 
						|
long arg;
 | 
						|
{
 | 
						|
#ifdef WORDS_REVERSED
 | 
						|
	emit2((int)(arg>>16)); emit2((int)(arg));
 | 
						|
#else
 | 
						|
	emit2((int)(arg)); emit2((int)(arg>>16));
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
emitx(val, n)
 | 
						|
valu_t val;
 | 
						|
int n;
 | 
						|
{
 | 
						|
	switch (n) {
 | 
						|
	case 1:
 | 
						|
		emit1((int)val); break;
 | 
						|
	case 2:
 | 
						|
		emit2((int)val); break;
 | 
						|
	case 4:
 | 
						|
		emit4((long)val); break;
 | 
						|
	default:
 | 
						|
		assert(0);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
emitstr(zero)
 | 
						|
{
 | 
						|
	register i;
 | 
						|
	register char *p;
 | 
						|
 | 
						|
	p = stringbuf;
 | 
						|
	i = *p++ & 0377;
 | 
						|
	while (--i >= 0)
 | 
						|
		emit1(*p++);
 | 
						|
	if (zero)
 | 
						|
		emit1(0);
 | 
						|
}
 | 
						|
 | 
						|
/* ---------- Error checked file I/O  ---------- */
 | 
						|
 | 
						|
ffreopen(s, f)
 | 
						|
char *s;
 | 
						|
FILE *f;
 | 
						|
{
 | 
						|
	if (freopen(s, "r", f) == NULL)
 | 
						|
		fatal("can't reopen %s", s);
 | 
						|
}
 | 
						|
 | 
						|
FILE *
 | 
						|
ffcreat(s)
 | 
						|
char *s;
 | 
						|
{
 | 
						|
	FILE *f;
 | 
						|
 | 
						|
	if ((f = fopen(s, "w")) == NULL)
 | 
						|
		fatal("can't create %s", s);
 | 
						|
	return(f);
 | 
						|
}
 | 
						|
 | 
						|
#ifndef TMPDIR
 | 
						|
#define TMPDIR "/tmp"
 | 
						|
#endif
 | 
						|
char *tmp_dir = TMPDIR;
 | 
						|
 | 
						|
FILE *
 | 
						|
fftemp(path, tail)
 | 
						|
char *path, *tail;
 | 
						|
{
 | 
						|
	register char *dir;
 | 
						|
 | 
						|
	if ((dir = getenv("TMPDIR")) == NULL)
 | 
						|
		dir = tmp_dir;
 | 
						|
	sprintf(path, "%s/%s", dir, tail);
 | 
						|
	return(ffcreat(mktemp(path)));
 | 
						|
}
 | 
						|
 | 
						|
/* ---------- Error handling ---------- */
 | 
						|
 | 
						|
/*VARARGS*/
 | 
						|
yyerror(){}		/* we will do our own error printing */
 | 
						|
 | 
						|
nosect()
 | 
						|
{
 | 
						|
	fatal("no sections");
 | 
						|
}
 | 
						|
 | 
						|
wr_fatal()
 | 
						|
{
 | 
						|
	fatal("write error");
 | 
						|
}
 | 
						|
 | 
						|
/* VARARGS1 */
 | 
						|
fatal(s, a1, a2, a3, a4)
 | 
						|
char *s;
 | 
						|
{
 | 
						|
	nerrors++;
 | 
						|
	diag(" (fatal)\n", s, a1, a2, a3, a4);
 | 
						|
	stop();
 | 
						|
}
 | 
						|
 | 
						|
#if DEBUG == 2
 | 
						|
assert2(file, line)
 | 
						|
char *file;
 | 
						|
{
 | 
						|
	fatal("assertion failed (%s, %d)", file, line);
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
#if DEBUG == 1
 | 
						|
assert1()
 | 
						|
{
 | 
						|
	diag(" (fatal)\n", "assertion failed");
 | 
						|
	abort();
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/* VARARGS1 */
 | 
						|
serror(s, a1, a2, a3, a4)
 | 
						|
char *s;
 | 
						|
{
 | 
						|
	nerrors++;
 | 
						|
	diag("\n", s, a1, a2, a3, a4);
 | 
						|
}
 | 
						|
 | 
						|
/* VARARGS1 */
 | 
						|
warning(s, a1, a2, a3, a4)
 | 
						|
char *s;
 | 
						|
{
 | 
						|
	diag(" (warning)\n", s, a1, a2, a3, a4);
 | 
						|
}
 | 
						|
 | 
						|
/* VARARGS1 */
 | 
						|
diag(tail, s, a1, a2, a3, a4)
 | 
						|
char *tail, *s;
 | 
						|
{
 | 
						|
	fflush(stdout);
 | 
						|
	if (modulename)
 | 
						|
		fprintf(stderr, "\"%s\", line %ld: ", modulename, lineno);
 | 
						|
	else
 | 
						|
		fprintf(stderr, "%s: ", progname);
 | 
						|
	fprintf(stderr, s, a1, a2, a3, a4);
 | 
						|
	fprintf(stderr, tail);
 | 
						|
}
 | 
						|
 | 
						|
nofit()
 | 
						|
{
 | 
						|
	if (pass == PASS_3)
 | 
						|
		warning("too big");
 | 
						|
}
 |