|
|
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: 7766 (0x1e56)
Types: TextFile
Notes: UNIX file
Names: »asm.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/as/asm.c«
/*
* Segmented assembler.
* Segmented assemblers are much
* more of a pain then non segmented
* ones. Here we try to make them
* easy to use, at the expense of
* driving the implementor absolutely
* crazy.
*/
#include "asm.h"
main(argc, argv)
char *argv[];
{
register char *p;
register c, i;
char *sfn;
int nfile, sfx;
static char copen[] = "%s: cannot open.\n";
nfile = argc-1;
for (i=1; i<argc; ++i) {
p = argv[i];
if (*p == '-') {
argv[i] = NULL;
--nfile;
++p;
while (c = *p++) {
switch(c) {
case 'g':
++gflag;
break;
case 'l':
++lflag;
break;
case 'o':
if (++i >= argc)
usage();
ofn = argv[i];
argv[i] = NULL;
--nfile;
break;
case 'x':
++xflag;
break;
default:
usage();
}
}
}
}
if (nfile == 0)
usage();
#if CPM
ofp = fopen(ofn, "wb");
#else
ofp = fopen(ofn, "w");
#if !INTEL
if (ofp != NULL)
ofp = freopen(ofn, "r+w", ofp);
#endif
#endif
if (ofp == NULL) {
fprintf(stderr, "%s: cannot create.\n", ofn);
exit(1);
}
#if !RSX && !CPM
setbuf(ofp, NULL);
#endif
syminit();
locinit();
for (pass = 0; pass < 3; ++pass) {
if (pass==1 && gflag)
symglob();
if (pass == 2) {
locadjust();
outinit();
}
sfx = 1;
page = 0;
lop = NLPP;
if (sfp != NULL) {
fseek(sfp, (long)0, 0);
line = 0;
}
loczero();
fuzz = 0;
#if MINIT
minit();
#endif
dot->s_kind = S_USER;
dot->s_type = E_DIR;
dot->s_addr = defloc->l_offset;
dot->s_base.s_lp = defloc;
setinbss();
if (pass != 0) {
for (i=0; i<10; ++i) {
tsymp[i].tp_bp = NULL;
tsymp[i].tp_fp = tsymp[i].tp_lfp;
}
}
for (;;) {
if (sfp == NULL) {
sfn = NULL;
while (sfx<argc && (sfn=argv[sfx++])==NULL)
;
if (sfn == NULL)
break;
if ((sfp = fopen(sfn, "r")) == NULL) {
fprintf(stderr, copen, sfn);
exit(1);
}
if (nfile != 1)
ifn = sfn;
line = 0;
lop = NLPP;
}
if (getline() == 0) {
if (nfile == 1)
break;
fclose(sfp);
sfp = NULL;
continue;
}
++line;
cp = cb;
ep = eb;
ip = ib;
if (setjmp(env) == 0)
asm();
if (pass == 2)
list();
}
newloc(NULL);
}
outfinish();
if (nerr != 0) {
if (lflag) {
fprintf(stderr, "%d error", nerr);
if (nerr != 1)
putc('s', stderr);
fprintf(stderr, " detected.\n");
}
exit(1);
}
#if !RSX && !CPM
chmod(ofn, 0755);
#endif
exit(0);
}
asm()
{
register struct sym *sp;
register struct tsym *tp;
register c;
address cs;
struct tsymp *tsp;
struct expr e1;
char id[NCPLN];
char *p;
int d;
laddr = dot->s_addr;
lmode = SLIST;
loop:
while ((c=getnb()) == ';')
;
if (c==0 || c=='/')
return;
if (ctype[c] == DIGIT) {
if (get() != ':')
qerr();
tsp = &tsymp[c-'0'];
if (pass == 0) {
tp = (struct tsym *) new(sizeof(struct tsym));
tp->t_fp = NULL;
tp->t_lp = dot->s_base.s_lp;
tp->t_addr = dot->s_addr;
if (tsp->tp_lfp == NULL)
tsp->tp_lfp = tp; else
tsp->tp_llp->t_fp = tp;
tsp->tp_llp = tp;
} else {
tp = tsp->tp_fp;
if (pass == 1) {
fuzz = tp->t_addr - dot->s_addr;
tp->t_lp = dot->s_base.s_lp;
tp->t_addr = dot->s_addr;
} else
phase(tp->t_lp, tp->t_addr);
}
tsp->tp_bp = tp;
tsp->tp_fp = tp->t_fp;
goto loop;
}
if (ctype[c] != LETTER)
qerr();
getid(id, c);
if ((c=getnb()) == ':') {
sp = lookup(id, 1);
if (sp == dot)
err('.');
if (pass == 0)
if (sp->s_type!=S_NEW && (sp->s_flag&S_ASG)==0)
sp->s_flag |= S_MDF;
if (pass != 2) {
fuzz = sp->s_addr - dot->s_addr;
sp->s_kind = S_USER;
sp->s_type = E_DIR;
sp->s_base.s_lp = dot->s_base.s_lp;
sp->s_addr = dot->s_addr;
} else {
if ((sp->s_flag&S_MDF) != 0)
err('m');
phase(sp->s_base.s_lp, sp->s_addr);
}
lmode = ALIST;
goto loop;
}
if (c == '=') {
expr(&e1, 0);
if ((sp=lookup(id, 1)) == dot) {
#if INTEL
dot->s_addr = e1.e_addr;
#else
if (okdot(&e1)) {
if (inbss == 0)
zblock(e1.e_addr-dot->s_addr);
else
dot->s_addr = e1.e_addr;
}
#endif
} else {
if (sp->s_type!=S_NEW && (sp->s_flag&S_ASG)==0)
err('m');
sp->s_kind = S_USER;
sp->s_type = e1.e_type;
if (e1.e_type == E_ASEG)
sp->s_base.s_segn = e1.e_base.e_segn;
else if (e1.e_type == E_DIR)
sp->s_base.s_lp = e1.e_base.e_lp;
else if (e1.e_type==E_SYM || e1.e_type==E_SEG)
sp->s_base.s_sp = e1.e_base.e_sp;
sp->s_addr = e1.e_addr;
sp->s_flag |= S_ASG;
}
laddr = e1.e_addr;
lmode = ALIST;
goto loop;
}
unget(c);
lmode = CLIST;
if ((sp=lookup(id, 0)) == NULL) {
err('o');
return;
}
switch (sp->s_kind) {
case S_BYTE:
case S_WORD:
do {
expr(&e1, 0);
if (sp->s_kind == S_BYTE)
outrb(&e1, 0); else
outrw(&e1, 0);
} while ((c = getnb()) == ',');
unget(c);
if (sp->s_kind == S_BYTE)
lmode = BLIST; else
lmode = WLIST;
break;
case S_ASCII:
if ((d = getnb()) == '\0')
qerr();
while ((c = getmap(d)) >= 0)
outab(c);
lmode = BLIST;
break;
case S_BLK:
cs = absexpr()*sp->s_addr;
if (inbss == 0)
zblock(cs); else
dot->s_addr += cs;
lmode = ALIST;
break;
case S_TITLE:
p = tb;
if (c = getnb()) {
do {
if (p < &tb[NTIT-1])
*p++ = c;
} while (c = get());
}
*p = 0;
unget(c);
case S_PAGE:
lop = NLPP;
lmode = NLIST;
break;
case S_GLOBL:
do {
getid(id, -1);
lookup(id, 1)->s_flag |= S_GBL;
} while ((c = getnb()) == ',');
unget(c);
lmode = SLIST;
break;
case S_COMM:
getid(id, -1);
if (getnb() != ',')
qerr();
cs = locrup(absexpr());
sp = lookup(id, 1);
if (sp->s_kind == S_NEW) {
sp->s_flag |= S_GBL;
if (cs > sp->s_addr)
sp->s_addr = cs;
}
lmode = SLIST;
break;
case S_LOC:
newloc((struct loc *) sp->s_addr);
lmode = SLIST;
break;
default:
machine(sp);
}
goto loop;
}
okdot(esp)
register struct expr *esp;
{
if (esp->e_type!=E_DIR || esp->e_base.e_lp!=dot->s_base.s_lp) {
rerr();
return (0);
}
if (esp->e_addr < dot->s_addr) {
aerr();
return (0);
}
return (1);
}
zblock(n)
address n;
{
while (n--)
outab(0);
}
usage()
{
fprintf(stderr, "Usage: as [-glx] [-o file] file [file ...]\n");
exit(1);
}
phase(lp, a)
struct loc *lp;
address a;
{
if (dot->s_base.s_lp!=lp || dot->s_addr!=a)
err('p');
}
newloc(nlp)
register struct loc *nlp;
{
register struct loc *olp;
if ((olp = dot->s_base.s_lp) != NULL) {
olp->l_fuzz = fuzz;
olp->l_break = dot->s_addr - olp->l_offset;
}
if (nlp != NULL) {
dot->s_base.s_lp = nlp;
dot->s_addr = nlp->l_break + nlp->l_offset;
fuzz = nlp->l_fuzz;
}
setinbss();
#if !INTEL
if (pass == 2)
outchk(HUGE, HUGE);
#endif
}
loczero()
{
register struct loc *lp;
register i;
for (i=0; i<nloc; ++i) {
lp = loc[i];
while (lp != NULL) {
lp->l_fuzz = 0;
lp->l_break = 0;
lp = lp->l_lp;
}
}
}
locadjust()
{
register struct sym *sp;
register struct loc *lp;
register struct tsym *tp;
address offset;
int i;
#if !SEG
offset = 0;
#endif
for (i=0; i<nloc; ++i) {
#if SEG
offset = 0;
#endif
lp = loc[i];
while (lp != NULL) {
lp->l_offset = offset;
offset += locrup(lp->l_break);
lp = lp->l_lp;
}
}
for (i=0; i<10; ++i) {
tp = tsymp[i].tp_lfp;
while (tp != NULL) {
if ((lp = tp->t_lp) != NULL)
tp->t_addr += lp->l_offset;
tp = tp->t_fp;
}
}
for (i=0; i<NHASH; ++i) {
sp = symhash[i];
while (sp != NULL) {
if (sp->s_kind == S_USER &&
sp->s_type == E_DIR &&
(lp=sp->s_base.s_lp) != NULL)
sp->s_addr += lp->l_offset;
sp = sp->s_sp;
}
}
}
setinbss()
{
register struct loc *lp;
inbss = 0;
lp = dot->s_base.s_lp;
#if SEG
if (lp->l_seg == BSS)
#else
if (lp->l_seg==L_BSSI || lp->l_seg==L_BSSD)
#endif
++inbss;
}