Zapple-II/z80as/as2.c

245 lines
3.2 KiB
C

/*
* Z-80 assembler.
* Symbol table routines
* and error handling.
*/
#include "as.h"
/*
* Given a pointer to a
* sumbol, compute the hash bucket
* number. The "add all the characters
* and take the result modulo the table
* size" algorithm is used.
*/
symhash(id)
register char *id;
{
register int hash;
register int n;
hash = 0;
n = NCPS;
do {
hash += *id++;
} while (--n);
return (hash&HMASK);
}
/*
* Handle an error.
* If no listing file, write out
* the error directly. Otherwise save
* the error in the error buffer.
*/
err(c)
{
if (pass != 0) {
if (lflag != 0)
storerror(c);
else
printf("%04d %c\n", line, c);
}
if (c == 'q')
longjmp(env, 1);
}
/*
* This routine is like
* "err", but it has the "u"
* code screwed into it, and it
* prints the name of the identifier
* "id" in the message.
*/
uerr(id)
char *id;
{
if (pass != 0) {
if (lflag != 0)
storerror('u');
else
printf("%04d u %.*s\n", line, NCPS, id);
}
}
/*
* The "a" error is common.
*/
aerr()
{
err('a');
}
/*
* Ditto the "q" error.
*/
qerr()
{
err('q');
}
/*
* Put the error code
* "c" into the error buffer.
* Check that it is not already
* there.
*/
storerror(c)
register int c;
{
register char *p;
p = &eb[0];
while (p < ep)
if (*p++ == c)
return;
if (p < &eb[NERR]) {
*p++ = c;
ep = p;
}
}
/*
* Read identifier.
* The character "c" is the first
* character of the name.
*/
getid(id, c)
register int c;
char *id;
{
register char *p;
if (c < 0) {
c = getnb();
if (isalpha(c) == 0)
qerr();
}
p = &id[0];
do {
if (p < &id[NCPS]) {
if (isupper(c))
c = tolower(c);
*p++ = c;
}
if ((c = *ip) != '\n')
++ip;
} while (c=='\'' || isalnum(c)!=0);
if (c != '\n')
--ip;
while (p < &id[NCPS])
*p++ = 0;
}
/*
* Lookup symbol in
* hash table "htable".
* If not there, and "cf" is
* true, create it.
*/
SYM *
lookup(id, htable, cf)
char *id;
SYM *htable[];
{
register SYM *sp;
register int hash;
hash = symhash(id);
sp = htable[hash];
while (sp != NULL) {
if (symeq(id, sp->s_id))
return (sp);
sp = sp->s_fp;
}
if (cf != 0) {
if ((sp=(SYM *)malloc(sizeof(SYM))) == NULL) {
fprintf(stderr, "No memory\n");
exit(BAD);
}
sp->s_fp = htable[hash];
htable[hash] = sp;
sp->s_type = TNEW;
sp->s_value = 0;
symcopy(sp->s_id, id);
}
return (sp);
}
/*
* Compare two names.
* Each are blocks of "NCPS"
* bytes. True return if the names
* are exactly equal.
*/
symeq(p1, p2)
register char *p1;
register char *p2;
{
register int n;
n = NCPS;
do {
if (*p1++ != *p2++)
return (0);
} while (--n);
return (1);
}
/*
* Copy the characters
* that make up the name of a
* symbol.
*/
symcopy(p1, p2)
register char *p1;
register char *p2;
{
register int n;
n = NCPS;
do {
*p1++ = *p2++;
} while (--n);
}
/*
* Get the next character
* from the input buffer. Do not
* step past the newline.
*/
get()
{
register int c;
if ((c = *ip) != '\n')
++ip;
return (c);
}
/*
* Get the next non
* whitespace character from
* the input buffer. Do not step
* past the newline.
*/
getnb()
{
register int c;
while ((c = *ip)==' ' || c=='\t')
++ip;
if (c != '\n')
++ip;
return (c);
}
/*
* Put a character back.
*/
unget(c)
{
if (c != '\n')
--ip;
}