|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 3857 (0xf11)
Types: TextFile
Notes: UNIX file
Names: »asmexpr.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/as/asmexpr.c«
#include "asm.h"
expr(esp, n)
register struct expr *esp;
{
register c, p;
address lv, rv;
int lt, rt;
struct expr re;
term(esp);
for (;;) {
c = getnb();
if (ctype[c] != BINOP)
break;
if (c == '|')
p = 10;
else if (c == '*')
p = 9;
else
p = 8;
if (p <= n)
break;
expr(&re, p);
lt = esp->e_type;
lv = esp->e_addr;
rt = re.e_type;
rv = re.e_addr;
if (c == '|') {
if (rt != E_ACON)
aerr();
switch (lt) {
case E_ACON:
esp->e_type = E_ASEG;
esp->e_base.e_segn = lv;
break;
case E_SYM:
esp->e_type = E_SEG;
break;
default:
aerr();
}
esp->e_addr = rv;
continue;
}
if (c == '^') {
if ((esp->e_type = rt) == E_DIR)
esp->e_base.e_lp = re.e_base.e_lp;
else if (rt==E_SYM || rt==E_SEG)
esp->e_base.e_sp = re.e_base.e_sp;
else if (rt == E_ASEG)
esp->e_base.e_segn = re.e_base.e_segn;
continue;
}
if (c == '+') {
if (lt == E_ACON) {
esp->e_type = rt;
if (rt == E_ASEG)
esp->e_base.e_segn = re.e_base.e_segn;
else if (rt == E_DIR)
esp->e_base.e_lp = re.e_base.e_lp;
else if (rt==E_SYM || rt==E_SEG)
esp->e_base.e_sp = re.e_base.e_sp;
} else if (rt != E_ACON)
rerr();
esp->e_addr += rv;
continue;
}
if (c == '-') {
if (lt == E_ACON) {
if (rt != E_ACON)
rerr();
} else if (rt != E_ACON) {
if (lt!=E_DIR || rt!=E_DIR ||
esp->e_base.e_lp!=re.e_base.e_lp)
rerr();
esp->e_type = E_ACON;
}
esp->e_addr -= rv;
continue;
}
if (c == '*') {
if (lt!=E_ACON || rt!=E_ACON)
aerr();
esp->e_addr *= rv;
continue;
}
fprintf(stderr, "Internal error, c=%d in expr.\n", c);
exit( 1);
}
unget(c);
}
address
absexpr()
{
struct expr e;
expr(&e, 0);
abscheck(&e);
return (e.e_addr);
}
term(esp)
register struct expr *esp;
{
register c;
address n;
char id[NCPLN];
struct sym *sp;
struct tsym *tp;
int r, v;
if ((c=getnb()) == '[') {
expr(esp, 0);
if (getnb() != ']')
qerr();
return;
}
if (c == '-') {
expr(esp, 100);
abscheck(esp);
esp->e_addr = -esp->e_addr;
return;
}
if (c == '~') {
expr(esp, 100);
abscheck(esp);
esp->e_addr = ~esp->e_addr;
return;
}
if (c == '\'') {
esp->e_type = E_ACON;
esp->e_addr = getmap(-1);
return;
}
esp->e_type = E_ACON;
esp->e_addr = 0;
if (ctype[c] == DIGIT) {
r = 10;
if (c == '0') {
r = 8;
if ((c = *ip) != 0)
++ip;
if (c == 'x') {
r = 16;
if ((c = *ip) != 0)
++ip;
}
}
n = 0;
while ((v=digit(c, r)) >= 0) {
n = r*n + v;
if ((c = *ip) != 0)
++ip;
}
if (c=='f' || c=='b') {
if (n < 10) {
if (c == 'f')
tp = tsymp[n].tp_fp; else
tp = tsymp[n].tp_bp;
if (tp != NULL) {
esp->e_type = E_DIR;
esp->e_base.e_lp = tp->t_lp;
esp->e_addr = tp->t_addr;
return;
}
}
err('u');
return;
}
if (c != 0)
--ip;
esp->e_addr = n;
return;
}
if (ctype[c] == LETTER) {
getid(id, c);
if ((sp=lookup(id, gflag)) != NULL) {
if (sp->s_kind == S_NEW) {
if ((sp->s_flag&S_GBL) != 0) {
esp->e_type = E_SYM;
esp->e_base.e_sp = sp;
return;
}
uerr(id);
return;
}
esp->e_type = sp->s_type;
esp->e_addr = sp->s_addr;
if (sp->s_type == E_ASEG)
esp->e_base.e_segn = sp->s_base.s_segn;
else if (sp->s_type == E_DIR)
esp->e_base.e_lp = sp->s_base.s_lp;
else if (sp->s_type==E_SYM || sp->s_type==E_SEG)
esp->e_base.e_sp = sp->s_base.s_sp;
return;
}
uerr(id);
return;
}
qerr();
}
digit(c, r)
register c, r;
{
if (r == 16) {
if (c>='A' && c<='F')
return (c-'A'+10);
if (c>='a' && c<='f')
return (c-'a'+10);
}
if (c>='0' && c<='9')
return (c - '0');
return (-1);
}
abscheck(esp)
register struct expr *esp;
{
if (esp->e_type != E_ACON) {
rerr();
esp->e_type = E_ACON;
}
}