Output armor works, RSA keygen works.
[gnupg.git] / tools / mpicalc.c
1 /* mpitest.c - test the mpi functions
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This is a RPN calculator; values must be given in hex.
5  * Operaion is like dc(1) except that the input/output radix is
6  * always 16 and you can use a '-' to prefix a negative number.
7  * Addition operators: ++ and --. All operators must be delimeted by a blank
8  *
9  *
10  * This file is part of G10.
11  *
12  * G10 is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * G10 is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
25  */
26
27 #include <config.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31
32 #include "util.h"
33 #include "mpi.h"
34
35 #define STACKSIZE  100
36 static MPI stack[STACKSIZE];
37 static int stackidx;
38
39
40 const char *
41 strusage( int level )
42 {
43     const char *p;
44     switch( level ) {
45       case 10:
46       case 0:   p = "mpicalc - v" VERSION "; "
47                     "Copyright 1997 Werner Koch (dd9jn)" ; break;
48       case 13:  p = "mpicalc"; break;
49       case 14:  p = VERSION; break;
50       case 1:
51       case 11:  p = "Usage: mpicalc (-h for help)";
52                 break;
53       case 2:
54       case 12:  p =
55     "\nSyntax: mpicalc [options] [files]\n"
56     "MPI RPN calculator\n";
57         break;
58       default:  p = default_strusage(level);
59     }
60     return p;
61 }
62
63
64 static void
65 do_add(void)
66 {
67     if( stackidx < 2 ) {
68         fputs("stack underflow\n",stderr);
69         return;
70     }
71     mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
72     stackidx--;
73 }
74
75 static void
76 do_sub(void)
77 {
78     if( stackidx < 2 ) {
79         fputs("stack underflow\n", stderr);
80         return;
81     }
82     mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
83     stackidx--;
84 }
85
86 static void
87 do_inc(void)
88 {
89     if( stackidx < 1 ) {
90         fputs("stack underflow\n", stderr);
91         return;
92     }
93     mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 );
94 }
95
96 static void
97 do_dec(void)
98 {
99     if( stackidx < 1 ) {
100         fputs("stack underflow\n", stderr);
101         return;
102     }
103  /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
104 }
105
106 static void
107 do_mul(void)
108 {
109     if( stackidx < 2 ) {
110         fputs("stack underflow\n", stderr);
111         return;
112     }
113     mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
114     stackidx--;
115 }
116
117 static void
118 do_div(void)
119 {
120     if( stackidx < 2 ) {
121         fputs("stack underflow\n", stderr);
122         return;
123     }
124     mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
125     stackidx--;
126 }
127
128 static void
129 do_rem(void)
130 {
131     if( stackidx < 2 ) {
132         fputs("stack underflow\n", stderr);
133         return;
134     }
135     mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
136     stackidx--;
137 }
138
139 static void
140 do_powm(void)
141 {
142     MPI a;
143     if( stackidx < 3 ) {
144         fputs("stack underflow\n", stderr);
145         return;
146     }
147     a= mpi_alloc(10);
148     mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] );
149     mpi_free(stack[stackidx-3]);
150     stack[stackidx-3] = a;
151     stackidx -= 2;
152 }
153
154 static void
155 do_inv(void)
156 {
157     MPI a = mpi_alloc(40);
158     if( stackidx < 2 ) {
159         fputs("stack underflow\n", stderr);
160         return;
161     }
162     mpi_inv_mod( a, stack[stackidx-2], stack[stackidx-1] );
163     mpi_set(stack[stackidx-2],a);
164     mpi_free(a);
165     stackidx--;
166 }
167
168 static void
169 do_gcd(void)
170 {
171     MPI a = mpi_alloc(40);
172     if( stackidx < 2 ) {
173         fputs("stack underflow\n", stderr);
174         return;
175     }
176     mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] );
177     mpi_set(stack[stackidx-2],a);
178     mpi_free(a);
179     stackidx--;
180 }
181
182 static void
183 do_rshift(void)
184 {
185     if( stackidx < 1 ) {
186         fputs("stack underflow\n", stderr);
187         return;
188     }
189     mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
190 }
191
192
193 int
194 main(int argc, char **argv)
195 {
196     static ARGPARSE_OPTS opts[] = {
197     {0} };
198     ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
199     int i, c;
200     int state = 0;
201     char strbuf[1000];
202     int stridx=0;
203
204     while( arg_parse( &pargs, opts) ) {
205         switch( pargs.r_opt ) {
206           default : pargs.err = 2; break;
207         }
208     }
209     if( argc )
210         usage(1);
211
212
213     for(i=0; i < STACKSIZE; i++ )
214         stack[i] = NULL;
215     stackidx =0;
216
217     while( (c=getc(stdin)) != EOF ) {
218         if( !state ) {  /* waiting */
219             if( isdigit(c) || (c >='A' && c <= 'F') ) {
220                 state = 1;
221                 ungetc(c, stdin);
222                 strbuf[0] = '0';
223                 strbuf[1] = 'x';
224                 stridx=2;
225             }
226             else if( isspace(c) )
227                 ;
228             else {
229                 switch(c) {
230                   case '+':
231                     if( (c=getc(stdin)) == '+' )
232                         do_inc();
233                     else {
234                         ungetc(c, stdin);
235                         do_add();
236                     }
237                     break;
238                   case '-':
239                     if( (c=getc(stdin)) == '-' )
240                         do_dec();
241                     else if( isdigit(c) || (c >='A' && c <= 'F') ) {
242                         state = 1;
243                         ungetc(c, stdin);
244                         strbuf[0] = '-';
245                         strbuf[1] = '0';
246                         strbuf[2] = 'x';
247                         stridx=3;
248                     }
249                     else {
250                         ungetc(c, stdin);
251                         do_sub();
252                     }
253                     break;
254                   case '*':
255                     do_mul();
256                     break;
257                   case '/':
258                     do_div();
259                     break;
260                   case '%':
261                     do_rem();
262                     break;
263                   case '^':
264                     do_powm();
265                     break;
266                   case 'I':
267                     do_inv();
268                     break;
269                   case 'G':
270                     do_gcd();
271                     break;
272                   case '>':
273                     do_rshift();
274                     break;
275                   case 'i': /* dummy */
276                     if( !stackidx )
277                         fputs("stack underflow\n", stderr);
278                     else {
279                         mpi_free(stack[stackidx-1]);
280                         stackidx--;
281                     }
282                     break;
283                   case 'd': /* duplicate the tos */
284                     if( !stackidx )
285                         fputs("stack underflow\n", stderr);
286                     else if( stackidx < STACKSIZE ) {
287                         mpi_free(stack[stackidx]);
288                         stack[stackidx] = mpi_copy( stack[stackidx-1] );
289                         stackidx++;
290                     }
291                     else
292                         fputs("stack overflow\n", stderr);
293                     break;
294                   case 'c':
295                     for(i=0; i < stackidx; i++ )
296                         mpi_free(stack[i]), stack[i] = NULL;
297                     stackidx = 0;
298                     break;
299                   case 'p': /* print the tos */
300                     if( !stackidx )
301                         puts("stack is empty");
302                     else {
303                         mpi_print(stdout, stack[stackidx-1], 1 );
304                         putchar('\n');
305                     }
306                     break;
307                   case 'f': /* print the stack */
308                     for( i = stackidx-1 ; i >= 0; i-- ) {
309                         printf("[%2d]: ", i );
310                         mpi_print(stdout, stack[i], 1 );
311                         putchar('\n');
312                     }
313                     break;
314                   default:
315                     fputs("invalid operator\n", stderr);
316                 }
317             }
318         }
319         else if( state == 1 ) { /* in a number */
320             if( !(isdigit(c) || (c >='A' && c <= 'F')) ) { /* store the number */
321                 state = 0;
322                 ungetc(c, stdin);
323                 if( stridx < 1000 )
324                     strbuf[stridx] = 0;
325
326                 if( stackidx < STACKSIZE ) {
327                     if( !stack[stackidx] )
328                         stack[stackidx] = mpi_alloc(10);
329                     if( mpi_fromstr(stack[stackidx], strbuf) )
330                         fputs("invalid number\n", stderr);
331                     else
332                         stackidx++;
333                 }
334                 else
335                     fputs("stack overflow\n", stderr);
336             }
337             else { /* store digit */
338                 if( stridx < 999 )
339                     strbuf[stridx++] = c;
340                 else if( stridx == 999 ) {
341                     strbuf[stridx] = 0;
342                     fputs("string too large - truncated\n", stderr);
343                     stridx++;
344                 }
345             }
346         }
347
348     }
349     for(i=0; i < stackidx; i++ )
350         mpi_free(stack[i]);
351     return 0;
352 }
353
354