~ubuntu-branches/ubuntu/jaunty/gnupg2/jaunty

« back to all changes in this revision

Viewing changes to tools/mpicalc.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Urlichs
  • Date: 2006-01-24 04:31:42 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060124043142-pbg192or6qxv3yk2
Tags: 1.9.20-1
* New Upstream version. Closes:#306890,#344530
  * Closes:#320490: gpg-protect-tool fails to decrypt PKCS-12 files 
* Depend on libopensc2-dev, not -1-. Closes:#348106

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
}
 
389
 
 
390