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