521 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			521 lines
		
	
	
	
		
			8.1 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".
 | |
|  */
 | |
| /* @(#)comm5.c	1.1 */
 | |
| 
 | |
| #include	"comm0.h"
 | |
| #include	"comm1.h"
 | |
| #include	"y.tab.h"
 | |
| 
 | |
| extern YYSTYPE	yylval;
 | |
| 
 | |
| yylex()
 | |
| {
 | |
| 	register c;
 | |
| 
 | |
| 	if (pass == PASS_1) {
 | |
| 		/* scan the input file */
 | |
| 		do
 | |
| 			c = nextchar();
 | |
| 		while (isspace(c) && c != '\n');
 | |
| 		if (ISALPHA(c))
 | |
| 			c = inident(c);
 | |
| 		else if (isdigit(c))
 | |
| 			c = innumber(c);
 | |
| 		else switch (c) {
 | |
| 		case '=':
 | |
| 		case '<':
 | |
| 		case '>':
 | |
| 		case '|':
 | |
| 		case '&':
 | |
| 			c = induo(c); break;
 | |
| 		case ASC_SQUO:
 | |
| 		case ASC_DQUO:
 | |
| 			c = instring(c); break;
 | |
| 		case ASC_COMM:
 | |
| 			do
 | |
| 				c = nextchar();
 | |
| 			while (c != '\n' && c != '\0');
 | |
| 			break;
 | |
| 		case CTRL('A'):
 | |
| 			c = CODE1; readcode(1); break;
 | |
| 		case CTRL('B'):
 | |
| 			c = CODE2; readcode(2); break;
 | |
| 		case CTRL('C'):
 | |
| 			c = CODE4; readcode(4); break;
 | |
| 		}
 | |
| 
 | |
| 		/* produce the intermediate token file */
 | |
| 		if (c <= 0)
 | |
| 			return(0);
 | |
| 		if (c <= 127)
 | |
| 			putc(c, tempfile);
 | |
| 		else
 | |
| 			putval(c);
 | |
| 	} else {
 | |
| 		/* read from intermediate token file */
 | |
| 		c = getc(tempfile);
 | |
| 		if (c == EOF)
 | |
| 			return(0);
 | |
| 		if (c > 127) {
 | |
| 			c += 128;
 | |
| 			c = getval(c);
 | |
| 		}
 | |
| 	}
 | |
| 	return(c);
 | |
| }
 | |
| 
 | |
| putval(c)
 | |
| {
 | |
| 	register valu_t v;
 | |
| 	register n;
 | |
| 	register char *p;
 | |
| 
 | |
| 	assert(c >= 256 && c < 256+128);
 | |
| 	switch (c) {
 | |
| 	case CODE1:
 | |
| 		n = 1; goto putnum;
 | |
| 	case CODE2:
 | |
| 		n = 2; goto putnum;
 | |
| 	case CODE4:
 | |
| 		n = 4; goto putnum;
 | |
| 	case NUMBER:
 | |
| 		v = yylval.y_valu;
 | |
| 		for (n = 0; n < sizeof(v); n++) {
 | |
| 			if (v == 0)
 | |
| 				break;
 | |
| 			v >>= 8;
 | |
| 		}
 | |
| 		c = NUMBER0 + n;
 | |
| 	putnum:
 | |
| 		putc(c-128, tempfile);
 | |
| 		v = yylval.y_valu;
 | |
| 		while (--n >= 0)
 | |
| 			putc((int) (v >> (n*8)), tempfile);
 | |
| 		return;
 | |
| 	case IDENT:
 | |
| 	case FBSYM:
 | |
| 		n = sizeof(item_t *);
 | |
| 		p = (char *) &yylval.y_item; break;
 | |
| #ifdef ASLD
 | |
| 	case MODULE:
 | |
| 		n = sizeof(char *);
 | |
| 		p = (char *) &yylval.y_strp; break;
 | |
| #endif
 | |
| 	case STRING:
 | |
| 		p = stringbuf;
 | |
| 		n = (*p & 0377) + 1; break;
 | |
| 	case OP_EQ:
 | |
| 	case OP_NE:
 | |
| 	case OP_LE:
 | |
| 	case OP_GE:
 | |
| 	case OP_LL:
 | |
| 	case OP_RR:
 | |
| 	case OP_OO:
 | |
| 	case OP_AA:
 | |
| 		n = 0; break;
 | |
| 	default:
 | |
| 		n = sizeof(word_t);
 | |
| 		p = (char *) &yylval.y_word; break;
 | |
| 	}
 | |
| 	putc(c-128, tempfile);
 | |
| 	while (--n >= 0)
 | |
| 		putc(*p++, tempfile);
 | |
| }
 | |
