|
|
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: 5240 (0x1478)
Types: TextFile
Notes: UNIX file
Names: »interp.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/bc/interp.c«
#include <stdio.h>
#include <setjmp.h>
#include <assert.h>
#include "bc.h"
/*
* The jump buffer bcmenv is used to hold the environment of
* the bc-machine interpreter. If some error is detected while
* executing some bc-machine code, after an error message is
* printed, return is to the environment saved here.
*/
static jmp_buf bcmenv;
/*
* Interp is the routine which interprets bc-machine code.
*/
interp()
{
stkent stack[MAXSTACK];
register stkent *tos = &stack[-1];
register code *pc = cstream;
register rvalue *temp;
stkent *frame;
func *fnc;
if (setjmp(bcmenv))
return;
for (;;) {
if (tos >= &stack[MAXSTACK - 1])
bcmerr("Out of runtime stack");
switch (pc++->opcode) {
case LOAD:
temp = tos->lvalue;
minit(&tos->rvalue.mantissa);
mcopy(&temp->mantissa, &tos->rvalue.mantissa);
tos->rvalue.scale = temp->scale;
break;
case LIBASE:
minit(&(++tos)->rvalue.mantissa);
mitom(ibase, &tos->rvalue.mantissa);
tos->rvalue.scale = 0;
break;
case LOBASE:
minit(&(++tos)->rvalue.mantissa);
mcopy(&outbase, &tos->rvalue.mantissa);
tos->rvalue.scale = 0;
break;
case LSCALE:
minit(&(++tos)->rvalue.mantissa);
mitom(scale, &tos->rvalue.mantissa);
tos->rvalue.scale = 0;
break;
case STORE:
temp = (--tos)->lvalue;
*tos = tos[1];
mcopy(&tos->rvalue.mantissa, &temp->mantissa);
temp->scale = tos->rvalue.scale;
break;
case SIBASE:
sibase(&tos->rvalue);
break;
case SOBASE:
sobase(&tos->rvalue);
break;
case SSCALE:
sscale(&tos->rvalue);
break;
case POP:
mvfree(&tos--->rvalue.mantissa);
break;
case PRVAL:
temp = tos++->lvalue;
minit(&tos->rvalue.mantissa);
mcopy(&temp->mantissa, &tos->rvalue.mantissa);
tos->rvalue.scale = temp->scale;
break;
case PGLSC:
(++tos)->lvalue = pc++->lvalue;
break;
case PLOSC:
(++tos)->lvalue = &frame[pc++->ivalue].rvalue;
break;
case PGLAE:
temp = select(pc++->alvalue, rtoint(&tos->rvalue));
mvfree(&tos->rvalue.mantissa);
tos->lvalue = temp;
break;
case PLOAE:
temp = select(frame[pc++->ivalue].alvalue,
rtoint(&tos->rvalue));
mvfree(&tos->rvalue.mantissa);
tos->lvalue = temp;
break;
case PGLAR:
(++tos)->alvalue = pc++->alvalue;
break;
case PLOAR:
(++tos)->alvalue = frame[pc++->ivalue].alvalue;
break;
case STOP:
return;
case CALL:
chkcall(pc[0].dvalue, pc[1].ivalue);
fnc = &pc->dvalue->globalv.fvalue;
tos = pauto(fnc, tos, &stack[MAXSTACK-1]);
tos->bcstate.spc = pc + 2;
tos->bcstate.sfp = frame;
tos->bcstate.stos = frame = newframe(fnc, tos);
pc = fnc->body;
break;
case RETURN:
temp = &tos->rvalue;
bcclean(&pc->dvalue->globalv.fvalue, tos - 2);
pc = tos[-1].bcstate.spc;
frame = tos[-1].bcstate.sfp;
tos = tos[-1].bcstate.stos;
tos->rvalue = *temp;
break;
case INC:
madd(&tos->rvalue.mantissa, pow10(tos->rvalue.scale),
&tos->rvalue.mantissa);
break;
case DEC:
msub(&tos->rvalue.mantissa, pow10(tos->rvalue.scale),
&tos->rvalue.mantissa);
break;
case PRNUM:
putnum(&tos->rvalue);
mvfree(&dot.mantissa);
dot = tos->rvalue;
--tos;
break;
case PRSTR:
pstring(pc++->svalue, 0);
break;
case PRNL:
pnewln();
break;
case LENGTH:
mitom(tos->rvalue.mantissa.len, &tos->rvalue.mantissa);
tos->rvalue.scale = 0;
break;
case SCALE:
mitom(tos->rvalue.scale, &tos->rvalue.mantissa);
tos->rvalue.scale = 0;
break;
case SQRT:
bcsqrt(&tos->rvalue);
break;
case ADD:
bcadd(&tos[0].rvalue, &tos[-1].rvalue);
--tos;
break;
case SUB:
mneg(&tos[0].rvalue.mantissa,
&tos[0].rvalue.mantissa);
bcadd(&tos[0].rvalue, &tos[-1].rvalue);
--tos;
break;
case MUL:
bcmul(&tos[0].rvalue, &tos[-1].rvalue);
--tos;
break;
case DIV:
bcdiv(&tos[0].rvalue, &tos[-1].rvalue);
--tos;
break;
case REM:
bcrem(&tos[0].rvalue, &tos[-1].rvalue);
--tos;
break;
case EXP:
bcexp(&tos[0].rvalue, &tos[-1].rvalue);
--tos;
break;
case NEG:
mneg(&tos[0].rvalue.mantissa, &tos[0].rvalue.mantissa);
break;
case BRALW:
pc += pc->address;
break;
case BRNEV:
pc += 2;
break;
case BRLT:
if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) < 0)
pc += pc->address;
else
++pc;
tos -= 2;
break;
case BRLE:
if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) <= 0)
pc += pc->address;
else
++pc;
tos -= 2;
break;
case BREQ:
if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) == 0)
pc += pc->address;
else
++pc;
tos -= 2;
break;
case BRGE:
if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) >= 0)
pc += pc->address;
else
++pc;
tos -= 2;
break;
case BRGT:
if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) > 0)
pc += pc->address;
else
++pc;
tos -= 2;
break;
case BRNE:
if (bccmp(&tos[0].rvalue, &tos[-1].rvalue) != 0)
pc += pc->address;
else
++pc;
tos -= 2;
break;
default:
assert(FALSE);
}
}
}
/*
* Bcmerr is called when any bc-machine error occurrs.
* It prints out an error message and causes interp to
* return.
*/
bcmerr(str)
char *str;
{
fprintf(stderr, "%r\n", &str);
longjmp(bcmenv, TRUE);
}