|
|
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: 6702 (0x1a2e)
Types: TextFile
Notes: UNIX file
Names: »dc.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/dc/dc.c«
/*
* DC - Reverse Polish desk calculator (multi-precision)
* Depends on mint value being defined as a `char *'
* so mint may also be char string
*/
#include <stdio.h>
#include "bc.h"
#define NREG 256
#define NSTACK 256
struct reg_t {
struct reg_t *next;
rvalue regval;
} *reg[NREG];
rvalue stack[NSTACK],
*sp = &stack[0];
static char *soflmsg = "Out of pushdown",
*suflmsg = "stack empty",
*oospmsg = "Out of space",
*nregmsg = "Missing reg name";
#define skiperr(m) {fprintf(stderr,"%s\n",m);return(-1);}
#define push(x) {if(sp==&stack[NSTACK]){skiperr(soflmsg);}else{x=sp++;}}
#define pop(x) {if(sp==&stack[0]){skiperr(suflmsg);}else{x=--sp;}}
#define new(x) {push(x);minit(&(x)->mantissa);}
#define temp(x) {push(x);pop(x);}
#define tos(x) {pop(x);push(x);}
#define getreg(c,r){if((c=getc(infile))==EOF){skiperr(nregmsg);}else{r=reg[c];}}
#define newreg(c, r) {\
struct reg_t *nr=(struct reg_t *)malloc(sizeof(struct reg_t));\
if (nr == NULL) {\
skiperr(oospmsg);\
} else {\
nr->next = r;\
r = reg[c] = nr;\
}\
}
#define execute(x, y) if((x)->scale<0){\
FILE f;char *s=(x)->mantissa.val;if(y)minit(&(x)->mantissa);\
_stropen(s,strlen(s),&f);c=interp(&f);infile=fp;if(y)mpfree(s);\
if(c)return(c-1);}
main(argc, argv)
int argc;
char *argv[];
{
FILE *fp;
init();
if (argc > 1)
if ((fp=fopen(argv[1], "r"))==NULL) {
fprintf(stderr, "Dc: can't open %s\n", argv[1]);
return (1);
} else if (interp(fp) > 0)
return (0);
else
fclose(fp);
while (interp(stdin) < 0)
;
return (0);
}
interp(fp)
FILE *fp;
{
register int c;
register rvalue *a, *b;
struct reg_t *r;
int (*f)();
int d;
extern int iseq(), isne(), islt(), isle(), isge(), isgt();
extern int dcsub(), bcadd(), bcmul(), bcdiv(), bcrem(), bcexp();
extern int sibase(), sobase(), output();
infile = fp;
for (f=NULL;;f=NULL) switch (c = getc(infile)) {
case EOF:
return (0);
case ' ':
case '\t':
case '\n':
continue;
case '_':
c = getc(infile);
f = mneg;
/* Fall through */
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case '8': case '9': case 'A': case 'B':
case 'C': case 'D': case 'E': case 'F':
case '.':
push(a);
b = getnum(c);
*a = *b;
mpfree((char *)b);
if (f!=NULL)
(*f)(&a->mantissa, &a->mantissa);
continue;
case '-':
f = dcsub;
goto binary;
case '+':
f = bcadd;
goto binary;
case '*':
f = bcmul;
goto binary;
case '/':
f = bcdiv;
goto binary;
case '%':
f = bcrem;
goto binary;
case '^':
f = bcexp;
/* Fall through */
binary:
pop(b);
pop(a);
(*f)(b, a);
push(a);
continue;
case '[':
push(a);
if (c = rdstring(a))
return (c);
continue;
case '<':
f = islt;
goto compare;
case '=':
f = iseq;
goto compare;
case '>':
f = isgt;
goto compare;
case '!':
switch (c=getc(infile)) {
case '<':
f = isge;
goto compare;
case '=':
f = isne;
goto compare;
case '>':
f = isle;
goto compare;
default:
ungetc(c, infile);
temp(a);
rdline(a, infile);
system(a->mantissa.val);
printf("!\n");
mvfree(&a->mantissa);
continue;
}
compare:
pop(b);
pop(a);
d = (*f)(bccmp(b, a));
getreg(c, r);
if (d && r != NULL)
execute(&r->regval, 0);
continue;
case '?':
temp(a);
rdline(a, stdin);
execute(a, 1);
continue;
case 'c':
while (sp != &stack[0]) {
pop(a);
mvfree(&a->mantissa);
}
continue;
case 'd':
tos(a);
new(b);
mcopy(&a->mantissa, &b->mantissa);
b->scale = a->scale;
continue;
case 'f':
for (c = 0; c != NREG; c++)
if ((r=reg[c]) != NULL) {
printf("`%c': ", c);
output(&r->regval);
}
printf("stack:\n");
for (a = &stack[0]; a < sp; a++)
output(a);
continue;
case 'i':
f = sibase;
goto unary;
case 'I':
case 'K':
new(a);
mitom((c=='I' ? ibase : scale), &a->mantissa);
a->scale = 0;
continue;
case 'k':
pop(a);
scale = rtoint(a);
mvfree(&a->mantissa);
if (scale < 0) {
scale = 0;
skiperr("Scale < 0");
}
continue;
case 'l':
case 'L':
getreg(c, r);
new(a);
if (r == NULL) {
newscalar(a);
} else if (c == 'l') {
mcopy(&r->regval.mantissa, &a->mantissa);
a->scale = r->regval.scale;
} else {
reg[c] = r->next;
*a = r->regval;
free((char *)r);
}
continue;
case 'o':
f = sobase;
goto unary;
case 'O':
new(a);
mcopy(&outbase, &a->mantissa);
a->scale = 0;
continue;
case 'p':
tos(a);
output(a);
continue;
case 'P':
f = output;
/* Fall through */
unary:
pop(a);
(*f)(a);
mvfree(&a->mantissa);
continue;
case 'q':
return (1);
continue;
case 'Q':
pop(a);
c = rtoint(a);
mvfree(&a->mantissa);
return (--c > 0 ? c : 0);
continue;
case 's':
getreg(c, r);
pop(a);
if (r != NULL) {
mvfree(&r->regval.mantissa);
} else
newreg(c, r);
r->regval = *a;
continue;
case 'S':
getreg(c, r);
pop(a);
newreg(c, r);
r->regval = *a;
continue;
case 'v':
tos(a);
bcsqrt(a);
continue;
case 'x':
pop(a);
execute(a, 1);
continue;
case 'X':
tos(a);
mitom(a->scale, &a->mantissa);
a->scale = 0;
continue;
case 'z':
new(a);
mitom(sp - &stack[0], &a->mantissa);
a->scale = 0;
continue;
case 'Z':
{
char *s;
tos(a);
s = mtos(&a->mantissa);
mitom(strlen(s), &a->mantissa);
a->scale = 0;
mpfree(s);
}
continue;
default:
fprintf(stderr, "`%c'", c);
skiperr("?");
}
}
iseq(x)
{
return (x==0);
}
isne(x)
{
return (x!=0);
}
islt(x)
{
return (x<0);
}
isle(x)
{
return (x<=0);
}
isge(x)
{
return (x>=0);
}
isgt(x)
{
return (x>0);
}
rdstring(v)
rvalue *v;
{
register int c;
register char *s,
*str;
unsigned int len,
d = 0; /* nesting depth */
s = str = malloc(len=16);
while ((c=getc(infile)) != EOF) {
if (c == '[')
++d;
else if (c == ']' && d-- == 0)
break;
if (str != NULL)
*s++ = c;
if (s == &str[len]) {
str = realloc(str, len*=2);
s = &str[len/2];
}
}
if (str == NULL) {
skiperr(oospmsg);
} else if (c == EOF) {
skiperr("Missing ']'");
} else {
*s = '\0';
v->mantissa.val = str;
v->mantissa.len = len;
v->scale = -1;
return (0);
}
}
rdline(v, fp)
rvalue *v;
FILE *fp;
{
register int c;
register char *s,
*str;
unsigned int len;
s = str = malloc(len=16);
while ((c=getc(fp))!= EOF && c != '\n') {
if (str != NULL)
*s++ = c;
if (s == &str[len]) {
str = realloc(str, len*=2);
s = &str[len/2];
}
}
if (str == NULL) {
skiperr(oospmsg);
} else {
*s = '\0';
v->mantissa.val = str;
v->mantissa.len = len;
v->scale = -1;
return (0);
}
}
output(v)
rvalue *v;
{
if (v->scale < 0)
printf("%s\n", v->mantissa.val);
else {
putnum(v);
pnewln();
}
}