home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
archives
/
appleii.zip
/
apxa3.c
< prev
next >
Wrap
Text File
|
1988-08-16
|
21KB
|
1,039 lines
#!/bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #!/bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# assm2.c
# assm3.c
# This archive created: Tue Apr 2 14:21:24 1985
# By: James Van Ornum (AT&T-Bell Laboratories)
export PATH; PATH=/bin:$PATH
if test -f 'assm2.c'
then
echo shar: over-writing existing file "'assm2.c'"
fi
cat << \SHAR_EOF > 'assm2.c'
#include "stdio.h"
#include "assm.d1"
#include "assm.d2"
extern int optab[];
extern int step[];
/* translate source line to machine language */
assemble()
{
int flg;
int i; /* prlnbuf pointer */
if ((prlnbuf[SFIELD] == ';') | (prlnbuf[SFIELD] == 0)) {
if (pass == LAST_PASS)
println();
return;
}
lablptr = -1;
i = SFIELD;
udtype = UNDEF;
if (colsym(&i) != 0 && (lablptr = stlook()) == -1)
return;
while (prlnbuf[++i] == ' '); /* find first non-space */
if ((flg = oplook(&i)) < 0) { /* collect operation code */
labldef(loccnt);
if (flg == -1)
error("Invalid operation code");
if ((flg == -2) && (pass == LAST_PASS)) {
if (lablptr != -1)
loadlc(loccnt, 1, 0);
println();
}
return;
}
if (opflg == PSEUDO)
pseudo(&i);
else if (labldef(loccnt) == -1)
return;
else {
if (opflg == CLASS1)
class1();
else if (opflg == CLASS2)
class2(&i);
else class3(&i);
}
}
/****************************************************************************/
/* printline prints the contents of prlnbuf */
println()
{
if (lflag > 0)
fprintf(stdout, "%s\n", prlnbuf);
}
/* colsym() collects a symbol from prlnbuf into symbol[],
* leaves prlnbuf pointer at first invalid symbol character,
* returns 0 if no symbol collected
*/
colsym(ip)
int *ip;
{
int valid;
int i;
char ch;
valid = 1;
i = 0;
while (valid == 1) {
ch = prlnbuf[*ip];
if (ch == '_' || ch == '.');
else if (ch >= 'a' && ch <= 'z');
else if (ch >= 'A' && ch <= 'Z');
else if (i >= 1 && ch >= '0' && ch <= '9');
else if (i == 1 && ch == '=');
else valid = 0;
if (valid == 1) {
if (i < SBOLSZ - 1)
symbol[++i] = ch;
(*ip)++;
}
}
if (i == 1) {
switch (symbol[1]) {
case 'A': case 'a':
case 'X': case 'x':
case 'Y': case 'y':
error("Symbol is reserved (A, X or Y)");
i = 0;
}
}
symbol[0] = i;
return(i);
}
/* symbol table lookup
* if found, return pointer to symbol
* else, install symbol as undefined, and return pointer
*/
stlook()
{
int found;
int hptr;
int j;
int nptr;
int pptr;
int ptr;
hptr = 0;
for (j = 0; j < symbol[0]; j++)
hptr += symbol[j];
hptr %= 128;
ptr = hash_tbl[hptr];
if (ptr == -1) { /* no entry for this link */
hash_tbl[hptr] = nxt_free;
return(stinstal());
}
while (symtab[ptr] != 0) { /* 0 count = end of table */
found = 1;
for (j = 0; j <= symbol[0]; j++) {
if (symbol[j] != symtab[ptr + j]) {
found = 0;
pptr = ptr + symtab[ptr] + 4;
nptr = (symtab[pptr + 1] << 8) + (symtab[pptr] & 0xff);
nptr &= 0xffff;
if (nptr == 0) {
symtab[ptr + symtab[ptr] + 4] = nxt_free & 0xff;
symtab[ptr + symtab[ptr] + 5] = (nxt_free >> 8) & 0xff;
return(stinstal());
}
ptr = nptr;
break;
}
}
if (found == 1)
return(ptr);
}
error("Symbol not found");
return(-1);
}
/* instal symbol into symtab
*/
stinstal()
{
register int j;
register int ptr1;
register int ptr2;
ptr1 = ptr2 = nxt_free;
if ((ptr1 + symbol[0] + 6) >= STABSZ) {
error("Symbol table full");
return(-1);
}
for (j = 0; j <= symbol[0]; j++)
symtab[ptr1++] = symbol[j];
symtab[ptr1] = udtype;
nxt_free = ptr1 + 5;
return(ptr2);
}
/* operation code table lookup
* if found, return pointer to symbol,
* else, return -1
*/
oplook(ip)
int *ip;
{
register char ch;
register int i;
register int j;
int k;
int temp[2];
i = j = 0;
temp[0] = temp[1] = 0;
while((ch=prlnbuf[*ip])!= ' ' && ch!= 0 && ch!= '\t' && ch!= ';') {
if (ch >= 'A' && ch <= 'Z')
ch &= 0x1f;
else if (ch >= 'a' && ch <= 'z')
ch &= 0x1f;
else if (ch == '.')
ch = 31;
else if (ch == '*')
ch = 30;
else if (ch == '=')
ch = 29;
else return(-1);
temp[j] = (temp[j] * 0x20) + (ch & 0xff);
if (ch == 29)
break;
++(*ip);
if (++i >= 3) {
i = 0;
if (++j >= 2) {
return(-1);
}
}
}
if ((j = temp[0]^temp[1]) == 0)
return(-2);
k = 0;
i = step[k] - 3;
do {
if (j == optab[i]) {
opflg = optab[++i];
opval = optab[++i];
return(i);
}
else if (j < optab[i])
i -= step[++k];
else i += step[++k];
} while (step[k] != 0);
return(-1);
}
/* error printing routine */
error(stptr)
char *stptr;
{
loadlc(loccnt, 0, 1);
loccnt += 3;
loadv(0,0,0);
loadv(0,1,0);
loadv(0,2,0);
fprintf(stderr, "%s\n", prlnbuf);
fprintf(stderr, "***** %s\n", stptr);
errcnt++;
}
/* load 16 bit value in printable form into prlnbuf */
loadlc(val, f, outflg)
int val;
int f;
int outflg;
{
int i;
i = 6 + 7*f;
hexcon(4, val);
if (nflag == 0) {
prlnbuf[i++] = hex[3];
prlnbuf[i++] = hex[4];
prlnbuf[i++] = ':';
prlnbuf[i++] = hex[1];
prlnbuf[i] = hex[2];
}
else {
prlnbuf[i++] = hex[1];
prlnbuf[i++] = hex[2];
prlnbuf[i++] = hex[3];
prlnbuf[i] = hex[4];
}
if ((pass == LAST_PASS)&&(oflag != 0)&&(objcnt <= 0)&&(outflg != 0)) {
/* rearrange the next for franklin monitor tm */
fprintf(optr, "\n%c%c%c%c:", hex[1], hex[2], hex[3], hex[4]);
objcnt = 16;
}
}
/* load value in hex into prlnbuf[contents[i]] */
/* and output hex characters to obuf if LAST_PASS & oflag == 1 */
loadv(val,f,outflg)
int val;
int f; /* contents field subscript */
int outflg; /* flag to output object bytes */
{
hexcon(2, val);
prlnbuf[13 + 3*f] = hex[1];
prlnbuf[14 + 3*f] = hex[2];
if ((pass == LAST_PASS) && (oflag != 0) && (outflg != 0)) {
fputc(hex[1], optr);
fputc(hex[2], optr);
fputc(' ', optr); /* add space for franklin monitor tm */
--objcnt;
}
}
/* convert number supplied as argument to hexadecimal in hex[digit] (lsd)
through hex[1] (msd) */
hexcon(digit, num)
int digit;
int num;
{
for (; digit > 0; digit--) {
hex[digit] = (num & 0x0f) + '0';
if (hex[digit] > '9')
hex[digit] += 'A' -'9' - 1;
num >>= 4;
}
}
/* assign <value> to label pointed to by lablptr,
* checking for valid definition, etc.
*/
labldef(lval)
int lval;
{
int i;
if (lablptr != -1) {
lablptr += symtab[lablptr] + 1;
if (pass == FIRST_PASS) {
if (symtab[lablptr] == UNDEF) {
symtab[lablptr + 1] = lval & 0xff;
i = symtab[lablptr + 2] = (lval >> 8) & 0xff;
if (i == 0)
symtab[lablptr] = DEFZRO;
else symtab[lablptr] = DEFABS;
}
else if (symtab[lablptr] == UNDEFAB) {
symtab[lablptr] = DEFABS;
symtab[lablptr + 1] = lval & 0xff;
symtab[lablptr + 2] = (lval >> 8) & 0xff;
}
else {
symtab[lablptr] = MDEF;
symtab[lablptr + 1] = 0;
symtab[lablptr + 2] = 0;
error("Label multiply defined");
return(-1);
}
}
else {
i = (symtab[lablptr + 2] << 8) +
(symtab[lablptr+1] & 0xff);
i &= 0xffff;
if (i != lval && pass == LAST_PASS) {
error("Sync error");
return(-1);
}
}
}
return(0);
}
/* determine the value of the symbol,
* given pointer to first character of symbol in symtab
*/
symval(ip)
int *ip;
{
int ptr;
int svalue;
svalue = 0;
colsym(ip);
if ((ptr = stlook()) == -1)
undef = 1; /* no room error */
else if (symtab[ptr + symtab[ptr] + 1] == UNDEF)
undef = 1;
else if (symtab[ptr + symtab[ptr] + 1] == UNDEFAB)
undef = 1;
else svalue = ((symtab[ptr + symtab[ptr] + 3] << 8) +
(symtab[ptr + symtab[ptr] + 2] & 0xff)) & 0xffff;
if (symtab[ptr + symtab[ptr] + 1] == DEFABS)
zpref = 1;
if (undef != 0)
zpref = 1;
return(svalue);
}
SHAR_EOF
if test -f 'assm3.c'
then
echo shar: over-writing existing file "'assm3.c'"
fi
cat << \SHAR_EOF > 'assm3.c'
#include "stdio.h"
#include "assm.d1"
#include "assm.d2"
/* class 1 machine operations processor - 1 byte, no operand field */
class1()
{
if (pass == LAST_PASS) {
loadlc(loccnt, 0, 1);
loadv(opval, 0, 1);
println();
}
loccnt++;
}
/* class 2 machine operations processor - 2 byte, relative addressing */
class2(ip)
int *ip;
{
if (pass == LAST_PASS) {
loadlc(loccnt, 0, 1);
loadv(opval, 0, 1);
while (prlnbuf[++(*ip)] == ' ');
if (evaluate(ip) != 0) {
loccnt += 2;
return;
}
loccnt += 2;
if ((value -= loccnt) >= -128 && value < 128) {
loadv(value, 1, 1);
println();
}
else error("Invalid branch address");
}
else loccnt += 2;
}
/* class 3 machine operations processor - various addressing modes */
class3(ip)
int *ip;
{
char ch;
int code;
int flag;
int i;
int ztmask;
while ((ch = prlnbuf[++(*ip)]) == ' ');
switch(ch) {
case 0:
case ';':
error("Operand field missing");
return;
case 'A':
case 'a':
if ((ch = prlnbuf[*ip + 1]) == ' ' || ch == 0) {
flag = ACC;
break;
}
default:
switch(ch = prlnbuf[*ip]) {
case '#': case '=':
flag = IMM1 | IMM2;
++(*ip);
break;
case '(':
flag = IND | INDX | INDY;
++(*ip);
break;
default:
flag = ABS | ZER | ZERX | ABSX | ABSY | ABSY2 | ZERY;
}
if ((flag & (INDX | INDY | ZER | ZERX | ZERY) & opflg) != 0)
udtype = UNDEFAB;
if (evaluate(ip) != 0)
return;
if (zpref != 0) {
flag &= (ABS | ABSX | ABSY | ABSY2 | IND | IMM1 | IMM2);
ztmask = 0;
}
else ztmask = ZER | ZERX | ZERY;
code = 0;
i = 0;
while (( ch = prlnbuf[(*ip)++]) != ' ' && ch != 0 && i++ < 4) {
code *= 8;
switch(ch) {
case ')': /* ) = 4 */
++code;
case ',': /* , = 3 */
++code;
case 'X': /* X = 2 */
case 'x':
++code;
case 'Y': /* Y = 1 */
case 'y':
++code;
break;
default:
flag = 0;
}
}
switch(code) {
case 0: /* no termination characters */
flag &= (ABS | ZER | IMM1 | IMM2);
break;
case 4: /* termination = ) */
flag &= IND;
break;
case 25: /* termination = ,Y */
flag &= (ABSY | ABSY2 | ZERY);
break;
case 26: /* termination = ,X */
flag &= (ABSX | ZERX);
break;
case 212: /* termination = ,X) */
flag &= INDX;
break;
case 281: /* termination = ),Y */
flag &= INDY;
break;
default:
flag = 0;
}
}
if ((opflg &= flag) == 0) {
error("Invalid addressing mode");
return;
}
if ((opflg & ztmask) != 0)
opflg &= ztmask;
switch(opflg) {
case ACC: /* single byte - class 3 */
if (pass == LAST_PASS) {
loadlc(loccnt, 0, 1);
loadv(opval + 8, 0, 1);
println();
}
loccnt++;
return;
case ZERX: case ZERY: /* double byte - class 3 */
opval += 4;
case INDY:
opval += 8;
case IMM2:
opval += 4;
case ZER:
opval += 4;
case INDX: case IMM1:
if (pass == LAST_PASS) {
loadlc(loccnt, 0, 1);
loadv(opval, 0, 1);
loadv(value, 1, 1);
println();
}
loccnt += 2;
return;
case IND: /* triple byte - class 3 */
opval += 16;
case ABSX:
case ABSY2:
opval += 4;
case ABSY:
opval += 12;
case ABS:
if (pass == LAST_PASS) {
opval += 12;
loadlc(loccnt, 0, 1);
loadv(opval, 0, 1);
loadv(value, 1, 1);
loadv(value >> 8, 2, 1);
println();
}
loccnt += 3;
return;
default:
error("Invalid addressing mode");
return;
}
}
/* pseudo operations processor */
pseudo(ip)
int *ip;
{
int count;
int i;
int tvalue;
int hibit; /* apple requires high bit to be on for chs */
int pi;
switch(opval) {
case 0: /* .byte pseudo */
labldef(loccnt);
loadlc(loccnt, 0, 1);
while (prlnbuf[++(*ip)] == ' '); /* field */
count = 0;
do {
if (prlnbuf[*ip] == '"') {
/* check for hibit on flag for ascii chs */
hibit = 0 ;
pi = *ip;
while((i = prlnbuf[++pi]) != '"' && i != 0 );
if (i != 0 )
while(prlnbuf[++pi] == ' ' ) ;
if (prlnbuf[pi] == '1' )
hibit = 0x80 ;
while ((tvalue = prlnbuf[++(*ip)]) != '"') {
if (tvalue == 0) {
error("Unterminated ASCII string");
return;
}
if (tvalue == '\\')
switch(tvalue = prlnbuf[++(*ip)]) {
case 'n':
tvalue = '\n';
break;
case 't':
tvalue = '\t';
break;
}
loccnt++;
if (pass == LAST_PASS) {
tvalue |= hibit ;
loadv(tvalue, count, 1);
if (++count >= 3) {
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
count = 0;
loadlc(loccnt, 0, 1);
}
}
}
++(*ip);
}
else {
if (evaluate(ip) != 0) {
loccnt++;
return;
}
loccnt++;
if (value > 0xff) {
error("Operand field size error");
return;
}
else if (pass == LAST_PASS) {
loadv(value, count, 1);
if (++count >= 3) {
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
count = 0;
loadlc(loccnt, 0, 1);
}
}
}
} while (prlnbuf[(*ip)++] == ',');
if ((pass == LAST_PASS) && (count != 0))
println();
return;
case 1: /* = pseudo */
while (prlnbuf[++(*ip)] == ' ');
if (evaluate(ip) != 0)
return;
labldef(value);
if (pass == LAST_PASS) {
loadlc(value, 1, 0);
println();
}
return;
case 2: /* .word pseudo */
labldef(loccnt);
loadlc(loccnt, 0, 1);
while (prlnbuf[++(*ip)] == ' ');
do {
if (evaluate(ip) != 0) {
loccnt += 2;
return;
}
loccnt += 2;
if (pass == LAST_PASS) {
loadv(value, 0, 1);
loadv(value>>8, 1, 1);
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
loadlc(loccnt, 0, 1);
}
} while (prlnbuf[(*ip)++] == ',');
return;
case 3: /* *= pseudo */
while (prlnbuf[++(*ip)] == ' ');
if (prlnbuf[*ip] == '*') {
if (evaluate(ip) != 0)
return;
if (undef != 0) {
error("Undefined symbol in operand field.");
return;
}
tvalue = loccnt;
}
else {
if (evaluate(ip) != 0)
return;
if (undef != 0) {
error("Undefined symbol in operand field.");
return;
}
tvalue = value;
}
loccnt = value;
labldef(tvalue);
if (pass == LAST_PASS) {
objcnt = 0;
loadlc(tvalue, 1, 0);
println();
}
return;
case 4: /* .list pseudo */
if (lflag >= 0)
lflag = 1;
return;
case 5: /* .nlst pseudo */
if (lflag >= 0)
lflag = iflag;
return;
case 6: /* .dbyt pseudo */
labldef(loccnt);
loadlc(loccnt, 0, 1);
while (prlnbuf[++(*ip)] == ' ');
do {
if (evaluate(ip) != 0) {
loccnt += 2;
return;
}
loccnt += 2;
if (pass == LAST_PASS) {
loadv(value>>8, 0, 1);
loadv(value, 1, 1);
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
loadlc(loccnt, 0, 1);
}
} while (prlnbuf[(*ip)++] == ',');
return;
case 7: /* ds pseudo */
while (prlnbuf[++(*ip)] == ' ');
if (evaluate(ip) != 0)
return;
if (undef != 0) {
error("Undefined symbol in operand field.");
return;
}
tvalue = loccnt;
labldef(loccnt);
loccnt += value;
if (pass == LAST_PASS) {
objcnt = 0;
loadlc(tvalue, 1, 0);
println();
}
return;
case 8: /* asc pseudo */
labldef(loccnt);
loadlc(loccnt, 0, 1);
while (prlnbuf[++(*ip)] == ' '); /* field */
count = 0;
do {
if (prlnbuf[*ip] == '\'') {
while ((tvalue = prlnbuf[++(*ip)]) != '\'') {
if (tvalue == 0) {
error("Unterminated ASCII string");
return;
}
if (tvalue == '\\')
switch(tvalue = prlnbuf[++(*ip)]) {
case 'n':
tvalue = '\n';
break;
case 't':
tvalue = '\t';
break;
}
loccnt++;
if (pass == LAST_PASS) {
tvalue |= msb ;
loadv(tvalue, count, 1);
if (++count >= 3) {
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
count = 0;
loadlc(loccnt, 0, 1);
}
}
}
++(*ip);
}
else {
if (evaluate(ip) != 0) {
loccnt++;
return;
}
loccnt++;
if (value > 0xff) {
error("Operand field size error");
return;
}
else if (pass == LAST_PASS) {
loadv(value, count, 1);
if (++count >= 3) {
println();
for (i = 0; i < SFIELD; i++)
prlnbuf[i] = ' ';
prlnbuf[i] = 0;
count = 0;
loadlc(loccnt, 0, 1);
}
}
}
} while (prlnbuf[(*ip)++] == ',');
if ((pass == LAST_PASS) && (count != 0))
println();
return;
case 13: /* msb pseudo */
while (prlnbuf[++(*ip)] == ' ');
if (pass == LAST_PASS)
println();
pi = *ip;
if (( i = 0x20|prlnbuf[pi+1] ) == 'f' ){
msb=0;
return;
}
else if (i=='n'){
msb=0x80;
return;
}
error("Invalid symbol in operand field.");
return;
}
}
/* evaluate expression */
evaluate(ip)
int *ip;
{
int tvalue;
int invalid;
int parflg, value2;
char ch;
char op;
char op2;
op = '+';
parflg = zpref = undef = value = invalid = 0;
/* hcj: zpref should reflect the value of the expression, not the value of
the intermediate symbols
*/
while ((ch=prlnbuf[*ip]) != ' ' && ch != ')' && ch != ',' && ch != ';') {
tvalue = 0;
if (ch == '$' || ch == '@' || ch == '%')
tvalue = colnum(ip);
else if (ch >= '0' && ch <= '9')
tvalue = colnum(ip);
else if (ch >= 'a' && ch <= 'z')
tvalue = symval(ip);
else if (ch >= 'A' && ch <= 'Z')
tvalue = symval(ip);
else if ((ch == '_') || (ch == '.'))
tvalue = symval(ip);
else if (ch == '*') {
tvalue = loccnt;
++(*ip);
}
else if (ch == '\'') {
++(*ip);
tvalue = prlnbuf[*ip] & 0xff;
++(*ip);
}
else if (ch == '[') {
if (parflg == 1) {
error("Too many ['s in expression");
invalid++;
}
else {
value2 = value;
op2 = op;
value = tvalue = 0;
op = '+';
parflg = 1;
}
goto next;
}
else if (ch == ']') {
if (parflg == 0) {
error("No matching [ for ] in expression");
invalid++;
}
else {
parflg = 0;
tvalue = value;
value = value2;
op = op2;
}
++(*ip);
}
switch(op) {
case '+':
value += tvalue;
break;
case '-':
value -= tvalue;
break;
case '/':
value = (unsigned) value/tvalue;
break;
case '*':
value *= tvalue;
break;
case '%':
value = (unsigned) value%tvalue;
break;
case '^':
value ^= tvalue;
break;
case '~':
value = ~tvalue;
break;
case '&':
value &= tvalue;
break;
case '|':
value |= tvalue;
break;
case '<':
tvalue >>= 8; /* fall through to '<' */
case '>':
if (value != 0) {
error("High or low byte operator not first in operand field");
}
value = tvalue & 0xff;
zpref = 0;
break;
default:
invalid++;
}
if ((op=prlnbuf[*ip]) == ' '
|| op == ')'
|| op == ','
|| op == ';')
break;
else if (op != ']')
next: ++(*ip);
}
if (parflg == 1) {
error("Missing ] in expression");
return(1);
}
if (value < 0 || value >= 256) {
zpref = 1;
}
if (undef != 0) {
if (pass != FIRST_PASS) {
error("Undefined symbol in operand field");
invalid++;
}
value = 0;
}
else if (invalid != 0)
{
error("Invalid operand field");
}
else {
/*
This is the only way out that may not signal error
*/
if (value < 0 || value >= 256) {
zpref = 1;
}
else {
zpref = 0;
}
}
return(invalid);
}
/* collect number operand */
colnum(ip)
int *ip;
{
int mul;
int nval;
char ch;
nval = 0;
if ((ch = prlnbuf[*ip]) == '$')
mul = 16;
else if (ch >= '1' && ch <= '9') {
mul = 10;
nval = ch - '0';
}
else if (ch == '@' || ch == '0')
mul = 8;
else if (ch == '%')
mul = 2;
while ((ch = prlnbuf[++(*ip)] - '0') >= 0) {
if (ch > 9) {
ch -= ('A' - '9' - 1);
if (ch > 15)
ch -= ('a' - 'A');
if (ch > 15)
break;
if (ch < 10)
break;
}
if (ch >= mul)
break;
nval = (nval * mul) + ch;
}
return(nval);
}
SHAR_EOF
# End of shell archive
exit 0