2013-09-04 15:25:18 +02:00
|
|
|
/* mpicalc.c - test the mpi functions
|
|
|
|
* Copyright (C) 1997, 1998, 1999, 2004, 2006 Werner Koch
|
1997-11-18 15:06:00 +01:00
|
|
|
*
|
1998-04-14 19:51:16 +02:00
|
|
|
* This is an RPN calculator; values must be given in hex.
|
|
|
|
* Operation is like dc(1) except that the input/output radix is
|
1997-11-18 15:06:00 +01:00
|
|
|
* always 16 and you can use a '-' to prefix a negative number.
|
1998-04-14 19:51:16 +02:00
|
|
|
* Addition operators: ++ and --. All operators must be delimited by a blank
|
1997-11-18 15:06:00 +01:00
|
|
|
*
|
2013-09-04 15:25:18 +02:00
|
|
|
* WARNING: This is an old test utility which is not anymore
|
|
|
|
* maintained as part of GnuPG. However, Libgcrypt has a
|
|
|
|
* copy of it which uses the libgcrypt functions.
|
1997-11-18 15:06:00 +01:00
|
|
|
*
|
1998-12-23 13:41:40 +01:00
|
|
|
* This file is part of GnuPG.
|
1997-11-18 15:06:00 +01:00
|
|
|
*
|
1998-12-23 13:41:40 +01:00
|
|
|
* GnuPG is free software; you can redistribute it and/or modify
|
1997-11-18 15:06:00 +01:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2007-10-23 12:48:09 +02:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1997-11-18 15:06:00 +01:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
1998-12-23 13:41:40 +01:00
|
|
|
* GnuPG is distributed in the hope that it will be useful,
|
1997-11-18 15:06:00 +01:00
|
|
|
* 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
|
2007-10-23 12:48:09 +02:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
1997-11-18 15:06:00 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#include "util.h"
|
2002-06-29 15:46:34 +02:00
|
|
|
#include "mpi.h"
|
1998-02-09 18:43:42 +01:00
|
|
|
#include "i18n.h"
|
1997-11-18 15:06:00 +01:00
|
|
|
|
|
|
|
#define STACKSIZE 100
|
|
|
|
static MPI stack[STACKSIZE];
|
|
|
|
static int stackidx;
|
|
|
|
|
|
|
|
|
2002-06-29 15:46:34 +02:00
|
|
|
const char *
|
|
|
|
strusage( int level )
|
1997-11-18 15:06:00 +01:00
|
|
|
{
|
|
|
|
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;
|
2002-06-29 15:46:34 +02:00
|
|
|
default: p = default_strusage(level);
|
1997-11-18 15:06:00 +01:00
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-02-09 18:43:42 +01:00
|
|
|
static void
|
|
|
|
i18n_init(void)
|
|
|
|
{
|
2003-05-24 20:38:35 +02:00
|
|
|
#ifdef ENABLE_NLS
|
|
|
|
setlocale( LC_ALL, "" );
|
2006-12-11 20:54:53 +01:00
|
|
|
bindtextdomain (PACKAGE, LOCALEDIR);
|
2003-05-24 20:38:35 +02:00
|
|
|
textdomain( PACKAGE );
|
|
|
|
#endif
|
1998-02-09 18:43:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-11-18 15:06:00 +01:00
|
|
|
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--;
|
|
|
|
}
|
|
|
|
|
1999-06-08 13:41:46 +02:00
|
|
|
static void
|
|
|
|
do_mulm(void)
|
|
|
|
{
|
|
|
|
if( stackidx < 3 ) {
|
|
|
|
fputs("stack underflow\n", stderr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mpi_mulm( stack[stackidx-3], stack[stackidx-3],
|
|
|
|
stack[stackidx-2], stack[stackidx-1] );
|
|
|
|
stackidx -= 2;
|
|
|
|
}
|
|
|
|
|
1997-11-18 15:06:00 +01:00
|
|
|
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;
|
|
|
|
}
|
1997-11-24 23:24:04 +01:00
|
|
|
mpi_invm( a, stack[stackidx-2], stack[stackidx-1] );
|
1997-11-18 15:06:00 +01:00
|
|
|
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--;
|
|
|
|
}
|
|
|
|
|
1997-11-19 14:12:23 +01:00
|
|
|
static void
|
|
|
|
do_rshift(void)
|
|
|
|
{
|
|
|
|
if( stackidx < 1 ) {
|
|
|
|
fputs("stack underflow\n", stderr);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
|
|
|
|
}
|
|
|
|
|
1997-11-18 15:06:00 +01:00
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
static ARGPARSE_OPTS opts[] = {
|
|
|
|
{0} };
|
1998-12-10 20:20:47 +01:00
|
|
|
ARGPARSE_ARGS pargs;
|
1997-11-18 15:06:00 +01:00
|
|
|
int i, c;
|
|
|
|
int state = 0;
|
|
|
|
char strbuf[1000];
|
|
|
|
int stridx=0;
|
|
|
|
|
1998-12-10 20:20:47 +01:00
|
|
|
pargs.argc = &argc;
|
|
|
|
pargs.argv = &argv;
|
|
|
|
pargs.flags = 0;
|
|
|
|
|
1998-02-09 18:43:42 +01:00
|
|
|
i18n_init();
|
1997-11-18 15:06:00 +01:00
|
|
|
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 */
|
1999-06-08 13:41:46 +02:00
|
|
|
if( isdigit(c) ) {
|
1997-11-18 15:06:00 +01:00
|
|
|
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;
|
1999-06-08 13:41:46 +02:00
|
|
|
case 'm':
|
|
|
|
do_mulm();
|
|
|
|
break;
|
1997-11-18 15:06:00 +01:00
|
|
|
case '/':
|
|
|
|
do_div();
|
|
|
|
break;
|
|
|
|
case '%':
|
|
|
|
do_rem();
|
|
|
|
break;
|
|
|
|
case '^':
|
|
|
|
do_powm();
|
|
|
|
break;
|
|
|
|
case 'I':
|
|
|
|
do_inv();
|
|
|
|
break;
|
|
|
|
case 'G':
|
|
|
|
do_gcd();
|
|
|
|
break;
|
1997-11-19 14:12:23 +01:00
|
|
|
case '>':
|
|
|
|
do_rshift();
|
|
|
|
break;
|
1997-11-18 15:06:00 +01:00
|
|
|
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 */
|
1999-06-08 13:41:46 +02:00
|
|
|
if( !isxdigit(c) ) { /* store the number */
|
1997-11-18 15:06:00 +01:00
|
|
|
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;
|
|
|
|
}
|