430 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			430 lines
		
	
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* @(#)comm7.c	1.10 */
 | |
| /*
 | |
|  * miscellaneous
 | |
|  */
 | |
| 
 | |
| #include	"comm0.h"
 | |
| #include	"comm1.h"
 | |
| #include	"y.tab.h"
 | |
| 
 | |
| 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
 | |
| #ifdef DUK
 | |
| 	if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM)) {
 | |
| #else DUK
 | |
| 	if ((ip->i_type & S_TYP) == S_UND) {
 | |
| #endif DUK
 | |
| 		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 = sbrk(MEMINCR);
 | |
| 		if ((int) next == -1)
 | |
| 			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');
 | |
| 	listeoln = 1;
 | |
| 	listcolm = 0;
 | |
| 	listflag = listtemp;
 | |
| }
 | |
| #endif LISTING
 | |
| 
 | |
| /* ---------- code optimization ---------- */
 | |
| 
 | |
| #ifdef THREE_PASS
 | |
| small(fitsmall, gain)
 | |
| {
 | |
| 	register bit;
 | |
| 	register char *p;
 | |
| 
 | |
| 	if (DOTSCT == NULL)
 | |
| 		nosect();
 | |
| 	if (bflag)
 | |
| 		return(0);
 | |
| 	if ((bit = nbits++) >= BITMAX) {
 | |
| 		if (bit != BITMAX)
 | |
| 			nbits--;	/* prevent wraparound */
 | |
| 		else if (pass == PASS_1)
 | |
| 			warning("bit table overflow");
 | |
| 		return(0);
 | |
| 	}
 | |
| 	p = &bittab[bit>>3];
 | |
| 	bit = 1 << (bit&7);
 | |
| 	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);
 | |
| 	}
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /* ---------- output ---------- */
 | |
| 
 | |
| emit1(arg)
 | |
| char arg;
 | |
| {
 | |
| #ifdef LISTING
 | |
| 	if (listeoln) {
 | |
| 		if (listflag & 1) {
 | |
| 			listcolm += printx(VALWIDTH, 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:
 | |
| 		AOUTPART(PARTEMIT);
 | |
| 		while (DOTSCT->s_zero) {
 | |
| 			AOUTPUTC(0, PARTEMIT);
 | |
| 			DOTSCT->s_zero--;
 | |
| 		}
 | |
| 		AOUTPUTC(arg, PARTEMIT);
 | |
| 		break;
 | |
| 	}
 | |
| 	DOTVAL++;
 | |
| }
 | |
| 
 | |
| emit2(arg)
 | |
| short arg;
 | |
| {
 | |
| #ifdef BYTES_REVERSED
 | |
| 	emit1((char)(arg>>8)); emit1((char)arg);
 | |
| #else
 | |
| 	emit1((char)arg); emit1((char)(arg>>8));
 | |
| #endif
 | |
| }
 | |
| 
 | |
| emit4(arg)
 | |
| long arg;
 | |
| {
 | |
| #ifdef WORDS_REVERSED
 | |
| 	emit2((short)(arg>>16)); emit2((short)(arg));
 | |
| #else
 | |
| 	emit2((short)(arg)); emit2((short)(arg>>16));
 | |
| #endif
 | |
| }
 | |
| 
 | |
| emitx(val, n)
 | |
| valu_t val;
 | |
| register n;
 | |
| {
 | |
| 	switch (n) {
 | |
| 	case 1:
 | |
| 		emit1((char)val); break;
 | |
| 	case 2:
 | |
| 		emit2((short)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);
 | |
| }
 | |
| 
 | |
| FILE *
 | |
| fftemp(path, tail)
 | |
| char *path;
 | |
| {
 | |
| 	register char *dir;
 | |
| 
 | |
| 	if ((dir = getenv("TMPDIR")) == NULL)
 | |
| #ifdef TMPDIR
 | |
| 		dir = TMPDIR;
 | |
| #else
 | |
| 		dir = "/tmp";
 | |
| #endif
 | |
| 	sprintf(path, "%s/%s", dir, tail);
 | |
| 	return(ffcreat(mktemp(path)));
 | |
| }
 | |
| 
 | |
| putofmt(p, s, part)
 | |
| register char	*p;
 | |
| register char	*s;
 | |
| {
 | |
| 	register i;
 | |
| 	register long l;
 | |
| 
 | |
| 	AOUTPART(part);
 | |
| 	while (i = *s++) {
 | |
| 		switch (i -= '0') {
 | |
| /*		case 0: p++; break; */
 | |
| 		case 1:
 | |
| 			l = (long) *((char  *)p); p += sizeof(char );
 | |
| 			break;
 | |
| 		case 2:
 | |
| 			l = (long) *((short *)p); p += sizeof(short);
 | |
| 			break;
 | |
| 		case 4:
 | |
| 			l = (long) *((long  *)p); p += sizeof(long );
 | |
| 			break;
 | |
| 		default:
 | |
| 			assert(0);
 | |
| 		}
 | |
| 		while (--i >= 0) {
 | |
| 			AOUTPUTC((int)l, part);
 | |
| 			l >>= 8;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* ---------- Error handling ---------- */
 | |
| 
 | |
| yyerror(){}		/* we will do our own error printing */
 | |
| 
 | |
| nosect()
 | |
| {
 | |
| 	fatal("no sections");
 | |
| }
 | |
| 
 | |
| werror()
 | |
| {
 | |
| 	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 %d: ", 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");
 | |
| }
 |