761 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			761 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|  *
 | |
|  *          This product is part of the Amsterdam Compiler Kit.
 | |
|  *
 | |
|  * Permission to use, sell, duplicate or disclose this software must be
 | |
|  * obtained in writing. Requests for such permissions may be sent to
 | |
|  *
 | |
|  *      Dr. Andrew S. Tanenbaum
 | |
|  *      Wiskundig Seminarium
 | |
|  *      Vrije Universiteit
 | |
|  *      Postbox 7161
 | |
|  *      1007 MC Amsterdam
 | |
|  *      The Netherlands
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #ifndef NORCSID
 | |
| static char rcsid[] = "$Header$";
 | |
| #endif
 | |
| 
 | |
| /*
 | |
|  * Encode to compact EM assembly language
 | |
|  *
 | |
|  * Author: Johan Stevenson, Vrije Universiteit, Amsterdam
 | |
|  */
 | |
| 
 | |
| #include	<stdio.h>
 | |
| #include	<ctype.h>
 | |
| #include	<assert.h>
 | |
| #include	<setjmp.h>
 | |
| #include	<em_spec.h>
 | |
| #include	<em_pseu.h>
 | |
| #include	<em_flag.h>
 | |
| #include	<em_ptyp.h>
 | |
| #include	<em_mes.h>
 | |
| 
 | |
| #define put8(x)		putchar(x)
 | |
| 
 | |
| #define check(x)	if (!(x)) fail_check()
 | |
| 
 | |
| #define fit16i(x)	((x) >= 0xFFFF8000 && (x) <= 0x00007FFF)
 | |
| #define	fit8u(x)	((x) >= 0 && (x) <= 0xFF)
 | |
| 
 | |
| #define	MAXSTR		256
 | |
| #define	HSIZE		256
 | |
| #define	EMPTY		(EOF-1)
 | |
| 
 | |
| /*
 | |
|  * global variables
 | |
|  */
 | |
| 
 | |
| int	opcode;
 | |
| int	offtyp;
 | |
| long	argval;
 | |
| int	dlbval;
 | |
| char	string[MAXSTR];
 | |
| int	strsiz;
 | |
| 
 | |
| int	wsize;
 | |
| int	psize;
 | |
| int	lineno;
 | |
| int	argnum;
 | |
| int	errors;
 | |
| char	*progname;
 | |
| char	*filename = "INPUT";
 | |
| 
 | |
| long	wordmask[] = {	/* allowed bits in a word */
 | |
| 	0x00000000,
 | |
| 	0x000000FF,
 | |
| 	0x0000FFFF,
 | |
| 	0x00000000,
 | |
| 	0xFFFFFFFF
 | |
| };
 | |
| 
 | |
| long	sizemask[] = {	/* allowed bits in multiples of 'wsize' */
 | |
| 	0x00000000,
 | |
| 	0x7FFFFFFF,
 | |
| 	0x7FFFFFFE,
 | |
| 	0x00000000,
 | |
| 	0x7FFFFFFC
 | |
| };
 | |
| 
 | |
| int	peekc = EMPTY;
 | |
| int	hashtab[HSIZE];
 | |
| jmp_buf	recover;
 | |
| 
 | |
| /*
 | |
|  * external tables
 | |
|  */
 | |
| 
 | |
| extern	char	em_flag[];
 | |
| extern	short	em_ptyp[];
 | |
| extern	char	em_mnem[][4];
 | |
| extern	char	em_pseu[][4];
 | |
| 
 | |
| int main(argc,argv) char **argv; {
 | |
| 
 | |
| 	progname = argv[0];
 | |
| 	if (argc >= 2) {
 | |
| 		filename = argv[1];
 | |
| 		if (freopen(filename,"r",stdin) == NULL)
 | |
| 			fatal("can't open %s",filename);
 | |
| 	}
 | |
| 	if (argc >= 3)
 | |
| 		if (freopen(argv[2],"w",stdout) == NULL)
 | |
| 			fatal("can't create %s",argv[2]);
 | |
| 	init();
 | |
| 	put16(sp_magic);
 | |
| 	setjmp(recover);
 | |
| 	while (nextline())
 | |
| 		;
 | |
| 	return(errors ? -1 : 0);
 | |
| }
 | |
