summaryrefslogtreecommitdiffstats
path: root/comm/third_party/libgcrypt/src/mpicalc.c
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/libgcrypt/src/mpicalc.c')
-rw-r--r--comm/third_party/libgcrypt/src/mpicalc.c627
1 files changed, 627 insertions, 0 deletions
diff --git a/comm/third_party/libgcrypt/src/mpicalc.c b/comm/third_party/libgcrypt/src/mpicalc.c
new file mode 100644
index 0000000000..0903e0a4d3
--- /dev/null
+++ b/comm/third_party/libgcrypt/src/mpicalc.c
@@ -0,0 +1,627 @@
+/* mpicalc.c - Simple RPN calculator using gcry_mpi functions
+ * Copyright (C) 1997, 1998, 1999, 2004, 2006, 2013 Werner Koch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ This program is a simple RPN calculator which was originally used
+ to develop the mpi functions of GnuPG. Values must be given in
+ hex. Operation is like dc(1) except that the input/output radix is
+ always 16 and you can use a '-' to prefix a negative number.
+ Addition operators: ++ and --. All operators must be delimited by
+ a blank.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#ifdef _GCRYPT_IN_LIBGCRYPT
+# undef _GCRYPT_IN_LIBGCRYPT
+# include "gcrypt.h"
+#else
+# include <gcrypt.h>
+#endif
+
+
+#define MPICALC_VERSION "2.0"
+#define NEED_LIBGCRYPT_VERSION "1.6.0"
+
+#define STACKSIZE 500
+static gcry_mpi_t stack[STACKSIZE];
+static int stackidx;
+
+
+static int
+scan_mpi (gcry_mpi_t retval, const char *string)
+{
+ gpg_error_t err;
+ gcry_mpi_t val;
+
+ err = gcry_mpi_scan (&val, GCRYMPI_FMT_HEX, string, 0, NULL);
+ if (err)
+ {
+ fprintf (stderr, "scanning input failed: %s\n", gpg_strerror (err));
+ return -1;
+ }
+ mpi_set (retval, val);
+ mpi_release (val);
+ return 0;
+}
+
+
+static void
+print_mpi (gcry_mpi_t a)
+{
+ gpg_error_t err;
+ char *buf;
+ void *bufaddr = &buf;
+
+ err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
+ if (err)
+ fprintf (stderr, "[error printing number: %s]\n", gpg_strerror (err));
+ else
+ {
+ fputs (buf, stdout);
+ gcry_free (buf);
+ }
+}
+
+
+
+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--;
+}
+
+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;
+}
+
+static void
+do_div (void)
+{
+ if (stackidx < 2)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ mpi_fdiv (stack[stackidx - 2], NULL,
+ stack[stackidx - 2], stack[stackidx - 1]);
+ stackidx--;
+}
+
+static void
+do_rem (void)
+{
+ if (stackidx < 2)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ mpi_mod (stack[stackidx - 2],
+ stack[stackidx - 2], stack[stackidx - 1]);
+ stackidx--;
+}
+
+static void
+do_powm (void)
+{
+ gcry_mpi_t a;
+ if (stackidx < 3)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ a = mpi_new (0);
+ mpi_powm (a, stack[stackidx - 3], stack[stackidx - 2], stack[stackidx - 1]);
+ mpi_release (stack[stackidx - 3]);
+ stack[stackidx - 3] = a;
+ stackidx -= 2;
+}
+
+static void
+do_inv (void)
+{
+ gcry_mpi_t a;
+
+ if (stackidx < 2)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ a = mpi_new (0);
+ mpi_invm (a, stack[stackidx - 2], stack[stackidx - 1]);
+ mpi_set (stack[stackidx - 2], a);
+ mpi_release (a);
+ stackidx--;
+}
+
+static void
+do_gcd (void)
+{
+ gcry_mpi_t a;
+
+ if (stackidx < 2)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ a = mpi_new (0);
+ mpi_gcd (a, stack[stackidx - 2], stack[stackidx - 1]);
+ mpi_set (stack[stackidx - 2], a);
+ mpi_release (a);
+ stackidx--;
+}
+
+static void
+do_lshift (void)
+{
+ if (stackidx < 1)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ mpi_lshift (stack[stackidx - 1], stack[stackidx - 1], 1);
+}
+
+static void
+do_rshift (void)
+{
+ if (stackidx < 1)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ mpi_rshift (stack[stackidx - 1], stack[stackidx - 1], 1);
+}
+
+static void
+do_nbits (void)
+{
+ unsigned int n;
+
+ if (stackidx < 1)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ n = mpi_get_nbits (stack[stackidx - 1]);
+ mpi_set_ui (stack[stackidx - 1], n);
+}
+
+
+static void
+do_primecheck (void)
+{
+ gpg_error_t err;
+
+ if (stackidx < 1)
+ {
+ fputs ("stack underflow\n", stderr);
+ return;
+ }
+ err = gcry_prime_check (stack[stackidx - 1], 0);
+ mpi_set_ui (stack[stackidx - 1], !err);
+ if (err && gpg_err_code (err) != GPG_ERR_NO_PRIME)
+ fprintf (stderr, "checking prime failed: %s\n", gpg_strerror (err));
+}
+
+
+static int
+my_getc (void)
+{
+ static int shown;
+ int c;
+
+ for (;;)
+ {
+ if ((c = getc (stdin)) == EOF)
+ return EOF;
+ if (!(c & 0x80))
+ return c;
+
+ if (!shown)
+ {
+ shown = 1;
+ fputs ("note: Non ASCII characters are ignored\n", stderr);
+ }
+ }
+}
+
+
+static void
+print_help (void)
+{
+ fputs ("+ add [0] := [1] + [0] {-1}\n"
+ "- subtract [0] := [1] - [0] {-1}\n"
+ "* multiply [0] := [1] * [0] {-1}\n"
+ "/ divide [0] := [1] / [0] {-1}\n"
+ "% modulo [0] := [1] % [0] {-1}\n"
+ "< left shift [0] := [0] << 1 {0}\n"
+ "> right shift [0] := [0] >> 1 {0}\n"
+ "++ increment [0] := [0]++ {0}\n"
+ "-- decrement [0] := [0]-- {0}\n"
+ "m multiply mod [0] := [2] * [1] mod [0] {-2}\n"
+ "^ power mod [0] := [2] ^ [1] mod [0] {-2}\n"
+ "I inverse mod [0] := [1]^-1 mod [0] {-1}\n"
+ "G gcd [0] := gcd([1],[0]) {-1}\n"
+ "i remove item [0] := [1] {-1}\n"
+ "d dup item [-1] := [0] {+1}\n"
+ "r reverse [0] := [1], [1] := [0] {0}\n"
+ "b # of bits [0] := nbits([0]) {0}\n"
+ "P prime check [0] := is_prime([0])?1:0 {0}\n"
+ "c clear stack\n"
+ "p print top item\n"
+ "f print the stack\n"
+ "# ignore until end of line\n"
+ "? print this help\n"
+ , stdout);
+}
+
+
+
+int
+main (int argc, char **argv)
+{
+ const char *pgm;
+ int last_argc = -1;
+ int print_config = 0;
+ int i, c;
+ int state = 0;
+ char strbuf[4096];
+ int stridx = 0;
+
+ if (argc)
+ {
+ pgm = strrchr (*argv, '/');
+ if (pgm)
+ pgm++;
+ else
+ pgm = *argv;
+ argc--; argv++;
+ }
+ else
+ pgm = "?";
+
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--version")
+ || !strcmp (*argv, "--help"))
+ {
+ printf ("%s " MPICALC_VERSION "\n"
+ "libgcrypt %s\n"
+ "Copyright (C) 1997, 2013 Werner Koch\n"
+ "License LGPLv2.1+: GNU LGPL version 2.1 or later "
+ "<http://gnu.org/licenses/old-licenses/lgpl-2.1.html>\n"
+ "This is free software: you are free to change and "
+ "redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n"
+ "\n"
+ "Syntax: mpicalc [options]\n"
+ "Simple interactive big integer RPN calculator\n"
+ "\n"
+ "Options:\n"
+ " --version print version information\n"
+ " --print-config print the Libgcrypt config\n"
+ " --disable-hwf NAME disable feature NAME\n",
+ pgm, gcry_check_version (NULL));
+ exit (0);
+ }
+ else if (!strcmp (*argv, "--print-config"))
+ {
+ argc--; argv++;
+ print_config = 1;
+ }
+ else if (!strcmp (*argv, "--disable-hwf"))
+ {
+ argc--; argv++;
+ if (argc)
+ {
+ if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL))
+ fprintf (stderr, "%s: unknown hardware feature `%s'"
+ " - option ignored\n", pgm, *argv);
+ argc--; argv++;
+ }
+ }
+ }
+
+ if (argc)
+ {
+ fprintf (stderr, "usage: %s [options] (--help for help)\n", pgm);
+ exit (1);
+ }
+
+ if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
+ {
+ fprintf (stderr, "%s: Libgcrypt is too old (need %s, have %s)\n",
+ pgm, NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
+ exit (1);
+ }
+ gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
+ gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
+ if (print_config)
+ {
+ gcry_control (GCRYCTL_PRINT_CONFIG, stdout);
+ exit (0);
+ }
+
+ for (i = 0; i < STACKSIZE; i++)
+ stack[i] = NULL;
+ stackidx = 0;
+
+ while ((c = my_getc ()) != EOF)
+ {
+ if (!state) /* waiting */
+ {
+ if (isdigit (c))
+ {
+ state = 1;
+ ungetc (c, stdin);
+ strbuf[0] = '0';
+ strbuf[1] = 'x';
+ stridx = 2;
+ }
+ else if (isspace (c))
+ ;
+ else
+ {
+ switch (c)
+ {
+ case '#':
+ state = 2;
+ break;
+ case '+':
+ if ((c = my_getc ()) == '+')
+ do_inc ();
+ else
+ {
+ ungetc (c, stdin);
+ do_add ();
+ }
+ break;
+ case '-':
+ if ((c = my_getc ()) == '-')
+ do_dec ();
+ else if (isdigit (c)
+ || (c >= 'A' && c <= 'F')
+ || (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;
+ case 'm':
+ do_mulm ();
+ break;
+ case '/':
+ do_div ();
+ break;
+ case '%':
+ do_rem ();
+ break;
+ case '^':
+ do_powm ();
+ break;
+ case '<':
+ do_lshift ();
+ break;
+ case '>':
+ do_rshift ();
+ break;
+ case 'I':
+ do_inv ();
+ break;
+ case 'G':
+ do_gcd ();
+ break;
+ case 'i': /* dummy */
+ if (!stackidx)
+ fputs ("stack underflow\n", stderr);
+ else
+ {
+ mpi_release (stack[stackidx - 1]);
+ stackidx--;
+ }
+ break;
+ case 'd': /* duplicate the tos */
+ if (!stackidx)
+ fputs ("stack underflow\n", stderr);
+ else if (stackidx < STACKSIZE)
+ {
+ mpi_release (stack[stackidx]);
+ stack[stackidx] = mpi_copy (stack[stackidx - 1]);
+ stackidx++;
+ }
+ else
+ fputs ("stack overflow\n", stderr);
+ break;
+ case 'r': /* swap top elements */
+ if (stackidx < 2)
+ fputs ("stack underflow\n", stderr);
+ else if (stackidx < STACKSIZE)
+ {
+ gcry_mpi_t tmp = stack[stackidx-1];
+ stack[stackidx-1] = stack[stackidx - 2];
+ stack[stackidx-2] = tmp;
+ }
+ break;
+ case 'b':
+ do_nbits ();
+ break;
+ case 'P':
+ do_primecheck ();
+ break;
+ case 'c':
+ for (i = 0; i < stackidx; i++)
+ {
+ mpi_release (stack[i]); stack[i] = NULL;
+ }
+ stackidx = 0;
+ break;
+ case 'p': /* print the tos */
+ if (!stackidx)
+ puts ("stack is empty");
+ else
+ {
+ print_mpi (stack[stackidx - 1]);
+ putchar ('\n');
+ }
+ break;
+ case 'f': /* print the stack */
+ for (i = stackidx - 1; i >= 0; i--)
+ {
+ printf ("[%2d]: ", i);
+ print_mpi (stack[i]);
+ putchar ('\n');
+ }
+ break;
+ case '?':
+ print_help ();
+ break;
+ default:
+ fputs ("invalid operator\n", stderr);
+ }
+ }
+ }
+ else if (state == 1) /* In a number. */
+ {
+ if (!isxdigit (c))
+ {
+ /* Store the number */
+ state = 0;
+ ungetc (c, stdin);
+ if (stridx < sizeof strbuf)
+ strbuf[stridx] = 0;
+
+ if (stackidx < STACKSIZE)
+ {
+ if (!stack[stackidx])
+ stack[stackidx] = mpi_new (0);
+ if (scan_mpi (stack[stackidx], strbuf))
+ fputs ("invalid number\n", stderr);
+ else
+ stackidx++;
+ }
+ else
+ fputs ("stack overflow\n", stderr);
+ }
+ else
+ { /* Store a digit. */
+ if (stridx < sizeof strbuf - 1)
+ strbuf[stridx++] = c;
+ else if (stridx == sizeof strbuf - 1)
+ {
+ strbuf[stridx] = 0;
+ fputs ("input too large - truncated\n", stderr);
+ stridx++;
+ }
+ }
+ }
+ else if (state == 2) /* In a comment. */
+ {
+ if (c == '\n')
+ state = 0;
+ }
+
+ }
+
+ for (i = 0; i < stackidx; i++)
+ mpi_release (stack[i]);
+ return 0;
+}