f705339f86
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.
583 lines
9.2 KiB
C
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);
|
|
}
|