You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

248 lines
5.7 KiB
C

/* itest.c
* Copyright 1984-2017 Cisco Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define r_EOF 0
#define r_LPAREN 1
#define r_RPAREN 2
#define r_CONST 3
static INT digit_value(ICHAR c, INT r) {
switch (r) {
case 2:
if ('0' <= c && c <= '1') return c - '0';
break;
case 8:
if ('0' <= c && c <= '8') return c - '0';
break;
case 10:
if ('0' <= c && c <= '9') return c - '0';
break;
case 16:
if ('0' <= c && c <= '9') return c - '0';
if ('a' <= c && c <= 'f') return c - 'a';
if ('A' <= c && c <= 'F') return c - 'A';
default:
break;
}
return -1;
}
static INT read_int(ptr *v, ptr n, INT r, IBOOL sign) {
INT i, c;
for (;;) {
if ((i = digit_value((c = getchar()), r)) == -1) {
ungetc(c, stdin);
break;
}
n = S_add(S_mul(n, FIX(r)), FIX(i));
}
*v = sign ? S_sub(FIX(0), n) : n;
return r_CONST;
}
static INT read_token(ptr *v) {
ICHAR c = getchar();
switch (c) {
case SEOF: return r_EOF;
case '\n':
case ' ': return read_token(v);
case ';':
for (;;) {
switch (getchar()) {
case SEOF:
return r_EOF;
case '\n':
return read_token(v);
default:
break;
}
}
case '(': return r_LPAREN;
case ')': return r_RPAREN;
case '#': {
ICHAR c = getchar();
INT r = 10;
switch (c) {
case 'x':
r = 16;
case 'o':
if (r == 0) r = 8;
case 'b':
if (r == 10) r = 2;
case 'd': {
INT i;
IBOOL sign = 0;
c = getchar();
if (c == '+')
c = getchar();
else if (c == '-') {
sign = 1;
c = getchar();
}
if ((i = digit_value(c, r)) != -1)
return read_int(v, FIX(i), r, sign);
}
default:
printf("malformed hash prefix ignored\n");
return read_token(v);
}
}
case '+':
case '-': {
INT i, c2;
if ((i = digit_value((c2 = getchar()), 10)) == -1) {
ungetc(c2, stdin);
} else {
return read_int(v, FIX(i), 10, c == '-');
}
}
case '*':
case '/':
case 'q':
case 'r':
case 'g':
case '=':
case '<':
case 'f':
case 'c':
case 'd':
*v = Schar(c);
return r_CONST;
default: {
INT i;
if ((i = digit_value(c, 10)) != -1)
return read_int(v, FIX(i), 10, 0);
}
break;
}
printf("invalid character %d ignored\n", c);
return read_token(v);
}
static ptr readx(INT t, ptr v);
static ptr read_list(void) {
INT t; ptr v, x;
t = read_token(&v);
if (t == r_RPAREN) return Snil;
x = readx(t, v);
return Scons(x, read_list());
}
static ptr readx(INT t, ptr v) {
switch (t) {
case r_EOF:
printf("unexpected EOF\n");
exit(1);
case r_LPAREN: return read_list();
case r_RPAREN:
printf("unexpected right paren ignored\n");
t = read_token(&v);
return readx(t, v);
case r_CONST: return v;
default:
printf("invalid token %d\n", t);
exit(1);
}
}
static ptr read_top(void) {
INT t; ptr v;
t = read_token(&v);
switch (t) {
case r_EOF: return Seof_object;
case r_RPAREN: return read_top();
default: return readx(t, v);
}
}
static ptr eval(ptr x);
#define First(x) eval(Scar(Scdr(x)))
#define Second(x) eval(Scar(Scdr(Scdr(x))))
static ptr eval(ptr x) {
if (Spairp(x)) {
switch (Schar_value(Scar(x))) {
case '+': return S_add(First(x), Second(x));
case '-': return S_sub(First(x), Second(x));
case '*': return S_mul(First(x), Second(x));
case '/': return S_div(First(x), Second(x));
case 'q': return S_trunc(First(x), Second(x));
case 'r': return S_rem(First(x), Second(x));
case 'g': return S_gcd(First(x), Second(x));
case '=': {
ptr x1 = First(x), x2 = Second(x);
if (Sfixnump(x1) && Sfixnump(x2))
return Sboolean(x1 == x2);
else if (Sbignump(x1) && Sbignump(x2))
return Sboolean(S_big_eq(x1, x2));
else return Sfalse;
}
case '<': {
ptr x1 = First(x), x2 = Second(x);
if (Sfixnump(x1))
if (Sfixnump(x2))
return Sboolean(x1 < x2);
else
return Sboolean(!BIGSIGN(x2));
else
if (Sfixnump(x2))
return Sboolean(BIGSIGN(x1));
else
return Sboolean(S_big_lt(x1, x2));
}
case 'f': return Sflonum(S_floatify(First(x)));
case 'c':
S_gc(get_thread_context(), UNFIX(First(x)),UNFIX(Second(x)));
return Svoid;
case 'd': return S_decode_float(Sflonum_value(First(x)));
default:
S_prin1(x);
putchar('\n');
printf("unrecognized operator, returning zero\n");
return FIX(0);
}
} else
return x;
}
#undef PROMPT
#undef NOISY
static void bignum_test(void) {
ptr x;
for (;;) {
#ifdef PROMPT
putchar('*');
putchar(' ');
#endif
x = read_top();
if (x == Seof_object) { putchar('\n'); exit(0); }
#ifdef NOISY
S_prin1(x);
putchar('\n');
#endif
x = eval(x);
S_prin1(x);
putchar('\n');
}
}