| 
 | |
| getval(c)
 | |
| {
 | |
| 	register n;
 | |
| 	register valu_t v;
 | |
| 	register char *p;
 | |
| 
 | |
| 	switch (c) {
 | |
| 	case CODE1:
 | |
| 		n = 1; goto getnum;
 | |
| 	case CODE2:
 | |
| 		n = 2; goto getnum;
 | |
| 	case CODE4:
 | |
| 		n = 4; goto getnum;
 | |
| 	case NUMBER0:
 | |
| 		n = 0; c = NUMBER; goto getnum;
 | |
| 	case NUMBER1:
 | |
| 		n = 1; c = NUMBER; goto getnum;
 | |
| 	case NUMBER2:
 | |
| 		n = 2; c = NUMBER; goto getnum;
 | |
| 	case NUMBER3:
 | |
| 		n = 3; c = NUMBER; goto getnum;
 | |
| 	case NUMBER:
 | |
| 		n = 4;
 | |
| 	getnum:
 | |
| 		v = 0;
 | |
| 		while (--n >= 0) {
 | |
| 			v <<= 8;
 | |
| 			v |= getc(tempfile);
 | |
| 		}
 | |
| 		yylval.y_valu = v;
 | |
| 		return(c);
 | |
| 	case IDENT:
 | |
| 	case FBSYM:
 | |
| 		n = sizeof(item_t *);
 | |
| 		p = (char *) &yylval.y_item; break;
 | |
| #ifdef ASLD
 | |
| 	case MODULE:
 | |
| 		n = sizeof(char *);
 | |
| 		p = (char *) &yylval.y_strp; break;
 | |
| #endif
 | |
| 	case STRING:
 | |
| 		p = stringbuf;
 | |
| 		*p++ = n = getc(tempfile); p[n] = '\0'; break;
 | |
| 	case OP_EQ:
 | |
| 	case OP_NE:
 | |
| 	case OP_LE:
 | |
| 	case OP_GE:
 | |
| 	case OP_LL:
 | |
| 	case OP_RR:
 | |
| 	case OP_OO:
 | |
| 	case OP_AA:
 | |
| 		n = 0; break;
 | |
| 	default:
 | |
| 		n = sizeof(word_t);
 | |
| 		p = (char *) &yylval.y_word; break;
 | |
| 	}
 | |
| 	while (--n >= 0)
 | |
| 		*p++ = getc(tempfile);
 | |
| 	return(c);
 | |
| }
 | |
| 
 | |
| /* ---------- lexical scan in pass 1 ---------- */
 | |
| 
 | |
| nextchar()
 | |
| {
 | |
| 	register c;
 | |
| 
 | |
| 	if (peekc != -1) {
 | |
| 		c = peekc;
 | |
| 		peekc = -1;
 | |
| 		return(c);
 | |
| 	}
 | |
| #ifdef ASLD
 | |
| 	if (archmode && --archsize < 0)
 | |
| 		return(0);
 | |
| #endif
 | |
| 	if ((c = getc(input)) == EOF)
 | |
| 		return(0);
 | |
| 	if (isascii(c) == 0)
 | |
| 		fatal("non-ascii character");
 | |
| #ifdef LISTING
 | |
| 	if (listflag & 0440)
 | |
| 		putc(c, listfile);
 | |
| #endif
 | |
| 	return(c);
 | |
| }
 | |
| 
 | |
| readcode(n)
 | |
| {
 | |
| 	register c;
 | |
| 
 | |
| 	yylval.y_valu = 0;
 | |
| 	do {
 | |
| 		if (
 | |
| #ifdef ASLD
 | |
| 			(archmode && --archsize < 0)
 | |
| 			||
 | |
| #endif
 | |
| 			(c = getc(input)) == EOF
 | |
| 		)
 | |
| 			fatal("unexpected EOF in compact input");
 | |
| 		yylval.y_valu <<= 8;
 | |
| 		yylval.y_valu |= c;
 | |
| 	} while (--n);
 | |
| }
 | |
| 
 | |
| induo(c)
 | |
| register c;
 | |
| {
 | |
| 	static short duo[] = {
 | |
| 		('='<<8) | '=', OP_EQ,
 | |
| 		('<'<<8) | '>', OP_NE,
 | |
| 		('<'<<8) | '=', OP_LE,
 | |
| 		('>'<<8) | '=', OP_GE,
 | |
| 		('<'<<8) | '<', OP_LL,
 | |
| 		('>'<<8) | '>', OP_RR,
 | |
| 		('|'<<8) | '|', OP_OO,
 | |
| 		('&'<<8) | '&', OP_AA,
 | |
| 	};
 | |
| 	register short *p;
 | |
| 
 | |
| 	c = (c<<8) | nextchar();
 | |
| 	for (p = duo; *p; p++)
 | |
| 		if (*p++ == c)
 | |
| 			return(*p++);
 | |
| 	peekc = c & 0377;
 | |
| 	return(c>>8);
 | |
| }
 | |
