ack/mach/proto/as/comm5.c

698 lines
10 KiB
C
Raw Normal View History

1994-06-24 14:02:31 +00:00
/* $Id$ */
1987-03-09 19:15:41 +00:00
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
1985-04-12 16:56:43 +00:00
/* @(#)comm5.c 1.1 */
2018-09-10 20:25:14 +00:00
#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(const char*);
static int maxstring = 0;
2018-09-10 20:25:14 +00:00
int yylex(void)
1985-04-12 16:56:43 +00:00
{
int c, c0, c1;
1985-04-12 16:56:43 +00:00
2018-09-10 20:25:14 +00:00
if (pass == PASS_1)
{
1985-04-12 16:56:43 +00:00
/* 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);
2018-09-10 20:25:14 +00:00
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;
}
1985-04-12 16:56:43 +00:00
/* produce the intermediate token file */
if (c <= 0)
2018-09-10 20:25:14 +00:00
return (0);
if (c < 256)
{
1985-04-12 16:56:43 +00:00
putc(c, tempfile);
putc(0, tempfile);
2018-09-10 20:25:14 +00:00
}
else
{
1985-04-12 16:56:43 +00:00
putval(c);
}
2018-09-10 20:25:14 +00:00
}
else
{
1985-04-12 16:56:43 +00:00
/* read from intermediate token file */
c0 = getc(tempfile);
if (c0 == EOF)
2018-09-10 20:25:14 +00:00
return (0);
c1 = getc(tempfile);
if (c1 == EOF)
2018-09-10 20:25:14 +00:00
return (0);
c = c0 + (c1 << 8);
if (c >= 256)
1985-04-12 16:56:43 +00:00
c = getval(c);
}
curr_token = c;
2018-09-10 20:25:14 +00:00
return (c);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
void putval(int c)
1985-04-12 16:56:43 +00:00
{
int64_t v;
int n = 0;
2018-09-10 20:25:14 +00:00
char* p = 0;
1985-04-12 16:56:43 +00:00
assert(c == (c & 0xffff));
2018-09-10 20:25:14 +00:00
switch (c)
{
case CODE1:
n = 1;
v = yylval.y_valu;
2018-09-10 20:25:14 +00:00
goto putnum;
case CODE2:
n = 2;
v = yylval.y_valu;
2018-09-10 20:25:14 +00:00
goto putnum;
case CODE4:
n = 4;
v = yylval.y_valu;
goto putnum;
case NUMBER8:
v = yylval.y_valu;
2018-09-10 20:25:14 +00:00
for (n = 0; n < sizeof(v); n++)
{
if (v == 0)
break;
v >>= 8;
}
if (n <= 4)
c = NUMBER0 + n;
else
n = 8;
v = yylval.y_valu;
2018-09-10 20:25:14 +00:00
putnum:
putc(c, tempfile);
putc(c >> 8, tempfile);
while (--n >= 0)
putc((int)(v >> (n * 8)), tempfile);
return;
case IDENT:
case FBSYM:
n = sizeof(item_t*);
p = (char*)&yylval.y_item;
break;
1985-04-12 16:56:43 +00:00
#ifdef ASLD
2018-09-10 20:25:14 +00:00
case MODULE:
n = sizeof(char*);
p = (char*)&yylval.y_strp;
break;
1985-04-12 16:56:43 +00:00
#endif
2018-09-10 20:25:14 +00:00
case STRING:
case NUMBERF:
2018-09-10 20:25:14 +00:00
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;
1985-04-12 16:56:43 +00:00
}
putc(c, tempfile);
putc(c >> 8, tempfile);
1985-04-12 16:56:43 +00:00
while (--n >= 0)
putc(*p++, tempfile);
}
2018-09-10 20:25:14 +00:00
int getval(int c)
1985-04-12 16:56:43 +00:00
{
int64_t v;
int n = 0;
2018-09-10 20:25:14 +00:00
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 = NUMBER8;
2018-09-10 20:25:14 +00:00
goto getnum;
case NUMBER1:
n = 1;
c = NUMBER8;
2018-09-10 20:25:14 +00:00
goto getnum;
case NUMBER2:
n = 2;
c = NUMBER8;
2018-09-10 20:25:14 +00:00
goto getnum;
case NUMBER3:
n = 3;
c = NUMBER8;
2018-09-10 20:25:14 +00:00
goto getnum;
case NUMBER4:
2018-09-10 20:25:14 +00:00
n = 4;
c = NUMBER8;
goto getnum;
case NUMBER8:
n = 8;
2018-09-10 20:25:14 +00:00
getnum:
v = 0;
while (--n >= 0)
{
v <<= 8;
v |= getc(tempfile);
}
yylval.y_valu = v;
2018-09-10 20:25:14 +00:00
return (c);
case IDENT:
case FBSYM:
n = sizeof(item_t*);
p = (char*)&yylval.y_item;
break;
1985-04-12 16:56:43 +00:00
#ifdef ASLD
2018-09-10 20:25:14 +00:00
case MODULE:
n = sizeof(char*);
p = (char*)&yylval.y_strp;
break;
1985-04-12 16:56:43 +00:00
#endif
2018-09-10 20:25:14 +00:00
case STRING:
case NUMBERF:
2018-09-10 20:25:14 +00:00
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;
1985-04-12 16:56:43 +00:00
}
while (--n >= 0)
*p++ = getc(tempfile);
2018-09-10 20:25:14 +00:00
return (c);
1985-04-12 16:56:43 +00:00
}
/* ---------- lexical scan in pass 1 ---------- */
2018-09-10 20:25:14 +00:00
int nextchar(void)
1985-04-12 16:56:43 +00:00
{
int c;
1985-04-12 16:56:43 +00:00
2018-09-10 20:25:14 +00:00
if (peekc != -1)
{
1985-04-12 16:56:43 +00:00
c = peekc;
peekc = -1;
2018-09-10 20:25:14 +00:00
return (c);
1985-04-12 16:56:43 +00:00
}
#ifdef ASLD
if (archmode && --archsize < 0)
2018-09-10 20:25:14 +00:00
return (0);
1985-04-12 16:56:43 +00:00
#endif
if ((c = getc(input)) == EOF)
2018-09-10 20:25:14 +00:00
return (0);
1985-04-12 16:56:43 +00:00
if (isascii(c) == 0)
fatal("non-ascii character");
#ifdef LISTING
if (listflag & 0440)
putc(c, listfile);
#endif
2018-09-10 20:25:14 +00:00
return (c);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
static void readcode(int n)
1985-04-12 16:56:43 +00:00
{
int c;
1985-04-12 16:56:43 +00:00
yylval.y_valu = 0;
2018-09-10 20:25:14 +00:00
do
{
1985-04-12 16:56:43 +00:00
if (
#ifdef ASLD
2018-09-10 20:25:14 +00:00
(archmode && --archsize < 0) ||
1985-04-12 16:56:43 +00:00
#endif
2018-09-10 20:25:14 +00:00
(c = getc(input)) == EOF)
1985-04-12 16:56:43 +00:00
fatal("unexpected EOF in compact input");
yylval.y_valu <<= 8;
yylval.y_valu |= c;
} while (--n);
}
2018-09-10 20:25:14 +00:00
static int induo(int c)
1985-04-12 16:56:43 +00:00
{
static short duo[] = {
2018-09-10 20:25:14 +00:00
('=' << 8) | '=',
OP_EQ,
('<' << 8) | '>',
OP_NE,
('<' << 8) | '=',
OP_LE,
('>' << 8) | '=',
OP_GE,
('<' << 8) | '<',
OP_LL,
('>' << 8) | '>',
OP_RR,
('|' << 8) | '|',
OP_OO,
('&' << 8) | '&',
OP_AA,
0 /* terminates array */
1985-04-12 16:56:43 +00:00
};
2018-09-10 20:25:14 +00:00
short* p;
1985-04-12 16:56:43 +00:00
2018-09-10 20:25:14 +00:00
c = (c << 8) | nextchar();
1985-04-12 16:56:43 +00:00
for (p = duo; *p; p++)
if (*p++ == c)
2018-09-10 20:25:14 +00:00
return (*p++);
1985-04-12 16:56:43 +00:00
peekc = c & 0377;
2018-09-10 20:25:14 +00:00
return (c >> 8);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
static char name[NAMEMAX + 1];
2018-09-10 20:25:14 +00:00
static int inident(int c)
1985-04-12 16:56:43 +00:00
{
2018-09-10 20:25:14 +00:00
char* p = name;
item_t* ip;
int n = NAMEMAX;
1985-04-12 16:56:43 +00:00
2018-09-10 20:25:14 +00:00
do
{
if (--n >= 0)
*p++ = c;
c = nextchar();
} while (ISALNUM(c));
*p = '\0';
peekc = c;
ip = item_search(name);
2018-09-10 20:25:14 +00:00
if (ip == 0)
{
1985-04-12 16:56:43 +00:00
ip = item_alloc(S_UND);
ip->i_name = remember(name);
1985-04-12 16:56:43 +00:00
/* printf("ident %s %o\n", ip->i_name, ip); */
unresolved++;
2018-09-10 20:25:14 +00:00
item_insert(ip, H_LOCAL + (hashindex % H_SIZE));
}
else if (hashindex < H_SIZE)
{
1985-04-12 16:56:43 +00:00
assert(H_KEY == 0);
2018-09-10 20:25:14 +00:00
yylval.y_word = (word_t)ip->i_valu;
return (ip->i_type);
1985-04-12 16:56:43 +00:00
}
yylval.y_item = ip;
2018-09-10 20:25:14 +00:00
return (IDENT);
1985-04-12 16:56:43 +00:00
}
#ifdef ASLD
2018-09-10 20:25:14 +00:00
char* readident(int c)
1985-04-12 16:56:43 +00:00
{
int n = NAMEMAX;
2018-09-10 20:25:14 +00:00
char* p = name;
1985-04-12 16:56:43 +00:00
2018-09-10 20:25:14 +00:00
do
{
1985-04-12 16:56:43 +00:00
if (--n >= 0)
*p++ = c;
c = nextchar();
} while (ISALNUM(c));
*p++ = '\0';
peekc = c;
2018-09-10 20:25:14 +00:00
return (name);
1985-04-12 16:56:43 +00:00
}
#endif
1985-04-12 16:56:43 +00:00
2019-03-30 16:52:37 +00:00
static void need_stringbuf()
{
if (!maxstring)
{
maxstring = STRINGMAX;
if ((stringbuf = malloc(maxstring)) == 0)
{
fatal("out of memory");
}
}
}
2018-09-10 20:25:14 +00:00
static int innumber(int c)
1985-04-12 16:56:43 +00:00
{
uvalu_t uv;
2018-09-10 20:25:14 +00:00
char* p;
int radix;
static char num[40 + 1];
1985-04-12 16:56:43 +00:00
p = num;
radix = 40;
if (c == '.')
goto floatconstant;
2018-09-10 20:25:14 +00:00
do
{
1985-04-12 16:56:43 +00:00
if (--radix < 0)
fatal("number too long");
if (isupper(c))
c += ('a' - 'A');
*p++ = c;
c = nextchar();
if (c == '.')
goto floatconstant;
1988-04-22 18:34:22 +00:00
} while (isalnum(c));
1985-04-12 16:56:43 +00:00
peekc = c;
*p = '\0';
c = *--p;
p = num;
radix = 10;
2018-09-10 20:25:14 +00:00
if (*p == '0')
{
1985-04-12 16:56:43 +00:00
radix = 8;
p++;
2018-09-10 20:25:14 +00:00
if (*p == 'x')
{
1985-04-12 16:56:43 +00:00
radix = 16;
p++;
2018-09-10 20:25:14 +00:00
}
else if (*p == 'b')
{
1985-04-12 16:56:43 +00:00
radix = 2;
p++;
}
}
if (radix != 16 && (c == 'f' || c == 'b'))
2018-09-10 20:25:14 +00:00
return (infbsym(num));
uv = 0;
2019-03-24 16:13:42 +00:00
while ((c = *p++))
2018-09-10 20:25:14 +00:00
{
1985-04-12 16:56:43 +00:00
if (c > '9')
c -= ('a' - '9' - 1);
c -= '0';
1988-04-22 18:34:22 +00:00
if ((unsigned)c >= radix)
1985-04-12 16:56:43 +00:00
serror("digit exceeds radix");
uv = uv * radix + c;
1985-04-12 16:56:43 +00:00
}
yylval.y_valu = uv; /* signed = unsigned */
return (NUMBER8);
floatconstant:
do
{
if (--radix < 0)
fatal("number too long");
*p++ = c;
c = nextchar();
if (isupper(c))
c = tolower(c);
} while (isdigit(c) || (c == '.') || (c == 'e') || (c == '+') || (c == '-'));
peekc = c;
*p = '\0';
stringlen = p - num;
2019-03-30 16:52:37 +00:00
need_stringbuf();
assert(stringlen < maxstring);
strcpy(stringbuf, num);
return NUMBERF;
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
static int instring(int termc)
1985-04-12 16:56:43 +00:00
{
2018-09-10 20:25:14 +00:00
char* p;
int c;
1985-04-12 16:56:43 +00:00
2019-03-30 16:52:37 +00:00
need_stringbuf();
1990-08-01 14:30:45 +00:00
p = stringbuf;
2018-09-10 20:25:14 +00:00
for (;;)
{
1985-04-12 16:56:43 +00:00
c = nextchar();
2018-09-10 20:25:14 +00:00
if (c == '\n' || c == '\0')
{
1985-04-12 16:56:43 +00:00
peekc = c;
serror("non-terminated string");
break;
}
if (c == termc)
break;
if (c == '\\')
c = inescape();
2018-09-10 20:25:14 +00:00
if (p >= &stringbuf[maxstring - 1])
{
1990-08-01 14:30:45 +00:00
int cnt = p - stringbuf;
2018-09-10 20:25:14 +00:00
if ((stringbuf = realloc(stringbuf, maxstring += 256)) == 0)
{
1990-08-01 14:30:45 +00:00
fatal("out of memory");
}
p = stringbuf + cnt;
}
1985-04-12 16:56:43 +00:00
*p++ = c;
}
1990-08-01 14:30:45 +00:00
stringlen = p - stringbuf;
1985-04-12 16:56:43 +00:00
*p = '\0';
2018-09-10 20:25:14 +00:00
return (STRING);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
static int inescape(void)
1985-04-12 16:56:43 +00:00
{
int c, j, r;
1985-04-12 16:56:43 +00:00
c = nextchar();
2018-09-10 20:25:14 +00:00
if (c >= '0' && c <= '7')
{
1985-04-12 16:56:43 +00:00
r = c - '0';
2018-09-10 20:25:14 +00:00
for (j = 0; j < 2; j++)
{
1985-04-12 16:56:43 +00:00
c = nextchar();
2018-09-10 20:25:14 +00:00
if (c < '0' || c > '7')
{
1985-04-12 16:56:43 +00:00
peekc = c;
2018-09-10 20:25:14 +00:00
return (r);
1985-04-12 16:56:43 +00:00
}
r <<= 3;
r += (c - '0');
}
2018-09-10 20:25:14 +00:00
return (r);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
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 ('"');
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
return (c);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
static int infbsym(const char* p)
1985-04-12 16:56:43 +00:00
{
int lab;
2018-09-10 20:25:14 +00:00
item_t* ip;
1985-04-12 16:56:43 +00:00
lab = *p++ - '0';
2018-09-10 20:25:14 +00:00
if ((unsigned)lab < 10)
{
if (*p++ == 'f')
{
ip = fb_ptr[FB_FORW + lab];
if (ip == 0)
{
1985-04-12 16:56:43 +00:00
ip = fb_alloc(lab);
2018-09-10 20:25:14 +00:00
fb_ptr[FB_FORW + lab] = ip;
1985-04-12 16:56:43 +00:00
}
goto ok;
}
2018-09-10 20:25:14 +00:00
ip = fb_ptr[FB_BACK + lab];
1985-04-12 16:56:43 +00:00
if (ip != 0 && *p == 0)
goto ok;
}
serror("bad numeric label");
ip = fb_alloc(0);
ok:
yylval.y_item = ip;
2018-09-10 20:25:14 +00:00
return (FBSYM);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
int hash(const char* p)
1985-04-12 16:56:43 +00:00
{
unsigned short h;
int c;
1985-04-12 16:56:43 +00:00
h = 0;
2019-03-24 16:13:42 +00:00
while ((c = *p++))
2018-09-10 20:25:14 +00:00
{
1985-04-12 16:56:43 +00:00
h <<= 2;
h += c;
}
2018-09-10 20:25:14 +00:00
return (h % H_SIZE);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
item_t* item_search(const char* p)
1985-04-12 16:56:43 +00:00
{
int h;
2018-09-10 20:25:14 +00:00
item_t* ip;
1985-04-12 16:56:43 +00:00
2018-09-10 20:25:14 +00:00
for (h = hash(p); h < H_TOTAL; h += H_SIZE)
{
1985-04-12 16:56:43 +00:00
ip = hashtab[h];
2018-09-10 20:25:14 +00:00
while (ip != 0)
{
1985-04-12 16:56:43 +00:00
if (strcmp(p, ip->i_name) == 0)
goto done;
ip = ip->i_next;
}
}
done:
hashindex = h;
2018-09-10 20:25:14 +00:00
return (ip);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
void item_insert(item_t* ip, int h)
1985-04-12 16:56:43 +00:00
{
ip->i_next = hashtab[h];
hashtab[h] = ip;
}
2018-09-10 20:25:14 +00:00
item_t* item_alloc(int typ)
1985-04-12 16:56:43 +00:00
{
2018-09-10 20:25:14 +00:00
item_t* ip;
static int nleft = 0;
2018-09-10 20:25:14 +00:00
static item_t* next;
1985-04-12 16:56:43 +00:00
2018-09-10 20:25:14 +00:00
if (--nleft < 0)
{
next = (item_t*)malloc(MEMINCR);
1987-08-06 13:04:20 +00:00
if (next == 0)
1985-04-12 16:56:43 +00:00
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;
2018-09-10 20:25:14 +00:00
return (ip);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
item_t* fb_alloc(int lab)
1985-04-12 16:56:43 +00:00
{
item_t *ip, *p;
1985-04-12 16:56:43 +00:00
ip = item_alloc(S_UND);
2018-09-10 20:25:14 +00:00
p = fb_ptr[FB_TAIL + lab];
1985-04-12 16:56:43 +00:00
if (p == 0)
2018-09-10 20:25:14 +00:00
fb_ptr[FB_HEAD + lab] = ip;
1985-04-12 16:56:43 +00:00
else
p->i_next = ip;
2018-09-10 20:25:14 +00:00
fb_ptr[FB_TAIL + lab] = ip;
return (ip);
1985-04-12 16:56:43 +00:00
}
2018-09-10 20:25:14 +00:00
item_t* fb_shift(int lab)
1985-04-12 16:56:43 +00:00
{
2018-09-10 20:25:14 +00:00
item_t* ip;
1985-04-12 16:56:43 +00:00
2018-09-10 20:25:14 +00:00
ip = fb_ptr[FB_FORW + lab];
1985-04-12 16:56:43 +00:00
if (ip == 0)
2019-03-24 16:13:42 +00:00
{
1985-04-12 16:56:43 +00:00
if (pass == PASS_1)
2019-03-24 16:13:42 +00:00
{
1985-04-12 16:56:43 +00:00
ip = fb_alloc(lab);
2019-03-24 16:13:42 +00:00
}
1985-04-12 16:56:43 +00:00
else
2019-03-24 16:13:42 +00:00
{
2018-09-10 20:25:14 +00:00
ip = fb_ptr[FB_HEAD + lab];
2019-03-24 16:13:42 +00:00
}
}
2018-09-10 20:25:14 +00:00
fb_ptr[FB_BACK + lab] = ip;
fb_ptr[FB_FORW + lab] = ip->i_next;
return (ip);
1985-04-12 16:56:43 +00:00
}