mpcalc.c
上传用户:shmaik
上传日期:2014-06-01
资源大小:45093k
文件大小:5k
- static char rcsid[] = "$Id: H:/drh/idioms/book/RCS/mp.doc,v 1.11 1996/06/26 23:02:01 drh Exp $";
- #include <ctype.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <limits.h>
- #include "mem.h"
- #include "seq.h"
- #include "fmt.h"
- #include "mp.h"
- Seq_T sp;
- int ibase = 10;
- int obase = 10;
- struct {
- char *fmt;
- MP_T (*add)(MP_T, MP_T, MP_T);
- MP_T (*sub)(MP_T, MP_T, MP_T);
- MP_T (*mul)(MP_T, MP_T, MP_T);
- MP_T (*div)(MP_T, MP_T, MP_T);
- MP_T (*mod)(MP_T, MP_T, MP_T);
- } s = { "%Dn",
- MP_add, MP_sub, MP_mul, MP_div, MP_mod },
- u = { "%Un",
- MP_addu, MP_subu, MP_mulu, MP_divu, MP_modu },
- *f = &s;
- MP_T pop(void) {
- if (Seq_length(sp) > 0)
- return Seq_remhi(sp);
- else {
- Fmt_fprint(stderr, "?stack underflown");
- return MP_new(0);
- }
- }
- int main(int argc, char *argv[]) {
- int c;
- sp = Seq_new(0);
- Fmt_register('D', MP_fmt);
- Fmt_register('U', MP_fmtu);
- while ((c = getchar()) != EOF) {
- MP_T x = NULL, y = NULL, z = NULL;
- TRY
- switch (c) {
- default:
- if (isprint(c))
- Fmt_fprint(stderr, "?'%c'", c);
- else
- Fmt_fprint(stderr, "?'\%03o'", c);
- Fmt_fprint(stderr, " is unimplementedn");
- break;
- case ' ': case 't': case 'n': case 'f': case 'r':
- break;
- case 'c': while (Seq_length(sp) > 0) {
- MP_T x = Seq_remhi(sp);
- FREE(x);
- } break;
- case 'q': while (Seq_length(sp) > 0) {
- MP_T x = Seq_remhi(sp);
- FREE(x);
- }
- Seq_free(&sp);
- return EXIT_SUCCESS;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9': {
- char buf[512];
- z = MP_new(0);
- {
- int i = 0;
- for ( ; strchr(&"zyxwvutsrqponmlkjihgfedcba9876543210"[36-ibase],
- tolower(c)); c = getchar(), i++)
- if (i < (int)sizeof (buf) - 1)
- buf[i] = c;
- if (i > (int)sizeof (buf) - 1) {
- i = (int)sizeof (buf) - 1;
- Fmt_fprint(stderr,
- "?integer constant exceeds %d digitsn", i);
- }
- buf[i] = ' ';
- if (c != EOF)
- ungetc(c, stdin);
- }
- MP_fromstr(z, buf, ibase, NULL);
- break;
- }
- case '+': y = pop(); x = pop();
- z = MP_new(0); (*f->add)(z, x, y); break;
- case '-': y = pop(); x = pop();
- z = MP_new(0); (*f->sub)(z, x, y); break;
- case '*': y = pop(); x = pop();
- z = MP_new(0); (*f->mul)(z, x, y); break;
- case '/': y = pop(); x = pop();
- z = MP_new(0); (*f->div)(z, x, y); break;
- case '%': y = pop(); x = pop();
- z = MP_new(0); (*f->mod)(z, x, y); break;
- case '&': y = pop(); x = pop();
- z = MP_new(0); MP_and(z, x, y); break;
- case '|': y = pop(); x = pop();
- z = MP_new(0); MP_or (z, x, y); break;
- case '^': y = pop(); x = pop();
- z = MP_new(0); MP_xor(z, x, y); break;
- case '!': z = pop(); MP_not(z, z); break;
- case '~': z = pop(); MP_neg(z, z); break;
- case 'i': case 'o': {
- long n;
- x = pop();
- n = MP_toint(x);
- if (n < 2 || n > 36)
- Fmt_fprint(stderr, "?%d is an illegal basen",n);
- else if (c == 'i')
- ibase = n;
- else
- obase = n;
- if (obase == 2 || obase == 8 || obase == 16)
- f = &u;
- else
- f = &s;
- break;
- }
- case 'p':
- Fmt_print(f->fmt, z = pop(), obase);
- break;
- case 'f': {
- int n = Seq_length(sp);
- while (--n > 0)
- Fmt_print(f->fmt, Seq_get(sp, n), obase);
- break;
- }
- case '<': { long s;
- y = pop();
- z = pop();
- s = MP_toint(y);
- if (s < 0 || s > INT_MAX) {
- Fmt_fprint(stderr,
- "?%d is an illegal shift amountn", s);
- break;
- }; MP_lshift(z, z, s); break; }
- case '>': { long s;
- y = pop();
- z = pop();
- s = MP_toint(y);
- if (s < 0 || s > INT_MAX) {
- Fmt_fprint(stderr,
- "?%d is an illegal shift amountn", s);
- break;
- }; MP_rshift(z, z, s); break; }
- case 'k': {
- long n;
- x = pop();
- n = MP_toint(x);
- if (n < 2 || n > INT_MAX)
- Fmt_fprint(stderr,
- "?%d is an illegal precisionn", n);
- else if (Seq_length(sp) > 0)
- Fmt_fprint(stderr, "?nonempty stackn");
- else
- MP_set(n);
- break;
- }
- case 'd': {
- MP_T x = pop();
- z = MP_new(0);
- Seq_addhi(sp, x);
- MP_addui(z, x, 0);
- break;
- }
- }
- EXCEPT(MP_Overflow)
- Fmt_fprint(stderr, "?overflown");
- EXCEPT(MP_Dividebyzero)
- Fmt_fprint(stderr, "?divide by 0n");
- END_TRY;
- if (z)
- Seq_addhi(sp, z);
- FREE(x);
- FREE(y);
- }
- while (Seq_length(sp) > 0) {
- MP_T x = Seq_remhi(sp);
- FREE(x);
- }
- Seq_free(&sp);
- return EXIT_SUCCESS;
- }