| 
 | |
| /* ----- copy ----- */
 | |
| 
 | |
| int nextline() {
 | |
| 	register c,i;
 | |
| 
 | |
| 	lineno++;
 | |
| 	argnum = 1;
 | |
| 	c = nextchar();
 | |
| 	if (c == EOF)
 | |
| 		return(0);
 | |
| 	if (isspace(c) && c != '\n') {
 | |
| 		c = nospace();
 | |
| 		if (isalpha(c)) {
 | |
| 			inmnem(c);
 | |
| 			if (opcode <= sp_lmnem)
 | |
| 				instr();
 | |
| 			else
 | |
| 				pseudo();
 | |
| 		} else
 | |
| 			peekc = c;
 | |
| 	} else if (c == '#') {
 | |
| 		line_line();
 | |
| 	} else {
 | |
| 		peekc = c;
 | |
| 		i = gettyp(sym_ptyp | ptyp(sp_cst2) | ptyp(sp_cend));
 | |
| 		switch (i) {
 | |
| 		case sp_cst2:
 | |
| 			i = (int) argval;
 | |
| 			if (i >= 0 && i < sp_nilb0)
 | |
| 				put8(i + sp_filb0);
 | |
| 			else
 | |
| 				putarg(sp_ilb2);
 | |
| 			break;
 | |
| 		case sp_dlb2:
 | |
| 		case sp_dnam:
 | |
| 			putarg(i);
 | |
| 			break;
 | |
| 		case sp_cend:
 | |
| 			break;
 | |
| 		}
 | |
| 	}
 | |
| 	if (nospace() != '\n')
 | |
| 		syntax("end of line expected");
 | |
| 	return(1);
 | |
| }
 | |
| 
 | |
| instr() {
 | |
| 	register i,j,t;
 | |
| 	register long l;
 | |
| 
 | |
| 	i = opcode;
 | |
| 	put8(i);
 | |
| 	i -= sp_fmnem;
 | |
| 	j = em_flag[i] & EM_PAR;
 | |
| 	if (j == PAR_NO)
 | |
| 		return;
 | |
| 	t = em_ptyp[j];
 | |
| 	if (j == PAR_B)
 | |
| 		t = ptyp(sp_ilb2);
 | |
| 	t = getarg(t);
 | |
| 	/*
 | |
| 	 * range checking
 | |
| 	 */
 | |
| 	switch (j) {
 | |
| 	case PAR_N:
 | |
| 		check(argval >= 0);
 | |
| 		break;
 | |
| 	case PAR_G:
 | |
| 		if (t != sp_cst2 && t != sp_cst4)
 | |
| 			break;
 | |
| 		check(argval >= 0);
 | |
| 		/* fall through */
 | |
| 	case PAR_L:
 | |
| 		l = argval >= 0 ? argval : -argval;
 | |
| 		check((l & ~wordmask[psize]) == 0);
 | |
| 		break;
 | |
| 	case PAR_W:
 | |
| 		if (t == sp_cend)
 | |
| 			break;
 | |
| 		check((argval & ~wordmask[wsize]) == 0);
 | |
| 		/* fall through */
 | |
| 	case PAR_S:
 | |
| 		check(argval != 0);
 | |
| 		/* fall through */
 | |
| 	case PAR_Z:
 | |
| 		check((argval & ~sizemask[wsize]) == 0);
 | |
| 		break;
 | |
| 	case PAR_O:
 | |
| 		check(argval != 0);
 | |
| 		check((argval & ~sizemask[wsize])==0 || (wsize % argval)==0);
 | |
| 		break;
 | |
| 	case PAR_B:
 | |
| 		t = sp_cst2;
 | |
| 		break;
 | |
| 	case PAR_R:
 | |
| 		check(argval >= 0 && argval <= 2);
 | |
| 		break;
 | |
| 	}
 | |
| 	putarg(t);
 | |
| }
 | |
| 
 | |
