ack/mach/proto/as/comm5.c
George Koehler f705339f86 Allow more tokens in the assembler.
I need this so I can add more %token lines to mach/powerpc/as/mach2.c

The assembler's tempfile encoded each token in a byte.  This only
worked with tokens 0 to 127 and 256 and 383.  If a token 384 or higher
existed, the assembler stopped working.  I need tokens 384 and higher.

I change the token encoding to a 2-byte little-endian integer.  I also
change a byte in the string encoding.
2017-01-17 22:41:11 -05:00

583 lines
9.2 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".
*/
/* @(#)comm5.c 1.1 */
#include "comm0.h"
#include "comm1.h"
#include "y.tab.h"
extern YYSTYPE yylval;
static void readcode(int);
static int induo(int);
static int inident(int);
static int innumber(int);
static int instring(int);
static int inescape(void);
static int infbsym(char *);
int
yylex(void)
{
int c, c0, c1;
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 < 256) {
putc(c, tempfile);
putc(0, tempfile);
} else {
putval(c);
}
} else {
/* read from intermediate token file */
c0 = getc(tempfile);
if (c0 == EOF)
return(0);
c1 = getc(tempfile);
if (c1 == EOF)
return(0);
c = c0 + (c1 << 8);
if (c >= 256)
c = getval(c);
}
curr_token = c;
return(c);
}
void
putval(int c)
{
register valu_t v;
register n = 0;
register char *p = 0;
assert(c == (c & 0xffff));
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;
}
assert(n <= 4);
c = NUMBER0 + n;
putnum:
putc(c, tempfile);
putc(c >> 8, 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:
v = stringlen;
putc(c, tempfile);
putc(c >> 8, tempfile);
for (n = 0; n < sizeof(v); n++) {
if (v == 0)
break;
v >>= 8;
}
assert(n <= 4);
putc(n, tempfile);
v = stringlen;
while (--n >= 0)
putc((int) (v >> (n*8)), tempfile);
p = stringbuf;
n = stringlen;
while (--n >= 0)
putc(*p++, tempfile);
return;
case OP_EQ:
case OP_NE:
case OP_LE:
case OP_GE:
case OP_LL:
case OP_RR:
case OP_OO:
case OP_AA:
break;
default:
n = sizeof(word_t);
p = (char *) &yylval.y_word; break;
}
putc(c, tempfile);
putc(c >> 8, tempfile);
while (--n >= 0)
putc(*p++, tempfile);
}
int
getval(int c)
{
register n = 0;
register valu_t v;
register char *p = 0;
switch (c) {
case CODE1:
n = 1; goto getnum;
case CODE2:
n = 2; goto getnum;
case CODE4:
n = 4; goto getnum;
case NUMBER0:
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:
getval(getc(tempfile)+NUMBER0);
stringlen = n = yylval.y_valu;
p = stringbuf;
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:
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 ---------- */
int
nextchar(void)
{
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);
}
static void
readcode(int 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);
}
static int
induo(int 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);
}
static char name[NAMEMAX+1];
static int
inident(int c)
{
register char *p = name;
register item_t *ip;
register n = NAMEMAX;
do {
if (--n >= 0)
*p++ = c;
c = nextchar();
} while (ISALNUM(c));
*p = '\0';
peekc = c;
ip = item_search(name);
if (ip == 0) {
ip = item_alloc(S_UND);
ip->i_name = remember(name);
/* 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);
}
#ifdef ASLD
char *
readident(int c)
{
register n = NAMEMAX;
register char *p = name;
do {
if (--n >= 0)
*p++ = c;
c = nextchar();
} while (ISALNUM(c));
*p++ = '\0';
peekc = c;
return(name);
}
#endif
static int
innumber(int 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 ((unsigned)c >= radix)
serror("digit exceeds radix");
yylval.y_valu = yylval.y_valu * radix + c;
}
return(NUMBER);
}
static int
instring(int termc)
{
register char *p;
register c;
static int maxstring = 0;
if (! maxstring) {
maxstring = STRINGMAX;
if ((stringbuf = malloc(maxstring)) == 0) {
fatal("out of memory");
}
}
p = stringbuf;
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[maxstring - 1]) {
int cnt = p - stringbuf;
if ((stringbuf = realloc(stringbuf, maxstring += 256)) == 0) {
fatal("out of memory");
}
p = stringbuf + cnt;
}
*p++ = c;
}
stringlen = p - stringbuf;
*p = '\0';
return(STRING);
}
static int
inescape(void)
{
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);
}
static int
infbsym(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);
}
int
hash(char *p)
{
register unsigned short h;
register c;
h = 0;
while (c = *p++) {
h <<= 2;
h += c;
}
return(h % H_SIZE);
}
item_t *
item_search(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);
}
void
item_insert(item_t *ip, int h)
{
ip->i_next = hashtab[h];
hashtab[h] = ip;
}
item_t *
item_alloc(int 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(int 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(int 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);
}