| 
 | |
| inident(c)
 | |
| char c;
 | |
| {
 | |
| 	register char *p;
 | |
| 	register item_t *ip;
 | |
| 
 | |
| 	p = readident(c);
 | |
| 	ip = item_search(p);
 | |
| 	if (ip == 0) {
 | |
| 		ip = item_alloc(S_UND);
 | |
| 		ip->i_name = remember(p);
 | |
| 		/* printf("ident %s %o\n", ip->i_name, ip); */
 | |
| 		unresolved++;
 | |
| 		item_insert(ip, H_LOCAL + (hashindex%H_SIZE));
 | |
| 	} else if (hashindex < H_SIZE) {
 | |
| 		assert(H_KEY == 0);
 | |
| 		yylval.y_word = (word_t) ip->i_valu;
 | |
| 		return(ip->i_type);
 | |
| 	}
 | |
| 	yylval.y_item = ip;
 | |
| 	return(IDENT);
 | |
| }
 | |
| 
 | |
| char *
 | |
| readident(c)
 | |
| register c;
 | |
| {
 | |
| 	static char name[NAMEMAX+1];
 | |
| 	register n = NAMEMAX;
 | |
| 	register char *p = name;
 | |
| 
 | |
| 	do {
 | |
| 		if (--n >= 0)
 | |
| 			*p++ = c;
 | |
| 		c = nextchar();
 | |
| 	} while (ISALNUM(c));
 | |
| 	*p++ = '\0';
 | |
| 	peekc = c;
 | |
| 	return(name);
 | |
| }
 | |
| 
 | |
| innumber(c)
 | |
| register c;
 | |
| {
 | |
| 	register char *p;
 | |
| 	register radix;
 | |
| 	static char num[20+1];
 | |
| 
 | |
| 	p = num;
 | |
| 	radix = 20;
 | |
| 	do {
 | |
| 		if (--radix < 0)
 | |
| 			fatal("number too long");
 | |
| 		if (isupper(c))
 | |
| 			c += ('a' - 'A');
 | |
| 		*p++ = c;
 | |
| 		c = nextchar();
 | |
| 	} while (ISALNUM(c));
 | |
| 	peekc = c;
 | |
| 	*p = '\0';
 | |
| 	c = *--p;
 | |
| 	p = num;
 | |
| 	radix = 10;
 | |
| 	if (*p == '0') {
 | |
| 		radix = 8;
 | |
| 		p++;
 | |
| 		if (*p == 'x') {
 | |
| 			radix = 16;
 | |
| 			p++;
 | |
| 		} else if (*p == 'b') {
 | |
| 			radix = 2;
 | |
| 			p++;
 | |
| 		}
 | |
| 	}
 | |
| 	if (radix != 16 && (c == 'f' || c == 'b'))
 | |
| 		return(infbsym(num));
 | |
| 	yylval.y_valu = 0;
 | |
| 	while (c = *p++) {
 | |
| 		if (c > '9')
 | |
| 			c -= ('a' - '9' - 1);
 | |
| 		c -= '0';
 | |
| 		if (c >= radix)
 | |
| 			serror("digit exceeds radix");
 | |
| 		yylval.y_valu = yylval.y_valu * radix + c;
 | |
| 	}
 | |
| 	return(NUMBER);
 | |
| }
 | |
| 
 | |
| instring(termc)
 | |
| {
 | |
| 	register char *p;
 | |
| 	register c;
 | |
| 
 | |
| 	p = stringbuf+1;
 | |
| 	for (;;) {
 | |
| 		c = nextchar();
 | |
| 		if (c == '\n' || c == '\0') {
 | |
| 			peekc = c;
 | |
| 			serror("non-terminated string");
 | |
| 			break;
 | |
| 		}
 | |
| 		if (c == termc)
 | |
| 			break;
 | |
| 		if (c == '\\')
 | |
| 			c = inescape();
 | |
| 		if (p >= &stringbuf[STRINGMAX - 1])
 | |
| 			fatal("string buffer overflow");
 | |
| 		*p++ = c;
 | |
| 	}
 | |
| 	stringbuf[0] = p - stringbuf - 1;
 | |
| 	*p = '\0';
 | |
| 	return(STRING);
 | |
| }
 | |
| 
 | |
| 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');
 | |