| pseudo() {
 | |
| 	register i,t;
 | |
| 
 | |
| 	i = opcode;
 | |
| 	put8(i);
 | |
| 	switch (i) {
 | |
| 	case ps_bss:
 | |
| 	case ps_hol:
 | |
| 		putarg(getarg(cst_ptyp));
 | |
| 		putarg(getarg(val_ptyp));
 | |
| 		putarg(getarg(ptyp(sp_cst2)));
 | |
| 		check(argval==0 || argval==1);
 | |
| 		break;
 | |
| 	case ps_rom:
 | |
| 	case ps_con:
 | |
| 		putarg(getarg(val_ptyp));
 | |
| 		do
 | |
| 			putarg(t = getarg(any_ptyp));
 | |
| 		while (t != sp_cend);
 | |
| 		break;
 | |
| 	case ps_mes:
 | |
| 		putarg(getarg(ptyp(sp_cst2)));
 | |
| 		if (argval == ms_emx) {
 | |
| 			putarg(getarg(ptyp(sp_cst2)));
 | |
| 			check(argval > 0 && argval <= 4);
 | |
| 			wsize = (int) argval;
 | |
| 			putarg(getarg(ptyp(sp_cst2)));
 | |
| 			check(argval > 0 && argval <= 4);
 | |
| 			psize = (int) argval;
 | |
| 		}
 | |
| 		do
 | |
| 			putarg(t = getarg(any_ptyp));
 | |
| 		while (t != sp_cend);
 | |
| 		break;
 | |
| 	case ps_exa:
 | |
| 	case ps_ina:
 | |
| 		putarg(getarg(sym_ptyp));
 | |
| 		break;
 | |
| 	case ps_exp:
 | |
| 	case ps_inp:
 | |
| 		putarg(getarg(ptyp(sp_pnam)));
 | |
| 		break;
 | |
| 	case ps_exc:
 | |
| 		putarg(getarg(ptyp(sp_cst2)));
 | |
| 		putarg(getarg(ptyp(sp_cst2)));
 | |
| 		break;
 | |
| 	case ps_pro:
 | |
| 		putarg(getarg(ptyp(sp_pnam)));
 | |
| 		putarg(getarg(cst_ptyp|ptyp(sp_cend)));
 | |
| 		break;
 | |
| 	case ps_end:
 | |
| 		putarg(getarg(cst_ptyp|ptyp(sp_cend)));
 | |
| 		break;
 | |
| 	default:
 | |
| 		syntax("bad pseudo %d",i);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* ----- input ----- */
 | |
| 
 | |
| int getarg(typset) {
 | |
| 	register c;
 | |
| 
 | |
| 	if (argnum != 1) {
 | |
| 		c = nospace();
 | |
| 		if (c != ',') {
 | |
| 			if (c != '\n')
 | |
| 				syntax("comma expected");
 | |
| 			peekc = c;
 | |
| 		}
 | |
| 	}
 | |
| 	argnum++;
 | |
| 	return(gettyp(typset));
 | |
| }
 | |
| 
 | |
| int gettyp(typset) {
 | |
| 	register c,t,sp;
 | |
| 
 | |
| 	c = nospace();
 | |
| 	if (c == '\n') {
 | |
| 		peekc = c;
 | |
| 		sp = sp_cend;
 | |
| 	} else if (isdigit(c) || c == '+' || c == '-' || c == '(') {
 | |
| 		sp = inexpr1(c);
 | |
| 		if (sp == sp_cst4 && fit16i(argval))
 | |
| 			sp = sp_cst2;
 | |
| 	} else if (isalpha(c)) {
 | |
| 		inname(c);
 | |
| 		sp = offsetted(sp_dnam);
 | |
| 	} else if (c == '.') {
 | |
| 		in15u();
 | |
| 		dlbval = (int) argval;
 | |
| 		sp = offsetted(sp_dlb2);
 | |
| 	} else if (c == '*') {
 | |
| 		in15u();
 | |
| 		sp = sp_ilb2;
 | |
| 	} else if (c == '$') {
 | |
| 		inname(nextchar());
 | |
| 		sp = sp_pnam;
 | |
| 	} else if (c == '"' || c == '\'') {
 | |
| 		sp = instring(c);
 | |
| 	} else if (c == '?') {
 | |
| 		sp = sp_cend;
 | |
| 	} else
 | |
| 		syntax("operand expected");
 | |
| 	t = sp - sp_fspec;
 | |
| 	assert(t >= 0 && t < 16);
 | |
| 	t = 1 << t;
 | |
| 	if ((typset & t) == 0)
 | |
| 		error("bad argument type %d",sp);
 | |
| 	return(sp);
 | |
| }
 | |
| 
 | |
| int offsetted(sp) {
 | |
| 	register c;
 | |
| 
 | |
| 	c = nospace();
 | |
| 	if (c == '+' || c == '-') {
 | |
| 		gettyp(cst_ptyp);
 | |
| 		if (c == '-')
 | |
| 			argval = -argval;
 | |
| 		offtyp = sp;
 | |
| 		return(sp_doff);
 | |
| 	}
 | |
| 	peekc = c;
 | |
| 	return(sp);
 | |
| }
 | |
| 
 | |
| inname(c) register c; {
 | |
| 	register char *p;
 | |
| 
 | |
| 	if (isalpha(c) == 0)
 | |
| 		syntax("letter expected");
 | |
| 	p = string;
 | |
| 	do {
 | |
| 		if (p < &string[MAXSTR-1])
 | |
| 			*p++ = c;
 | |
| 		c = nextchar();
 | |
| 	} while (isalnum(c));
 | |
| 	peekc = c;
 | |
| 	*p = '\0';
 | |
| 	strsiz = p - string;
 | |
| }
 | |
| 
 | |
| int inmnem(c) register c; {
 | |
| 	register unsigned h;
 | |
| 	register i;
 | |
| 
 | |
| 	inname(c);
 | |
| 	h = hash(string);
 | |
| 	for (;;) {
 | |
| 		h++;
 | |
| 		h %= HSIZE;
 | |
| 		i = hashtab[h];
 | |
| 		if (i == 0)
 | |
| 			syntax("bad mnemonic");
 | |
| 		if (i <= sp_lmnem) {
 | |
| 			assert(i >= sp_fmnem);
 | |
| 			if (strcmp(string,em_mnem[i - sp_fmnem]) != 0)
 | |
| 				continue;
 | |
| 			return(opcode = i);
 | |
| 		}
 | |
| 		assert(i <= sp_lpseu && i >= sp_fpseu);
 | |
| 		if (strcmp(string,em_pseu[i - sp_fpseu]) != 0)
 | |
| 			continue;
 | |
| 		return(opcode = i);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int inexpr1(c) register c; {
 | |
| 	long left;
 | |
| 
 | |
| 	if ((c = inexpr2(c)) != sp_cst4)
 | |
| 		return(c);
 | |
| 	for (;;) {
 | |
| 		c = nospace();
 | |
| 		if (c != '+' && c != '-') {
 | |
| 			peekc = c;
 | |
| 			break;
 | |
| 		}
 | |
| 		left = argval;
 | |
| 		if (inexpr2(nospace()) != sp_cst4)
 | |
| 			syntax("term expected");
 | |
| 		if (c == '+')
 | |
| 			argval += left;
 | |
| 		else
 | |
| 			argval = left - argval;
 | |
| 	}
 | |
| 	return(sp_cst4);
 | |
| }
 | |
| 
 | |
| int inexpr2(c) register c; {
 | |
| 	long left;
 | |
| 
 | |
| 	if ((c = inexpr3(c)) != sp_cst4)
 | |
| 		return(c);
 | |
| 	for (;;) {
 | |
| 		c = nospace();
 | |
| 		if (c != '*' && c != '/' && c != '%') {
 | |
| 			peekc = c;
 | |
| 			break;
 | |
| 		}
 | |
| 		left = argval;
 | |
| 		if (inexpr3(nospace()) != sp_cst4)
 | |
| 			syntax("factor expected");
 | |
| 		if (c == '*')
 | |
| 			argval *= left;
 | |
| 		else if (c == '/')
 | |
| 			argval = left / argval;
 | |
| 		else
 | |
| 			argval = left % argval;
 | |
| 	}
 | |
| 	return(sp_cst4);
 | |
| }
 | |
| 
 | |
| inexpr3(c) register c; {
 | |
| 
 | |
| 	if (c == '(') {
 | |
| 		if (inexpr1(nospace()) != sp_cst4)
 | |
| 			syntax("expression expected");
 | |
| 		if (nospace() != ')')
 | |
| 			syntax("')' expected");
 | |
| 		return(sp_cst4);
 | |
| 	}
 | |
| 	return(innumber(c));
 | |
| }
 | |
| 
 | |
| int innumber(c) register c; {
 | |
| 	register char *p;
 | |
| 	register n;
 | |
| 	int expsign;
 | |
| 	static char numstr[MAXSTR];
 | |
| 	long atol();
 | |
| 
 | |
| 	p = numstr;
 | |
| 	expsign = 0;
 | |
| 	if (c == '+' || c == '-') {
 | |
| 		if (c == '-')
 | |
| 			*p++ = c;
 | |
| 		c = nextchar();
 | |
| 	}
 | |
| 	if (isdigit(c) == 0)
 | |
| 		syntax("digit expected");
 | |
| 	n = sp_cst4;
 | |
| 	for (;;) {
 | |
| 		if (p >= &numstr[MAXSTR-1])
 | |
| 			fatal("number too long");
 | |
| 		*p++ = c;
 | |
| 		c = nextchar();
 | |
| 		if (c == '.' || c == 'e' || c == 'E') {
 | |
| 			expsign = c != '.';
 | |
| 			n = sp_fcon;
 | |
| 			continue;
 | |
| 		}
 | |
| 		if (expsign) {
 | |
| 			expsign = 0;
 | |
| 			if (c == '+' || c == '-')
 | |
| 				continue;
 | |
| 		}
 | |
| 		if (isdigit(c) == 0)
 | |
| 			break;
 | |
| 	}
 | |
| 	peekc = c;
 | |
| 	*p = '\0';
 | |
| 	c = nospace();
 | |
| 	if (n == sp_fcon && c != 'F')
 | |
| 		syntax("'F' expected");
 | |
| 	if (c == 'I' || c == 'U' || c == 'F')
 | |
| 		return(incon(numstr,c));
 | |
| 	peekc = c;
 | |
| 	argval = atol(numstr);
 | |
| 	return(sp_cst4);
 | |
| }
 | |
| 
 | |
| in15u() {
 | |
| 
 | |
| 	if (innumber(nextchar()) != sp_cst4)
 | |
| 		syntax("integer expected");
 | |
| 	check((argval & ~077777) == 0);
 | |
| }
 | |
| 
 | |
| int incon(p,c) register char *p; {
 | |
| 	register char *q;
 | |
| 
 | |
| 	q = string;
 | |
| 	while (*q++ = *p++)
 | |
| 		;
 | |
| 	strsiz = q - string - 1;
 | |
| 	gettyp(cst_ptyp);
 | |
| 	return(c == 'I' ? sp_icon : (c == 'U' ? sp_ucon : sp_fcon));
 | |
| }
 | |
| 
 | |
| int instring(termc) {
 | |
| 	register char *p;
 | |
| 	register c;
 | |
| 
 | |
| 	p = string;
 | |
| 	for (;;) {
 | |
| 		c = nextchar();
 | |
| 		if (c == '\n' || c == EOF) {
 | |
| 			peekc = c;
 | |
| 			syntax("non-terminated string");
 | |
| 		}
 | |
| 		if (c == termc) {
 | |
| 			if (termc == '"')
 | |
| 				*p++ = '\0';
 | |
| 			break;
 | |
| 		}
 | |
| 		if (c == '\\')
 | |
| 			c = inescape();
 | |
| 		if (p >= &string[MAXSTR-1])
 | |
| 			fatal("string too long");
 | |
| 		*p++ = c;
 | |
| 	}
 | |
| 	strsiz = p - string;
 | |
| 	return(sp_scon);
 | |
| }
 | |
| 
 | |
| int inescape() {
 | |
| 	register c,j,r;
 | |
| 
 | |
| 	c = nextchar();
 | |
| 	if (c >= '0' && c <= '7') {
 | |
| 		r = c - '0';
 | |
| 		for (j = 0; j < 2; j++) {
 | |
| 			c = nextchar();
 | |
| 			if (c < '0' || c > '7') {
 | |
| 				peekc = c;
 | |
| 				return(r);
 | |
| 			}
 | |
| 			r <<= 3;
 | |
| 			r += (c - '0');
 | |
| 		}
 | |
| 		return(r);
 | |
| 	}
 | |
| 	switch (c) {
 | |
| 	case 'b':	return('\b');
 | |
| 	case 'f':	return('\f');
 | |
| 	case 'n':	return('\n');
 | |
| 	case 'r':	return('\r');
 | |
| 	case 't':	return('\t');
 | |
| 	}
 | |
| 	return(c);
 | |
| }
 | |
| 
 | |
| int nospace() {
 | |
| 	register c;
 | |
| 
 | |
| 	do
 | |
| 		c = nextchar();
 | |
| 	while (isspace(c) && c != '\n');
 | |
| 	if (c == ';')
 | |
| 		do
 | |
| 			c = nextchar();
 | |
| 		while (c != '\n' && c != EOF);
 | |
| 	return(c);
 | |
| }
 | |
| 
 | |
| int nextchar() {
 | |
| 	register c;
 | |
| 
 | |
| 	if (peekc != EMPTY) {
 | |
| 		c = peekc;
 | |
| 		peekc = EMPTY;
 | |
| 		return(c);
 | |
| 	}
 | |
| 	c = getchar();
 | |
| 	if (isascii(c) == 0 && c != EOF)
 | |
| 		fatal("non-ascii char");
 | |
| 	return(c);
 | |
| }
 | |
| 
 | |
| line_line() {
 | |
| 	register char *p,*q;
 | |
| 	static char filebuff[MAXSTR+1];
 | |
| 
 | |
| 	gettyp(ptyp(sp_cst2));
 | |
| 	lineno = (int) (argval-1);
 | |
| 	gettyp(ptyp(sp_scon));
 | |
| 	p = string;
 | |
| 	q = filebuff;
 | |
| 	while (--strsiz >= 0)
 | |
| 		*q++ = *p++;
 | |
| 	*q = '\0';
 | |
| 	filename = filebuff;
 | |
| }
 | |
| 
 | |
| init() {
 | |
| 	register i;
 | |
| 
 | |
| 	for (i = sp_fmnem; i <= sp_lmnem; i++)
 | |
| 		pre_hash(i,em_mnem[i - sp_fmnem]);
 | |
| 	for (i = sp_fpseu; i <= sp_lpseu; i++)
 | |
| 		pre_hash(i,em_pseu[i - sp_fpseu]);
 | |
| 	/* treat '_' as letter */
 | |
| 	/* In System III the array is called _ctype[] without the trailing '_' */
 | |
| 	(_ctype_+1)['_'] = (_ctype_+1)['a'];
 | |
| }
 | |
| 
 | |
| pre_hash(i,s) char *s; {
 | |
| 	register unsigned h;
 | |
| 
 | |
| 	assert(i != 0);
 | |
| 	h = hash(s);
 | |
| 	for (;;) {
 | |
| 		h++;
 | |
| 		h %= HSIZE;
 | |
| 		if (hashtab[h] == 0) {
 | |
| 			hashtab[h] = i;
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int hash(s) register char *s; {
 | |
| 	register h;
 | |
| 
 | |
| 	h = 0;
 | |
| 	while (*s) {
 | |
| 		h <<= 1;
 | |
| 		h += *s++;
 | |
| 	}
 | |
| 	return(h);
 | |
| }
 | |
| 
 | |
| /* ----- output ----- */
 | |
| 
 | |
| putarg(sp) register sp; {
 | |
| 	register i;
 | |
| 
 | |
| 	switch (sp) {
 | |
| 	case sp_ilb2:
 | |
| 		i = (int) argval;
 | |
| 		if (fit8u(i)) {
 | |
| 			put8(sp_ilb1);
 | |
| 			put8(i);
 | |
| 			break;
 | |
| 		}
 | |
| 		put8(sp);
 | |
| 		put16(i);
 | |
| 		break;
 | |
| 	case sp_dlb2:
 | |
| 		i = dlbval;
 | |
| 		if (fit8u(i)) {
 | |
| 			put8(sp_dlb1);
 | |
| 			put8(i);
 | |
| 			break;
 | |
| 		}
 | |
| 		put8(sp);
 | |
| 		put16(i);
 | |
| 		break;
 | |
| 	case sp_cst2:
 | |
| 	case sp_cst4:
 | |
| 		if (fit16i(argval) == 0) {
 | |
| 			put8(sp_cst4);
 | |
| 			put32(argval);
 | |
| 			break;
 | |
| 		}
 | |
| 		i = (int) argval;
 | |
| 		if (i >= -sp_zcst0 && i < sp_ncst0 - sp_zcst0) {
 | |
| 			put8(i + sp_zcst0 + sp_fcst0);
 | |
| 			break;
 | |
| 		}
 | |
| 		put8(sp_cst2);
 | |
| 		put16(i);
 | |
| 		break;
 | |
| 	case sp_doff:
 | |
| 		put8(sp);
 | |
| 		putarg(offtyp);
 | |
| 		putarg(sp_cst4);
 | |
| 		break;
 | |
| 	case sp_dnam:
 | |
| 	case sp_pnam:
 | |
| 	case sp_scon:
 | |
| 		put8(sp);
 | |
| 		putstr();
 | |
| 		break;
 | |
| 	case sp_icon:
 | |
| 	case sp_ucon:
 | |
| 	case sp_fcon:
 | |
| 		put8(sp);
 | |
| 		putarg(sp_cst4);
 | |
| 		putstr();
 | |
| 		break;
 | |
| 	case sp_cend:
 | |
| 		put8(sp);
 | |
| 		break;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| putstr() {
 | |
| 	register char *p;
 | |
| 	long consiz;
 | |
| 
 | |
| 	consiz = argval;
 | |
| 	argval = strsiz;
 | |
| 	putarg(sp_cst4);
 | |
| 	argval = consiz;
 | |
| 	p = string;
 | |
| 	while (--strsiz >= 0)
 | |
| 		put8(*p++);
 | |
| }
 | |
| 
 | |
| put16(w) int w; {
 | |
| 
 | |
| 	put8(w);
 | |
| 	put8(w >> 8);
 | |
| }
 | |
| 
 | |
| put32(f) long f; {
 | |
| 
 | |
| 	put16((int) f);
 | |
| 	put16((int)(f >> 16));
 | |
| }
 | |
| 
 | |
| /* ----- error handling ----- */
 | |
| 
 | |
| fail_check() {
 | |
| 	error("argument range error");
 | |
| }
 | |
| 
 | |
| /* VARARGS */
 | |
| error(s,a1,a2,a3,a4) char *s; {
 | |
| 	fprintf(stderr,"%s: line %d: ", filename, lineno);
 | |
| 	fprintf(stderr,s,a1,a2,a3,a4);
 | |
| 	fprintf(stderr,"\n");
 | |
| 	errors++;
 | |
| }
 | |
| 
 | |
| /* VARARGS */
 | |
| fatal(s,a1,a2,a3,a4) char *s; {
 | |
| 	error(s,a1,a2,a3,a4);
 | |
| 	exit(-1);
 | |
| }
 | |
| 
 | |
| /* VARARGS */
 | |
| syntax(s,a1,a2,a3,a4) char *s; {
 | |
| 	register c;
 | |
| 
 | |
| 	error(s,a1,a2,a3,a4);
 | |
| 	do
 | |
| 		c = nextchar();
 | |
| 	while (c != '\n' && c != EOF);
 | |
| 	longjmp(recover);
 | |
| }
 |