* keygen.c (proc_parameter_file): Default key and subkey usage flags to
[gnupg.git] / tools / mpicalc.c
1 /* mpitest.c - test the mpi functions
2  *      Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3  *
4  * This is an RPN calculator; values must be given in hex.
5  * Operation 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 delimited by a blank
8  *
9  *
10  * This file is part of GnuPG.
11  *
12  * GnuPG 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  * GnuPG 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
25  * USA.
26  */
27
28 #include <config.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32
33 #include "util.h"
34 #include "mpi.h"
35 #include "i18n.h"
36
37 #define STACKSIZE  100
38 static MPI stack[STACKSIZE];
39 static int stackidx;
40
41
42 const char *
43 strusage( int level )
44 {
45     const char *p;
46     switch( level ) {
47       case 10:
48       case 0:   p = "mpicalc - v" VERSION "; "
49                     "Copyright 1997 Werner Koch (dd9jn)" ; break;
50       case 13:  p = "mpicalc"; break;
51       case 14:  p = VERSION; break;
52       case 1:
53       case 11:  p = "Usage: mpicalc (-h for help)";
54                 break;
55       case 2:
56       case 12:  p =
57     "\nSyntax: mpicalc [options] [files]\n"
58     "MPI RPN calculator\n";
59         break;
60       default:  p = default_strusage(level);
61     }
62     return p;
63 }
64
65
66 static void
67 i18n_init(void)
68 {
69 #ifdef ENABLE_NLS
70   setlocale( LC_ALL, "" );
71   bindtextdomain( PACKAGE, G10_LOCALEDIR );
72   textdomain( PACKAGE );
73 #endif
74 }
75
76
77 static void
78 do_add(void)
79 {
80     if( stackidx < 2 ) {
81         fputs("stack underflow\n",stderr);
82         return;
83     }
84     mpi_add( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
85     stackidx--;
86 }
87
88 static void
89 do_sub(void)
90 {
91     if( stackidx < 2 ) {
92         fputs("stack underflow\n", stderr);
93         return;
94     }
95     mpi_sub( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
96     stackidx--;
97 }
98
99 static void
100 do_inc(void)
101 {
102     if( stackidx < 1 ) {
103         fputs("stack underflow\n", stderr);
104         return;
105     }
106     mpi_add_ui( stack[stackidx-1], stack[stackidx-1], 1 );
107 }
108
109 static void
110 do_dec(void)
111 {
112     if( stackidx < 1 ) {
113         fputs("stack underflow\n", stderr);
114         return;
115     }
116  /* mpi_sub_ui( stack[stackidx-1], stack[stackidx-1], 1 ); */
117 }
118
119 static void
120 do_mul(void)
121 {
122     if( stackidx < 2 ) {
123         fputs("stack underflow\n", stderr);
124         return;
125     }
126     mpi_mul( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
127     stackidx--;
128 }
129
130 static void
131 do_mulm(void)
132 {
133     if( stackidx < 3 ) {
134         fputs("stack underflow\n", stderr);
135         return;
136     }
137     mpi_mulm( stack[stackidx-3], stack[stackidx-3],
138                                  stack[stackidx-2], stack[stackidx-1] );
139     stackidx -= 2;
140 }
141
142 static void
143 do_div(void)
144 {
145     if( stackidx < 2 ) {
146         fputs("stack underflow\n", stderr);
147         return;
148     }
149     mpi_fdiv_q( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
150     stackidx--;
151 }
152
153 static void
154 do_rem(void)
155 {
156     if( stackidx < 2 ) {
157         fputs("stack underflow\n", stderr);
158         return;
159     }
160     mpi_fdiv_r( stack[stackidx-2], stack[stackidx-2], stack[stackidx-1] );
161     stackidx--;
162 }
163
164 static void
165 do_powm(void)
166 {
167     MPI a;
168     if( stackidx < 3 ) {
169         fputs("stack underflow\n", stderr);
170         return;
171     }
172     a= mpi_alloc(10);
173     mpi_powm( a, stack[stackidx-3], stack[stackidx-2], stack[stackidx-1] );
174     mpi_free(stack[stackidx-3]);
175     stack[stackidx-3] = a;
176     stackidx -= 2;
177 }
178
179 static void
180 do_inv(void)
181 {
182     MPI a = mpi_alloc(40);
183     if( stackidx < 2 ) {
184         fputs("stack underflow\n", stderr);
185         return;
186     }
187     mpi_invm( a, stack[stackidx-2], stack[stackidx-1] );
188     mpi_set(stack[stackidx-2],a);
189     mpi_free(a);
190     stackidx--;
191 }
192
193 static void
194 do_gcd(void)
195 {
196     MPI a = mpi_alloc(40);
197     if( stackidx < 2 ) {
198         fputs("stack underflow\n", stderr);
199         return;
200     }
201     mpi_gcd( a, stack[stackidx-2], stack[stackidx-1] );
202     mpi_set(stack[stackidx-2],a);
203     mpi_free(a);
204     stackidx--;
205 }
206
207 static void
208 do_rshift(void)
209 {
210     if( stackidx < 1 ) {
211         fputs("stack underflow\n", stderr);
212         return;
213     }
214     mpi_rshift( stack[stackidx-1],stack[stackidx-1], 1 );
215 }
216
217
218 int
219 main(int argc, char **argv)
220 {
221     static ARGPARSE_OPTS opts[] = {
222     {0} };
223     ARGPARSE_ARGS pargs;
224     int i, c;
225     int state = 0;
226     char strbuf[1000];
227     int stridx=0;
228
229     pargs.argc = &argc;
230     pargs.argv = &argv;
231     pargs.flags = 0;
232
233     i18n_init();
234     while( arg_parse( &pargs, opts) ) {
235         switch( pargs.r_opt ) {
236           default : pargs.err = 2; break;
237         }
238     }
239     if( argc )
240         usage(1);
241
242
243     for(i=0; i < STACKSIZE; i++ )
244         stack[i] = NULL;
245     stackidx =0;
246
247     while( (c=getc(stdin)) != EOF ) {
248         if( !state ) {  /* waiting */
249             if( isdigit(c) ) {
250                 state = 1;
251                 ungetc(c, stdin);
252                 strbuf[0] = '0';
253                 strbuf[1] = 'x';
254                 stridx=2;
255             }
256             else if( isspace(c) )
257                 ;
258             else {
259                 switch(c) {
260                   case '+':
261                     if( (c=getc(stdin)) == '+' )
262                         do_inc();
263                     else {
264                         ungetc(c, stdin);
265                         do_add();
266                     }
267                     break;
268                   case '-':
269                     if( (c=getc(stdin)) == '-' )
270                         do_dec();
271                     else if( isdigit(c) || (c >='A' && c <= 'F') ) {
272                         state = 1;
273                         ungetc(c, stdin);
274                         strbuf[0] = '-';
275                         strbuf[1] = '0';
276                         strbuf[2] = 'x';
277                         stridx=3;
278                     }
279                     else {
280                         ungetc(c, stdin);
281                         do_sub();
282                     }
283                     break;
284                   case '*':
285                     do_mul();
286                     break;
287                   case 'm':
288                     do_mulm();
289                     break;
290                   case '/':
291                     do_div();
292                     break;
293                   case '%':
294                     do_rem();
295                     break;
296                   case '^':
297                     do_powm();
298                     break;
299                   case 'I':
300                     do_inv();
301                     break;
302                   case 'G':
303                     do_gcd();
304                     break;
305                   case '>':
306                     do_rshift();
307                     break;
308                   case 'i': /* dummy */
309                     if( !stackidx )
310                         fputs("stack underflow\n", stderr);
311                     else {
312                         mpi_free(stack[stackidx-1]);
313                         stackidx--;
314                     }
315                     break;
316                   case 'd': /* duplicate the tos */
317                     if( !stackidx )
318                         fputs("stack underflow\n", stderr);
319                     else if( stackidx < STACKSIZE ) {
320                         mpi_free(stack[stackidx]);
321                         stack[stackidx] = mpi_copy( stack[stackidx-1] );
322                         stackidx++;
323                     }
324                     else
325                         fputs("stack overflow\n", stderr);
326                     break;
327                   case 'c':
328                     for(i=0; i < stackidx; i++ )
329                         mpi_free(stack[i]), stack[i] = NULL;
330                     stackidx = 0;
331                     break;
332                   case 'p': /* print the tos */
333                     if( !stackidx )
334                         puts("stack is empty");
335                     else {
336                         mpi_print(stdout, stack[stackidx-1], 1 );
337                         putchar('\n');
338                     }
339                     break;
340                   case 'f': /* print the stack */
341                     for( i = stackidx-1 ; i >= 0; i-- ) {
342                         printf("[%2d]: ", i );
343                         mpi_print(stdout, stack[i], 1 );
344                         putchar('\n');
345                     }
346                     break;
347                   default:
348                     fputs("invalid operator\n", stderr);
349                 }
350             }
351         }
352         else if( state == 1 ) { /* in a number */
353             if( !isxdigit(c) ) { /* store the number */
354                 state = 0;
355                 ungetc(c, stdin);
356                 if( stridx < 1000 )
357                     strbuf[stridx] = 0;
358
359                 if( stackidx < STACKSIZE ) {
360                     if( !stack[stackidx] )
361                         stack[stackidx] = mpi_alloc(10);
362                     if( mpi_fromstr(stack[stackidx], strbuf) )
363                         fputs("invalid number\n", stderr);
364                     else
365                         stackidx++;
366                 }
367                 else
368                     fputs("stack overflow\n", stderr);
369             }
370             else { /* store digit */
371                 if( stridx < 999 )
372                     strbuf[stridx++] = c;
373                 else if( stridx == 999 ) {
374                     strbuf[stridx] = 0;
375                     fputs("string too large - truncated\n", stderr);
376                     stridx++;
377                 }
378             }
379         }
380
381     }
382     for(i=0; i < stackidx; i++ )
383         mpi_free(stack[i]);
384     return 0;
385 }