aboutsummaryrefslogtreecommitdiffstats
path: root/tools/mpicalc.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mpicalc.c')
-rw-r--r--tools/mpicalc.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/tools/mpicalc.c b/tools/mpicalc.c
new file mode 100644
index 000000000..2402695d7
--- /dev/null
+++ b/tools/mpicalc.c
@@ -0,0 +1,341 @@
+/* mpitest.c - test the mpi functions
+ * Copyright (c) 1997 by Werner Koch (dd9jn)
+ *
+ * This is a RPN calculator; values must be given in hex.
+ * Operaion is like dc(1) except that the input/output radix is
+ * always 16 and you can use a '-' to prefix a negative number.
+ * Addition operators: ++ and --. All operators must be delimeted by a blank
+ *
+ *
+ * This file is part of G10.
+ *
+ * G10 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * G10 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "util.h"
+#include "mpi.h"
+
+#define STACKSIZE 100
+static MPI stack[STACKSIZE];
+static int stackidx;
+
+
+const char *
+strusage( int level )
+{
+ const char *p;
+ switch( level ) {
+ case 10:
+ case 0: p = "mpicalc - v" VERSION "; "
+ "Copyright 1997 Werner Koch (dd9jn)" ; break;
+ case 13: p = "mpicalc"; break;
+ case 14: p = VERSION; break;
+ case 1:
+ case 11: p = "Usage: mpicalc (-h for help)";
+ break;
+ case 2:
+ case 12: p =
+ "\nSyntax: mpicalc [options] [files]\n"
+ "MPI RPN calculator\n";
+ break;
+ default: p = default_strusage(level);
+ }
+ return p;
+}
+
+
+static void
+do_add(void)
+{
+ if( stackidx < 2 ) {
+ fputs("stack underflow\n",stderr);
+ return;
+ }
+ mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+ stackidx--;
+}
+
+static void
+do_sub(void)
+{
+ if( stackidx < 2 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+ stackidx--;
+}
+
+static void
+do_inc(void)
+{
+ if( stackidx < 1 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 );
+}
+
+static void
+do_dec(void)
+{
+ if( stackidx < 1 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
+}
+
+static void
+do_mul(void)
+{
+ if( stackidx < 2 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+ stackidx--;
+}
+
+static void
+do_div(void)
+{
+ if( stackidx < 2 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+ stackidx--;
+}
+
+static void
+do_rem(void)
+{
+ if( stackidx < 2 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
+ stackidx--;
+}
+
+static void
+do_powm(void)
+{
+ MPI a;
+ if( stackidx < 3 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ a= mpi_alloc(10);
+ mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] );
+ mpi_free(stack[stackidx-3]);
+ stack[stackidx-3] = a;
+ stackidx -= 2;
+}
+
+static void
+do_inv(void)
+{
+ MPI a = mpi_alloc(40);
+ if( stackidx < 2 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ mpi_inv_mod( a, stack[stackidx-2], stack[stackidx-1] );
+ mpi_set(stack[stackidx-2],a);
+ mpi_free(a);
+ stackidx--;
+}
+
+static void
+do_gcd(void)
+{
+ MPI a = mpi_alloc(40);
+ if( stackidx < 2 ) {
+ fputs("stack underflow\n", stderr);
+ return;
+ }
+ mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] );
+ mpi_set(stack[stackidx-2],a);
+ mpi_free(a);
+ stackidx--;
+}
+
+
+int
+main(int argc, char **argv)
+{
+ static ARGPARSE_OPTS opts[] = {
+ {0} };
+ ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
+ int i, c;
+ int state = 0;
+ char strbuf[1000];
+ int stridx=0;
+
+ while( arg_parse( &pargs, opts) ) {
+ switch( pargs.r_opt ) {
+ default : pargs.err = 2; break;
+ }
+ }
+ if( argc )
+ usage(1);
+
+
+ for(i=0; i < STACKSIZE; i++ )
+ stack[i] = NULL;
+ stackidx =0;
+
+ while( (c=getc(stdin)) != EOF ) {
+ if( !state ) { /* waiting */
+ if( isdigit(c) || (c >='A' && c <= 'F') ) {
+ state = 1;
+ ungetc(c, stdin);
+ strbuf[0] = '0';
+ strbuf[1] = 'x';
+ stridx=2;
+ }
+ else if( isspace(c) )
+ ;
+ else {
+ switch(c) {
+ case '+':
+ if( (c=getc(stdin)) == '+' )
+ do_inc();
+ else {
+ ungetc(c, stdin);
+ do_add();
+ }
+ break;
+ case '-':
+ if( (c=getc(stdin)) == '-' )
+ do_dec();
+ else if( isdigit(c) || (c >='A' && c <= 'F') ) {
+ state = 1;
+ ungetc(c, stdin);
+ strbuf[0] = '-';
+ strbuf[1] = '0';
+ strbuf[2] = 'x';
+ stridx=3;
+ }
+ else {
+ ungetc(c, stdin);
+ do_sub();
+ }
+ break;
+ case '*':
+ do_mul();
+ break;
+ case '/':
+ do_div();
+ break;
+ case '%':
+ do_rem();
+ break;
+ case '^':
+ do_powm();
+ break;
+ case 'I':
+ do_inv();
+ break;
+ case 'G':
+ do_gcd();
+ break;
+ case 'i': /* dummy */
+ if( !stackidx )
+ fputs("stack underflow\n", stderr);
+ else {
+ mpi_free(stack[stackidx-1]);
+ stackidx--;
+ }
+ break;
+ case 'd': /* duplicate the tos */
+ if( !stackidx )
+ fputs("stack underflow\n", stderr);
+ else if( stackidx < STACKSIZE ) {
+ mpi_free(stack[stackidx]);
+ stack[stackidx] = mpi_copy( stack[stackidx-1] );
+ stackidx++;
+ }
+ else
+ fputs("stack overflow\n", stderr);
+ break;
+ case 'c':
+ for(i=0; i < stackidx; i++ )
+ mpi_free(stack[i]), stack[i] = NULL;
+ stackidx = 0;
+ break;
+ case 'p': /* print the tos */
+ if( !stackidx )
+ puts("stack is empty");
+ else {
+ mpi_print(stdout, stack[stackidx-1], 1 );
+ putchar('\n');
+ }
+ break;
+ case 'f': /* print the stack */
+ for( i = stackidx-1 ; i >= 0; i-- ) {
+ printf("[%2d]: ", i );
+ mpi_print(stdout, stack[i], 1 );
+ putchar('\n');
+ }
+ break;
+ default:
+ fputs("invalid operator\n", stderr);
+ }
+ }
+ }
+ else if( state == 1 ) { /* in a number */
+ if( !(isdigit(c) || (c >='A' && c <= 'F')) ) { /* store the number */
+ state = 0;
+ ungetc(c, stdin);
+ if( stridx < 1000 )
+ strbuf[stridx] = 0;
+
+ if( stackidx < STACKSIZE ) {
+ if( !stack[stackidx] )
+ stack[stackidx] = mpi_alloc(10);
+ if( mpi_fromstr(stack[stackidx], strbuf) )
+ fputs("invalid number\n", stderr);
+ else
+ stackidx++;
+ }
+ else
+ fputs("stack overflow\n", stderr);
+ }
+ else { /* store digit */
+ if( stridx < 999 )
+ strbuf[stridx++] = c;
+ else if( stridx == 999 ) {
+ strbuf[stridx] = 0;
+ fputs("string too large - truncated\n", stderr);
+ stridx++;
+ }
+ }
+ }
+
+ }
+ for(i=0; i < stackidx; i++ )
+ mpi_free(stack[i]);
+ return 0;
+}
+
+