| 	case '\'':	return('\'');
 | |
| 	case '"':	return('"');
 | |
| 	}
 | |
| 	return(c);
 | |
| }
 | |
| 
 | |
| infbsym(p)
 | |
| register char *p;
 | |
| {
 | |
| 	register lab;
 | |
| 	register item_t *ip;
 | |
| 
 | |
| 	lab = *p++ - '0';
 | |
| 	if ((unsigned)lab < 10) {
 | |
| 		if (*p++ == 'f') {
 | |
| 			ip = fb_ptr[FB_FORW+lab];
 | |
| 			if (ip == 0) {
 | |
| 				ip = fb_alloc(lab);
 | |
| 				fb_ptr[FB_FORW+lab] = ip;
 | |
| 			}
 | |
| 			goto ok;
 | |
| 		}
 | |
| 		ip = fb_ptr[FB_BACK+lab];
 | |
| 		if (ip != 0 && *p == 0)
 | |
| 			goto ok;
 | |
| 	}
 | |
| 	serror("bad numeric label");
 | |
| 	ip = fb_alloc(0);
 | |
| ok:
 | |
| 	yylval.y_item = ip;
 | |
| 	return(FBSYM);
 | |
| }
 | |
| 
 | |
| hash(p)
 | |
| register char *p;
 | |
| {
 | |
| 	register unsigned h;
 | |
| 	register c;
 | |
| 
 | |
| 	h = 0;
 | |
| 	while (c = *p++) {
 | |
| 		h <<= 2;
 | |
| 		h += c;
 | |
| 	}
 | |
| 	return(h % H_SIZE);
 | |
| }
 | |
| 
 | |
| item_t *
 | |
| item_search(p)
 | |
| register char *p;
 | |
| {
 | |
| 	register h;
 | |
| 	register item_t *ip;
 | |
| 
 | |
| 	for (h = hash(p); h < H_TOTAL; h += H_SIZE) {
 | |
| 		ip = hashtab[h];
 | |
| 		while (ip != 0) {
 | |
| 			if (strcmp(p, ip->i_name) == 0)
 | |
| 				goto done;
 | |
| 			ip = ip->i_next;
 | |
| 		}
 | |
| 	}
 | |
| done:
 | |
| 	hashindex = h;
 | |
| 	return(ip);
 | |
| }
 | |
| 
 | |
| item_insert(ip, h)
 | |
| item_t *ip;
 | |
| {
 | |
| 	ip->i_next = hashtab[h];
 | |
| 	hashtab[h] = ip;
 | |
| }
 | |
| 
 | |
| item_t *
 | |
| item_alloc(typ)
 | |
| {
 | |
| 	register item_t *ip;
 | |
| 	static nleft = 0;
 | |
| 	static item_t *next;
 | |
| 
 | |
| 	if (--nleft < 0) {
 | |
| 		next = (item_t *) malloc(MEMINCR);
 | |
| 		if (next == 0)
 | |
| 			fatal("out of memory");
 | |
| 		nleft += (MEMINCR / sizeof(item_t));
 | |
| 	}
 | |
| 	ip = next++;
 | |
| 	ip->i_next = 0;
 | |
| 	ip->i_type = typ;
 | |
| 	ip->i_name = 0;
 | |
| 	ip->i_valu = 0;
 | |
| 	return(ip);
 | |
| }
 | |
| 
 | |
| item_t *
 | |
| fb_alloc(lab)
 | |
| register lab;
 | |
| {
 | |
| 	register item_t *ip, *p;
 | |
| 
 | |
| 	ip = item_alloc(S_UND);
 | |
| 	p = fb_ptr[FB_TAIL+lab];
 | |
| 	if (p == 0)
 | |
| 		fb_ptr[FB_HEAD+lab] = ip;
 | |
| 	else
 | |
| 		p->i_next = ip;
 | |
| 	fb_ptr[FB_TAIL+lab] = ip;
 | |
| 	return(ip);
 | |
| }
 | |
| 
 | |
| item_t *
 | |
| fb_shift(lab)
 | |
| register lab;
 | |
| {
 | |
| 	register item_t *ip;
 | |
| 
 | |
| 	ip = fb_ptr[FB_FORW+lab];
 | |
| 	if (ip == 0)
 | |
| 		if (pass == PASS_1)
 | |
| 			ip = fb_alloc(lab);
 | |
| 		else
 | |
| 			ip = fb_ptr[FB_HEAD+lab];
 | |
| 	fb_ptr[FB_BACK+lab] = ip;
 | |
| 	fb_ptr[FB_FORW+lab] = ip->i_next;
 | |
| 	return(ip);
 | |
| }
 |