Merged silc_1_0_branch to trunk.
authorPekka Riikonen <priikone@silcnet.org>
Tue, 10 May 2005 18:31:12 +0000 (18:31 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 10 May 2005 18:31:12 +0000 (18:31 +0000)
170 files changed:
CHANGES
Makefile.ad
Makefile.defines.in
Makefile.defines_int.in
README.CVS
README.DIST
TODO-1.0
apps/Makefile.ad
apps/autodist/CHANGES
apps/autodist/TODO
apps/autodist/autodist.in
apps/autodist/doc/autodist.1.in
apps/autodist/doc/autodist.texi
apps/autodist/tests/Makefile.am
apps/autodist/tests/autodist1.test
apps/autodist/tests/autodist6.test [new file with mode: 0755]
apps/autodist/tests/autodist7.test [new file with mode: 0755]
apps/irssi/configure.ad [new file with mode: 0644]
apps/irssi/src/fe-text/Makefile.am
apps/irssi/src/perl/silc/Makefile.PL.in
apps/irssi/src/silc/core/silc-core.c
apps/silcd/Makefile.am
apps/silcd/command.c
apps/silcd/command.h
apps/silcd/command_reply.c
apps/silcd/configure.ad
apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/server.h
apps/silcd/server_query.c
apps/silcd/server_util.c
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
apps/silcd/silcd.c
apps/silcstress/Makefile.am [new file with mode: 0644]
apps/silcstress/configure.ad [new file with mode: 0644]
apps/silcstress/silcstress.c [new file with mode: 0644]
configure.ad
distdir/TOOLKIT [new file with mode: 0644]
distdir/TOOLKIT-header [new file with mode: 0644]
distdir/common
distdir/default
distdir/post-process-dist
distdir/pre-dist-toolkit [new file with mode: 0644]
distdir/pre-run
distdir/toolkit
doc/Makefile.ad
doc/example_silcd.conf.in
includes/silcincludes.h.in
includes/silcwin32.h
lib/Makefile.ad
lib/configure.ad
lib/contrib/Makefile.ad [moved from lib/contrib/Makefile.am with 72% similarity]
lib/contrib/getopt.c [deleted file]
lib/contrib/getopt.h [deleted file]
lib/contrib/getopt1.c [deleted file]
lib/contrib/getopti.c [new file with mode: 0644]
lib/contrib/getopti.h [new file with mode: 0644]
lib/contrib/regex.c [deleted file]
lib/contrib/regex.h [deleted file]
lib/contrib/regexpr.c [new file with mode: 0644]
lib/contrib/regexpr.h [new file with mode: 0644]
lib/doc/building.html
lib/doc/command_reply_args.html
lib/doc/silcclient_using.html
lib/silc.pc.in
lib/silcclient.pc.in
lib/silcclient/client_ops_example.c
lib/silcclient/command.c
lib/silcclient/command.h
lib/silcclient/command_reply.c
lib/silcclient/command_reply.h
lib/silccore/silcchannel.h
lib/silccore/silccommand.h
lib/silccore/silcid.c
lib/silccore/silcid.h
lib/silccore/silcidcache.c
lib/silccore/silcidcache.h
lib/silccore/silcmode.h
lib/silccore/silcnotify.h
lib/silccore/silcpacket.h
lib/silccrypt/aes.h
lib/silccrypt/blowfish.h
lib/silccrypt/blowfish_internal.h
lib/silccrypt/cast.h
lib/silccrypt/cast_internal.h
lib/silccrypt/ciphers.h
lib/silccrypt/ciphers_def.h
lib/silccrypt/md5.h
lib/silccrypt/md5_internal.h
lib/silccrypt/none.c
lib/silccrypt/none.h
lib/silccrypt/rc5.h
lib/silccrypt/rc5_internal.h
lib/silccrypt/rijndael_internal.h
lib/silccrypt/rsa.c
lib/silccrypt/rsa_internal.h
lib/silccrypt/silccipher.c
lib/silccrypt/silccipher.h
lib/silccrypt/silchmac.c
lib/silccrypt/twofish.h
lib/silccrypt/twofish_internal.h
lib/silcmath/Makefile.ad
lib/silcmath/configure.ad [new file with mode: 0644]
lib/silcmath/modinv.c
lib/silcmath/mp_gmp.c
lib/silcmath/mp_gmp.h
lib/silcmath/mp_tfm.c [new file with mode: 0644]
lib/silcmath/mp_tfm.h [new file with mode: 0644]
lib/silcmath/mp_tma.c [moved from lib/silcmath/mp_mpi.c with 74% similarity]
lib/silcmath/mp_tma.h [moved from lib/silcmath/mp_mpi.h with 60% similarity]
lib/silcmath/mpbin.c
lib/silcmath/silcmath.h
lib/silcmath/silcmp.h
lib/silcmath/silcprimegen.c
lib/silcmath/tfm.c [new file with mode: 0644]
lib/silcmath/tfm.h [new file with mode: 0644]
lib/silcmath/tma.c [new file with mode: 0644]
lib/silcmath/tma.h [new file with mode: 0644]
lib/silcmath/tma_class.h [new file with mode: 0644]
lib/silcmath/tma_superclass.h [new file with mode: 0644]
lib/silcsftp/silcsftp.h
lib/silcsftp/silcsftp_fs.h
lib/silcsim/Makefile.ad
lib/silcsim/silcsim.c
lib/silcsim/silcsim.h
lib/silcsim/silcsimutil.c
lib/silcsim/silcsimutil.h
lib/silcske/groups.c
lib/silcske/groups_internal.h
lib/silcske/silcske.c
lib/silcutil/Makefile.ad
lib/silcutil/silcbuffmt.c
lib/silcutil/silcconfig.c
lib/silcutil/silcconfig.h
lib/silcutil/silchashtable.c
lib/silcutil/silclog.c
lib/silcutil/silclog.h
lib/silcutil/silclog_i.h [new file with mode: 0644]
lib/silcutil/silcmutex.h
lib/silcutil/silcnet.c
lib/silcutil/silcnet.h
lib/silcutil/silcprotocol.c
lib/silcutil/silcprotocol.h
lib/silcutil/silcschedule.c
lib/silcutil/silcschedule.h
lib/silcutil/silcschedule_i.h
lib/silcutil/silcthread.h
lib/silcutil/tests/Makefile.am
lib/silcutil/tests/test_silclist.c [new file with mode: 0644]
lib/silcutil/tests/test_silcstrutil.c
lib/silcutil/unix/silcunixmutex.c
lib/silcutil/unix/silcunixnet.c
lib/silcutil/unix/silcunixthread.c
lib/silcutil/unix/silcunixutil.c
lib/silcutil/win32/silcwin32mutex.c
lib/silcutil/win32/silcwin32net.c
lib/silcutil/win32/silcwin32schedule.c
lib/silcutil/win32/silcwin32sockconn.c
lib/silcutil/win32/silcwin32thread.c
lib/silcutil/win32/silcwin32util.c
scripts/silcdoc/gen.sh
scripts/silcdoc/gen_detail.php
scripts/silcdoc/gen_html_detail.php
scripts/silcdoc/gen_index.php
scripts/silcdoc/silcdoc
win32/libsilc/libsilc.def
win32/libsilc/libsilc.dsp
win32/libsilc_static/libsilc_static.dsp
win32/silcdefs.h

diff --git a/CHANGES b/CHANGES
index baa76976ec81ad6840411b329770317b81371ab5..9b437dcf48958bb73b7c8f4d567e25670e44586f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,83 @@
+Tue May 10 15:11:53 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Rewritten SILC Log API.  Affected files lib/silcutil/silclog.[ch].
+
+Mon May  9 12:00:08 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed channel public key list saving on JOIN command reply
+         on backup router.  Affected file apps/silcd/command_reply.c.
+
+Mon May  2 10:42:49 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added default limit how many channels client can join,
+         default is 50.  Added 'channel_join_limit' configuration
+         option to server too.  Affected files are apps/silcd/command.c
+         and serverconfig.[ch].
+
+Sun May  1 17:42:55 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * --without-silc -> --with-silc, --without-irssi -> --with-irssi.
+         On Toolkit the server and client are not compiled by default.
+         Affected file configure.ad.
+
+Thu Apr 28 15:57:37 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added lib/contrib/getopt.[ch] for platforms that don't
+         have it (it is not GPL implementation).
+
+       * Fixed compilation when pkg-config is used.
+
+Wed Apr 27 11:49:41 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * A comma in invite/ban string is invalid, check for it.
+         Affected file apps/silcd/server_util.c.
+
+       * Added SERVICE command to the server.  It parses the command
+         request but SILC Server does not support services for the
+         time being.  Affected file apps/silcd/command.[ch].
+
+       * Added SERVICE command and command reply to client library.
+         It is however incomplete.  Updated Toolkit documentation.
+         Affected files are lib/silcclient/command[_reply].[ch].
+
+       * Fixed IDENTIFY/WHOWAS command reply to send the username
+         correctly (uninitialized buffer).  Affected file is
+         apps/silcd/server_query.c.
+
+Mon Apr 25 14:25:24 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Moved silcer/, silc/, silcd/ and irssi/ to apps/.  This
+         finalizes the major restructuring of the CVS tree.
+
+Mon Apr 25 00:39:30 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Send empty MOTD reply if MOTD file cannot be read.
+         Affected file silcd/command.c.
+
+Sun Apr 24 12:01:37 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+
+       * Optimized primer number generator to use simpler conversion
+         routines.  Also assure that the prime number will have the
+         highest bit set after modifying it.  Affected file is
+         lib/silcmath/silcprimegen.c.
+
+       * Added LibTomMath to SILC Math library (SILC_DIST_TMA).
+
+       * Added FastTomMath to SILC Math Library (SILC_DIST_TFM),
+         for now only for testing purposes, it will not be delivered
+         in any distribution for now.
+
+       * Removed NSS MPI from the source tree.  Due to upcoming
+         license change for the SILC Toolkit, we cannot deliver the
+         NSS MPI anymore.  I decided to replace it in all distributions
+         with public domain library.
+
+       * Removed GNU regex from lib/contrib and introduced free
+         GNU compatible regex, lib/contrib/regexpr.[ch].  Added
+         GNU regex compatible API to it (only partial).
+
+       * Removed getopt routines from lib/contrib.
+
 Fri Apr 22 12:21:44 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
 
        * Use silc_server_send_command_reply to send replies instead
index b34fc50d58927fece6150e4581cbb4d7a0d3e772..e2a6a2c67c28bd21b9c2c06fb6495e0402dcf58c 100644 (file)
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
 SUBDIRS =              \
+#ifdef SILC_DIST_LIB
+       @LIBSUBDIR@     \
+#endif SILC_DIST_LIB
 #ifdef SILC_DIST_APPS
        apps            \
 #endif SILC_DIST_APPS
-#ifdef SILC_DIST_LIB
-       lib             \
-#endif SILC_DIST_LIB
-#ifdef SILC_DIST_CLIENT
-       irssi           \
-#endif SILC_DIST_CLIENT
-#ifdef SILC_DIST_SERVER
-       silcd           \
-#endif SILC_DIST_SERVER
 #ifdef SILC_DIST_TOOLKIT
-       silc            \
        win32           \
 #endif SILC_DIST_TOOLKIT
 #ifdef SILC_DIST_INCLUDES
@@ -44,123 +37,38 @@ SUBDIRS =          \
 EXTRA_DIST =           \
        silcdefs.h.in   \
 #ifdef SILC_DIST_SILC
-#ifdef SILC_DIST_TOOLKIT
-       README.CVS README.WIN32 README.MACOSX silcer tutorial \
-#endif SILC_DIST_TOOLKIT
        libtoolfix      \
        CHANGES CREDITS
 #endif SILC_DIST_SILC
 
-#ifdef SILC_DIST_SILC
-#
-# Installing of SILC into the system
-#
-
-install-dirs:
-       -mkdir -p $(etcdir)
-       -mkdir -p $(modulesdir)
-       -mkdir -p $(docdir)
-
-#ifdef SILC_DIST_DOC
-doc-install:
-       -$(INSTALL_DATA) $(srcdir)/doc/CodingStyle $(docdir)/
-       -$(INSTALL_DATA) $(srcdir)/doc/FAQ $(docdir)/
-       -$(INSTALL_DATA) $(srcdir)/doc/*.txt $(docdir)/
-       -$(INSTALL_DATA) $(srcdir)/COPYING $(docdir)/
-       -$(INSTALL_DATA) $(srcdir)/CHANGES $(docdir)/
-       -$(INSTALL_DATA) $(srcdir)/CREDITS $(docdir)/
-       -$(INSTALL_DATA) $(srcdir)/README* $(docdir)/
-       -$(INSTALL_DATA) $(srcdir)/INSTALL $(docdir)/
-       -$(INSTALL_DATA) $(srcdir)/TODO $(docdir)/
-#endif SILC_DIST_DOC
-
-#ifdef SILC_DIST_SIM
-sim-install:
-       -$(INSTALL_DATA) $(srcdir)/lib/silcsim/*.so $(modulesdir)/
-#endif SILC_DIST_SIM
-
 #ifdef SILC_DIST_CLIENT
-install-dirs-client: install-dirs
+if with_irssi
+install-dirs-client:
+       -mkdir -p $(etcdir)
        -mkdir -p $(helpdir)
        -mkdir -p $(mandir)/man1
 
-doc-install-client: doc-install
-       $(INSTALL_DATA) $(srcdir)/irssi/silc.conf $(docdir)/example_silc.conf
+doc-install-client:
+       $(INSTALL_DATA) $(srcdir)/apps/irssi/silc.conf $(docdir)/example_silc.conf
        -@if test -f $(srcdir)/doc/silc.1 ; then \
         $(INSTALL_DATA) $(srcdir)/doc/silc.1 $(mandir)/man1; \
        fi
 
 etc-install-client:
-       -@if test '!' -d $(srcdir)/irssi ; then \
+       -@if test '!' -d $(srcdir)/apps/irssi ; then \
          if test '!' -f $(etcdir)/silc.conf ; then \
-           $(INSTALL_DATA) $(srcdir)/irssi/silc.conf \
+           $(INSTALL_DATA) $(srcdir)/apps/irssi/silc.conf \
                $(etcdir)/silc.conf; \
          fi; \
        fi
-#endif SILC_DIST_CLIENT
-
-#ifdef SILC_DIST_SERVER
-install-dirs-server: install-dirs
-       -mkdir -p $(logsdir)
-       -mkdir -p $(mandir)/man5
-       -mkdir -p $(mandir)/man8
-
-doc-install-server: doc-install
-       -$(INSTALL_DATA) $(srcdir)/doc/example_silcd.conf $(docdir)/
-       -@if test -f $(srcdir)/doc/silcd.8 ; then \
-        $(INSTALL_DATA) $(srcdir)/doc/silcd.8 $(mandir)/man8; \
-       fi
-       -@if test -f $(srcdir)/doc/silcd.conf.5 ; then \
-        $(INSTALL_DATA) $(srcdir)/doc/silcd.conf.5 $(mandir)/man5; \
-       fi
-
-etc-install-server:
-       -@if test '!' -f $(etcdir)/silcd.conf ; then \
-         $(INSTALL_DATA) $(srcdir)/doc/example_silcd.conf \
-               $(etcdir)/silcd.conf; \
-         $(INSTALL_DATA) $(srcdir)/doc/silcalgs.conf \
-               $(etcdir)/silcalgs.conf; \
-          chmod go= $(etcdir)/silcd.conf; \
-       fi
-
-examples-install:
-       -mkdir -p $(docdir)/examples/
-       -$(INSTALL_DATA) $(srcdir)/doc/examples/README $(docdir)/examples/
-       -$(INSTALL_DATA) $(srcdir)/doc/examples/silc* $(docdir)/examples/
-
-generate-server-key:
-       -@if test '!' -f $(etcdir)/silcd.pub ; then \
-         $(sbindir)/silcd -C $(etcdir); \
-       fi
-#endif SILC_DIST_SERVER
-
-#ifdef SILC_DIST_TOOLKIT
-toolkit-install:
-       -mkdir -p $(docdir)/toolkit/
-       -$(INSTALL_DATA) $(srcdir)/doc/toolkit/* $(docdir)/toolkit
-       -$(INSTALL_DATA) $(srcdir)/lib/doc/*.gif $(docdir)/toolkit
-       -cp -R $(srcdir)/tutorial $(docdir)
-#endif SILC_DIST_TOOLKIT
 
 install-data-hook:             \
-#ifdef SILC_DIST_CLIENT
        install-dirs-client     \
        doc-install-client      \
-       etc-install-client      \
+       etc-install-client
+endif
 #endif SILC_DIST_CLIENT
-#ifdef SILC_DIST_SERVER
-       install-dirs-server     \
-       doc-install-server      \
-       etc-install-server      \
-       examples-install        \
-       generate-server-key     \
-#endif SILC_DIST_SERVER
-#ifdef SILC_DIST_TOOLKIT
-       toolkit-install         \
-#endif SILC_DIST_TOOLKIT
-#ifdef SILC_DIST_SIM
-       sim-install
-#endif SILC_DIST_SIM
 
+#ifdef SILC_DIST_SILC
 include $(top_srcdir)/Makefile.defines.in
 #endif SILC_DIST_SILC
index 926a3035c61d8914db549e7e75a5313e135b85c1..c13aab23b8ccb584e27b76816a438612121e1d1c 100644 (file)
@@ -1,14 +1,13 @@
 #
 #  Makefile.defines.pre
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2001 Pekka Riikonen
+#  Copyright (C) 2001 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
index 3f82947145d85da14cd1cd305ef08bcceb3850f3..817ec5fec0e8990c7f298f01f3152ca6811fe5aa 100644 (file)
@@ -1,14 +1,13 @@
 #
 #  Makefile.defines_int.pre
 #
-#  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+#  Author: Pekka Riikonen <priikone@silcnet.org>
 #
-#  Copyright (C) 2000 - 2001 Pekka Riikonen
+#  Copyright (C) 2000 - 2005 Pekka Riikonen
 #
 #  This program is free software; you can redistribute it and/or modify
 #  it under the terms of the GNU General Public License as published by
-#  the Free Software Foundation; either version 2 of the License, or
-#  (at your option) any later version.
+#  the Free Software Foundation; version 2 of the License.
 #
 #  This program is distributed in the hope that it will be useful,
 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -30,7 +29,7 @@ silc_install_prefix=@prefix@
 #
 # Common libraries that are linked against the created executable
 #
-SILC_COMMON_LIBS= @LIBS@ -L$(silc_top_srcdir)/lib -lsilc
+SILC_COMMON_LIBS= -L$(silc_top_srcdir)/lib -lsilc @LIBS@
 
 #
 # Common compilation flags
index 4672367dcada6f6fd79df060360a7d35a405a7dd..c50be0b5183baab236405b690e521f029fa841a8 100644 (file)
@@ -59,6 +59,10 @@ distribution.
 
 Following directories currently exist in SILC source tree.
 
+  apps/
+
+       All applications.
+
   doc/
 
         Includes all the SILC documentation.  Some of the documentation
@@ -69,7 +73,7 @@ Following directories currently exist in SILC source tree.
 
         Includes SILC include files.
 
-  irssi/
+  apps/irssi/
 
        Includes the Irssi SILC Client.
 
@@ -136,19 +140,19 @@ Following directories currently exist in SILC source tree.
         Includes the official SILC web pages and everything that relates
         to them.  This directory never appears on public distribution.
 
-  silc/
+  apps/silc/
 
        Includes an example implementation of ncurses based SILC client.
        It won't compile with current Toolkit since it is not being 
        updated.  It is still good example for Toolkit programmer to 
        figure out how to use SILC Toolkit.
 
-  silcer/
+  apps/silcer/
 
        Includes an example implementation of GUI (Gnome) base SILC
        client.  Please read silcer/README for more information.
 
-  silcd/
+  apps/silcd/
 
         Includes SILC server.  There can be some extra files that will
         never appear in public distribution, such as, configuration files.
index f741abe1140403cfd786fee586c5e22a4c6f9f29..a2942501957a1ad683e1075c92767649e319006a 100644 (file)
@@ -71,16 +71,11 @@ directories.  Make sure they are not compiled and does not include any
 extra files.  If you haven't compiled them after the CVS checkout, they do
 not include any extra files.
 
-NOTE for 'toolkit' distribution:  Before giving make dist the following
-must be done:
+NOTE for 'toolkit' distribution:  Running ./configure for toolkit 
+distribution is not necessary.  Toolkit is packaged simply by giving 
+command:
 
-       go to util/robodoc/
-       give ./configure;make to compile robodoc
-       go to doc/
-       give make toolkit-ref-html
-
-This then creates the Toolkit reference manual.  After this the toolkit 
-distribution can be packaged.
+       makedist
 
 
 Before releasing the distribution
index 73e5a27bc4c2bbffb83c63e54fe1872255e611ff..46a8ab470be67d4a975d17cf2bc2d7d323e8115c 100644 (file)
--- a/TODO-1.0
+++ b/TODO-1.0
@@ -1,30 +1,12 @@
-TODO After 1.0
-==============
+TODO for 1.1 And Beyond
+=======================
 
-A rough list of stuff that is going to be done to SILC after 1.0 or at
-least could be done.
+lib/silccrypt
+=============
 
  o Implement the defined SilcDH API.  The definition is in
    lib/silccrypt/silcdh.h.
 
- o X.509 certificate support.  SILC protocol supports certificates and
-   it would be great to have support for them.  This is a big task as
-   support has to be made for ASN.1 as well.  I've looked into OpenSSL 
-   package as it has X.509 certificate support (and ASN.1 as well).  
-   The code does not look very good to my eye but it has some potentials.
-   This should be looked at more closely.
-
-   Naturally own SILC Certificate API has to be defined regardles what
-   the actual X.509 library is (OpenSSL X.509 or something else).  Other
-   choice is to write own X.509 library but I'm not going to do it - 
-   I can help to migrate the OpenSSL X.509 into SILC and I can help if 
-   someone would like to write the X.509 library - but I'm not going 
-   to start writing one myself.  Anyhow, the OpenSSL X.509 lib should
-   be checked.
-
-   Other package that should be checked is the NSS's X509 library,
-   which I like more over OpenSSL package.
-
  o SSH2 public keys support, allowing the use of SSH2 public keys in
    SILC.
 
@@ -39,145 +21,321 @@ least could be done.
    and certificates as well.  Add fe. silcpk.h into silccore.  It should
    also include the Public Key Payload encoding and decoding routines.
 
+ o Add DSS support.
+
+ o Cipher optimizations (asm, that this) at least for i386 would be nice.
+
+ o ECDSA and ECDH.
+
+
+lib/silccore/silcpacket.[ch]   ****PARTLY DONE****
+============================
+
+ o SilcPacketEngine.
+
+ o New SILC Packet API.
+
+
+lib/silccore/silcid.[ch]
+========================
+
+  o Add silc_id_str2id to accept the destination buffer as argument
+    and thus not require any memory allocation.  Same will happen
+    with silc_id_payload_* functions.
+
+  o silc_id_str2id, silc_id2str to non-allocating routines.
+
+
+lib/silcutil
+============
+
  o Compression routines are missing.  The protocol supports packet
    compression thus it must be implemented.  SILC Zip API must be
    defined.
 
- o Optimizations in Libraries
-
-       o There is currently three (3) allocations per packet in the
-         silc_packet_receive_process, which is used to process and
-         dispatch all packets in the packet queue to the parser callback
-         function.  First allocation is for parse_ctx, second for the
-         SilcPacketContext, and third for packet->buffer where the actual
-         data is saved.
-
-         The parse_ctx allocation can be removed by adding it as a
-         structure to the SilcPacketContext.  When the SilcPacketContext
-         is allocated there is space for the parse context already.
-
-         The silc_packet_context_alloc could have a free list of
-         packet contexts.  If free packet context is found from the list
-         it is returned instead of allocating a new one.  The library
-         could at first allocate them and save them to the free list
-         until enough contexts for smooth processing exists in the list.
-         This would remove a big allocation since the structure is
-         quite big, and even bigger if it would include the parse_ctx.
-
-         The packet->buffer can be optimized too if the SilcBuffer
-         interface would support free lists as well.  Maybe such could
-         be done in the same way as for SilcPacketContext.  The
-         silc_buffer_alloc would check free list before actually 
-         allocating new memory.  Since the packets in the SILC protocol
-         usually are about the same size (due to padding) it would be
-         easy to find suitable size buffer from the free list very
-         quickly.
-
-         These naturally cause the overal memory consumption to grow
-         but would take away many allocations that can be done several
-         times in a second (see also ~/silcpacket).
-
-       o Move the actual file descriptor task callback (the callback that
-         handles the incoming data, outgoing data etc, that is implemnted
-         in server and client separately (silc_server_packet_process and
-         silc_client_packet_proces)) to the low level socket connection
-         handling routines, and create an interface where the application
-         can register a callbacks for incoming data, outoing data and EOF
-         receiving, which the library will call when necessary.  This way 
-         we can move the data handling in one place.
-
-       o Add silc_id_str2id to accept the destination buffer as argument
-         and thus not require any memory allocation.  Same will happen
-         with silc_id_payload_* functions.
-
-       o Remove the `truelen' field from SilcBuffer as it is entirely
-         redundant since we can get the true length of the buffer by
-         doing buffer->end - buffer->header.  Add SILC_BUFFER_TRUELEN
-         macro instead.  Consider also removing `len' field too since
-         it effectively is buffer->tail - buffer->data, and adding
-         SILC_BUFFER_LEN macro can do the same.  These would save
-         totally 8 bytes of memory per buffer.
-
- o Optimizations in Server
-
-       o Remove the big switch statement from the function 
-         silc_server_packet_parse_type and replace it with predefined
-         table of function pointers where each of the slot in table
-         represents the packet type value.
-
-         Same could be done with notify packets which has big switch 
-         statement too.  Same kind of table of notify callbacks could be
-         done as well.
-
-       o The parser callback in the server will add a timeout task for
-         all packets.  It will require registering and allocating a
-         new task to the SilcSchedule.  Maybe, at least, for server
-         and router packets the parser would be called immediately
-         instead of adding it to the scheduler with 0 timeout.  It
-         should be analyzed too how slow the task registering process
-         actually is, and find out ways to optimize it.
-
-       o The SERVER_SIGNOFF notify handing is not optimal, because it'll
-         cause sending of multiple SIGNOFF notify's instead of the one
-         SERVER_SIGNOFF notify that the server received.  This should be
-         optimized so that the only SERVER_SIGNOFF is sent and not
-         SIGNOFF of notify at all (using SIGNOFF takes the idea about
-         SERVER_SIGNOFF away entirely).
-
-        o Another SERVER_SIGNOFF opt/bugfix:  Currently the signoff is
-          sent to a client if it is on same channel as the client that
-          signoffed.  However, the entire SERVER_SIGNOFF list is sent to
-          the client, ie. it may receive clients that was not on the 
-          same channel.  This is actually against the specs.  It must be
-          done per channel.  It shouldn't receive the whole list just
-          because one client happened to be on same channel.
-
-       o See also ~/silcserver
+ o Add builtin SOCKS and HTTP Proxy support, well the SOCKS at least.
+   SILC currently supports SOCKS4 and SOCKS5 but it needs to be compiled
+   in separately.
+
+ o bool -> SilcBool
+
+ o SilcBit, bit field:
+
+   #define SilcBit(b) unsigned int b : 1
+
+
+lib/silcutil/silcbuffer.h      ****DONE****
+=========================
+
+ o Remove the `truelen' field from SilcBuffer as it is entirely
+   redundant since we can get the true length of the buffer by
+   doing buffer->end - buffer->header.  Add silc_buffer_truelen
+   macro instead.  Consider also removing `len' field too since
+   it effectively is buffer->tail - buffer->data, and adding
+   silc_buffer_len macro can do the same.  These would save
+   totally 8 bytes of memory per buffer.
+
+
+lib/silcutil/silcbuffmt.[ch]   ****PARTY DONE****
+============================
+
+ o SILC_STR_APPEND, _APPEND_TAIL.
+
+ o SILC_STR_OFFSET
+
+
+lib/silcutil/silcstack.[ch]    ****DONE****
+===========================
+
+ o Data stack implementation
+
+
+lib/silcutil/silcstream.[ch]   ****DONE****
+============================
+
+ o Add abstract SilcStream.
+
+
+lib/silcutil/silcsocketstream.[ch]     ****PARTY DONE****
+==================================
+
+ o Add SilcSocketStream.
+
+
+lib/silcutil/epoc/*
+===================
+
+  o lib/silcutil/epoc routines missing or not completed.
+
+  o The PKCS#1 also calls global RNG (even though it is not used
+    currently in SILC, the interface allows its use).
+
+  o Something needs to be thought to the logging globals as well,
+    like silc_debug etc.  They won't work on EPOC.  Perhaps logging
+    and debugging is to be disabled on EPOC.
+
+
+lib/silcutil/silcschedule*.[ch]
+===============================
+
+ o Scheduler can be optimized for FD tasks by changing the fd_queue
+   to SilcHashTable instead of using linked list.  We need to do
+   one-to-one mapping of FD to task and hash table is more efficient
+   for this usage.
+
+   Also redefine the silc_select to perhaps return a separate
+   structure of the events that actually occurred, instead of
+   returning the events in the fd_list which is then traversed
+   in the generic code to find the changed events.  This can be
+   made faster by having own struct which includes only the
+   changed events, thus the tarversing is faster since the whole
+   fd_list is not traversed anymore (it is still traversed in the
+   silc_select but at least it removes one extra tarversing later
+   for the same list).
+
+   Other task queues should be changed to use SilcList.
+
+ o Add SILC scheduler's internal routines into a table of implementation
+   function pointers, that the generic code then takes as extern from
+   implementation.  These are the silc_schedule_internal_* routines.
+
+ o Change SILC_TASK_CALLBACK to non-static, and remove the macro
+   SILC_TASK_CALLBACK_GLOBAL.
+
+
+lib/silcutil/silcasync.[ch]    ****DONE****
+===========================
 
  o Add SilcAsyncOperation to utility library.  Any function that takes
-   callback as an argument must/should return SilcAsyncOperation (see 
-   ~/silcasync).
+   callback as an argument must/should return SilcAsyncOperation.
 
- o Rewrite SilcProtocol to be SilcFSM (see ~/silcfsm).
 
- o Do some scheduler optimizations and interface changes (see 
-   ~/silcschedule).
+lib/silcutil/silctime.[ch]     ****DONE****
+===========================
 
- o Change the lib/silccore/silcpacket.[ch] interfaces (see ~/silcpacket).
+ o SilcTime.
 
- o Add abstract SilcStream and SilcSocketStream (see ~/silcstream).
+ o system time, universal, generalized.
 
- o Change some of the SILC Net interfaces (see ~/silcnet).
 
- o Add DSS support.
+lib/silcmath
+============
 
- o SILC RNG does not implement random seed files, and they should be
-   implemented.
+ o The SILC MP API function must start returning indication of success
+   and failure of the operation.
 
- o Cipher optimizations (asm, that this) at least for i386 would be nice.
+ o Do SilcStack support for silc_mp_init, silc_mp_init_size and other
+   any other MP function (including utility ones) that may allocate
+   memory.
 
- o Add builtin SOCKS and HTTP Proxy support, well the SOCKS at least.
-   SILC currently supports SOCKS4 and SOCKS5 but it needs to be compiled
-   in separately.
+ o All utility functions should be made non-allocating ones.
 
- o Add a timeout to handling incoming JOIN commands.  It should be 
-   enforced that JOIN command is executed only once in a second or two
-   seconds.  Now it is possible to accept n incoming JOIN commands
-   and process them without any timeouts.  THis must be employed because
-   each JOIN command will create and distribute the new channel key
-   to everybody on the channel (Fix this to 0.9.x).
 
- o EPOC specific additions/changes required:
+lib/silcasn1                   ****PARTLY DONE****
+============
 
-       o lib/silcutil/epoc routines missing or not completed.
+ o ASN.1 library
 
-       o The PKCS#1 also calls global RNG (even though it is not used 
-         currently in SILC, the interface allows its use).
+ o Header documentation missing.
 
-       o Something needs to be thought to the logging globals as well, 
-         like silc_debug etc.  They won't work on EPOC.  Perhaps logging
-         and debugging is to be disabled on EPOC.
+ o Some string encodings missing (copy/paste matter).
 
- o Check whether we can fully comply with RFC 2779.
+
+lib/silcpkix
+============
+
+ o PKIX implementation
+
+
+lib/silcutil/silcfsm.[ch]
+=========================
+
+ o SILC Finite State Machine API.  Replaces SILC Protocol API,
+   (see ~silcfsm or ask Pekka).
+
+
+lib/silcutil/silcnet*, lib/silcutil/*/silc*net*
+===============================================
+
+ o Add UDP interface
+
+ o New network interfaces
+
+tyepdef enum {
+  SILC_NET_OK,
+  SILC_NET_UNKNOWN_IP,
+  SILC_NET_UNKNOWN_HOST,
+  SILC_NET_HOST_UNREACHABLE,
+  SILC_NET_CONNECTION_REFUSED,
+  SILC_NET_CONNECTION_TIMEOUT,
+  SILC_NET_NO_MEMORY,
+  SILC_NET_ERROR,
+} SilcNetStatus;
+
+/* A callback function of this type is returned by silc_net_create_server
+   and silc_net_create_connection_async.  For silc_net_create_server this
+   callback means that new incoming connection was accepted, and the
+   `stream' is the socket stream representing the socket connection.  For
+   silc_net_create_connection_async this means that we have connected to
+   the remote host and the `stream' is the socket stream for the socket
+   connection. */
+typedef void (*SilcNetCallback)(SilcNetStatus status,
+                               SilcStream stream, void *context);
+
+typedef SilcNetServerStruct *SilcNetServer;
+
+struct SilcNetServerStruct {
+  SilcNetCallback callback;
+  void *context;
+  int sock;
+  bool require_fqdn;
+};
+
+/* This function creates server or daemon or listener or what ever.  This
+   does not fork a new process, it must be done by the caller if caller
+   wants to create a child process.  This is used to create network
+   listener for incoming connections, and `callback' will be called
+   everytime new connection is received.  If `local_ip_addr' is NULL
+   any address is used.  If provided it can be used bind the server to
+   `local_ip_count' many IP addresses provided in `local_ip_addr' table.
+   On success returns the SilcNetServer context, or NULL on error.  If
+   `require_fqdn' is TRUE the server will require that the incoming
+   connection has FQDN to be able to connect. */
+SilcNetServer
+silc_net_create_server(const char **local_ip_addr, SilcUInt32 local_ip_count,
+                      int port, bool require_fqdn, SilcSchedule schedule,
+                      SilcNetCallback callback, void *context);
+
+/* Closes the server indicated by the `server'. */
+silc_net_close_server(SilcNetServer server);
+
+/* Creates TCP/IP connection to the remote host indicated by `remote_host'
+   which may be hostname or IP address, on the port indicated by `remote_port'.
+   If the `local_ip_addr' is provided the local host is bound to that address
+   before creating the connection.  This is synchronous call, and the
+   `callback' is called before this function returns.  The `callback'
+   delivers the SilcStream for the created connection. */
+SilcNetStatus
+silc_net_create_connection(const char *local_ip_addr,
+                          const char *remote_host, int remote_port,
+                          SilcNetCallback callback, void *context);
+
+/* Creates TCP/IP connection to the remote host indicated by `remote_host'
+   which may be hostname or IP address, on the port indicated by `remote_port'.
+   If the `local_ip_addr' is provided the local host is bound to that address
+   before creating the connection.  This is asynchronous call, and this
+   function returns before the connection is actually established.  The
+   `callback' will be called after the connection is created to deliver the
+   SilcStream for the created connection. */
+SilcAsyncOperation
+silc_net_create_connection_async(const char *local_ip_addr,
+                                const char *remote_ip_addr, int remote_port,
+                                SilcNetCallback callback, void *context);
+
+
+ o Other functions should remain as they are since these new functions have
+   to use them.  This way we also provide them for applications that want
+   to handle the sockets by themself.
+
+
+apps/silcd
+==========
+
+ o Remove the big switch statement from the function
+   silc_server_packet_parse_type and replace it with predefined
+   table of function pointers where each of the slot in table
+   represents the packet type value.
+
+   Same could be done with notify packets which has big switch
+   statement too.  Same kind of table of notify callbacks could be
+   done as well.
+
+ o The parser callback in the server will add a timeout task for
+   all packets.  It will require registering and allocating a
+   new task to the SilcSchedule.  Maybe, at least, for server
+   and router packets the parser would be called immediately
+   instead of adding it to the scheduler with 0 timeout.  It
+   should be analyzed too how slow the task registering process
+   actually is, and find out ways to optimize it.
+
+ o The SERVER_SIGNOFF notify handing is not optimal, because it'll
+   cause sending of multiple SIGNOFF notify's instead of the one
+   SERVER_SIGNOFF notify that the server received.  This should be
+   optimized so that the only SERVER_SIGNOFF is sent and not
+   SIGNOFF of notify at all (using SIGNOFF takes the idea about
+   SERVER_SIGNOFF away entirely).
+
+ o Another SERVER_SIGNOFF opt/bugfix:  Currently the signoff is
+   sent to a client if it is on same channel as the client that
+   signoffed.  However, the entire SERVER_SIGNOFF list is sent to
+   the client, ie. it may receive clients that was not on the
+   same channel.  This is actually against the specs.  It must be
+   done per channel.  It shouldn't receive the whole list just
+   because one client happened to be on same channel.
+
+ o MAYBE: The SilcChannelClientEntry can be:
+       SilcUInt32 address;
+       SilcUInt32 mode;
+
+  where address is SilcClientEntry address XOR SilcChannelEntry.
+  You can get SilcClientEntry by doing client = chl->address XOR channel,
+  and SilcChannelEntry by doing channel = chl->address XOR client.
+  As long as the other pointer is always available when accessing the
+  structure this can be done.
+
+ o Add reference counters to all Silc*Entry structures
+
+ o SERVICEs support (plugin, SIM)
+
+ o If client's public key is saved in the server (and doing public key
+   authentication) then the hostname and the username information could
+   be taken from the public key.  Should be a configuration option!
+
+ o Add a timeout to handling incoming JOIN commands.  It should be
+   enforced that JOIN command is executed only once in a second or two
+   seconds.  Now it is possible to accept n incoming JOIN commands
+   and process them without any timeouts.  THis must be employed because
+   each JOIN command will create and distribute the new channel key
+   to everybody on the channel (Fix this to 0.9.x).
 
  o The CMODE cipher & hmac change problem (#101).
index 87bc7ca44058f737f4d8a04ee4cdfdf27b80afe1..1b089851deffabc9d888c47669f98b4f7bee9105 100644 (file)
 
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
-SUBDIRS =              \
+SUBDIRS =      \
 #ifdef SILC_DIST_AUTODIST
-       autodist        \
+       autodist \
 #endif SILC_DIST_AUTODIST
-#ifdef SILC_DIST_SILCMAP
-       silcmap
-#endif SILC_DIST_SILCMAP
+#ifdef SILC_DIST_SERVER
+       @SILCD_SUBDIR@ \
+#endif SILC_DIST_SERVER
+#ifdef SILC_DIST_CLIENT
+       @IRSSI_SUBDIR@ \
+#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_INPLACE
+       silcstress
+#endif SILC_DIST_INPLACE
 
index 7f9bf01b832d67d50d8ac20ceff9ac9d3d5bfc8b..43f0de9e1721093bd8a9b54499a1979e629db19e 100644 (file)
@@ -1,4 +1,61 @@
-Sat Apr 23 12:49:09 EEST 2005  Pekka Riikonen <priikone@silcnet.org>
+Wed May  4 10:58:24 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
+
+       * Autodist 1.3.
+
+Sun May  1 17:31:55 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
+
+       * Added support for dependencies in makefiles.
+
+       * Added AD_DISABLE_DEPENDENCIES macro to disable Autodist
+         dependencies in makefiles.  Added support for dependencies
+         in makefiles.
+
+       * Added -p option to Autodist.  It can be used to a process file
+         from the command line.
+
+       * Added dependency support for configure.ad files as well.
+
+Sat Apr 30 17:49:05 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
+
+       * The 'noprocess' directive now works recursively with
+         directories.
+
+Sat Apr 30 11:49:01 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
+
+       * Added better debug messages.
+
+       * Added log file creation, autodist.log and makedist.log.
+
+       * Fixed license-header to change license only during packaging,
+         not also during preparation.
+
+       * Fixed .ad processing when the file was not processed, to
+         copy the original to new name.
+
+       * Fixed 'include' when copying directories to root of the
+         distdir, and the destination directory already exist.
+
+Fri Apr 29 16:48:16 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed configure.ac creation when no fragments in use.
+
+Thu Apr 28 11:44:59 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
+
+       * The '.in' suffix with source file suffixes expects source code 
+         format for the distdefs.
+
+Sun Apr 24 21:11:49 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed undefining to actually work.
+
+       * The top distribution now takes precedence on defined
+         distdefs over inherited distributions, and can override
+         defined and undefined distdefs (previously it could only
+         undefine defined but not define specificly undefined :)).
+
+       * Prettier distdef output with -s.
+
+Sat Apr 23 12:49:09 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
 
        * Autodist 1.2.1.
 
index e3e00ead42729904c74acb67257dd340f72f54cd..106cb4847e72dac9aa3f7d89978e07716d1f2949 100644 (file)
@@ -1,16 +1,8 @@
 TODO In Autodist
 ================
 
-o Autodist should produce output file when 'license-header' is used for
-  files that _was not_ re-licensed.  This would be useful to check if
-  there are files in the distribution with wrong license.
-
 o Better 'license-header' implementation.
 
 o Perhaps ability to partially re-license the source tree.  Now all files
-  will be processed if 'license-header' is used.
-
-o Better 'noprocess' so that it would work with directories recursively,
-  such as noprocess foo/bar, would not process anything under foo/bar.
-
-o Perhaps output autodist.log when processing the source tree.
+  will be processed if 'license-header' is used.  Only way to control
+  this is to use 'noprocess' or specify different header in file.
index 2e8a361498693d01395340acc9abd003f645a958..df1c2e622d959e65be6314c1f98de08bb0dae1bb 100755 (executable)
@@ -129,6 +129,7 @@ licenseh=
 
 # Whether to output ad_debug information
 debug=false
+nolog=false
 
 # Autodist version
 ver=@VERSION@
@@ -168,6 +169,7 @@ ad_debug()
 ad_fatal()
 {
   set -f
+  ad_log "error: $1"
   echo autodist: error: $1
   set +f
   exit 1
@@ -181,10 +183,39 @@ ad_fatal()
 ad_warning()
 {
   set -f
+  ad_log "warning: $1"
   echo autodist: warning: $1
   set +f
 }
 
+#
+# Opens a log file.
+#
+# Arguments: ad_log_open <logfile>
+#
+ad_log_open()
+{
+  rm -rf $1
+  exec 5> $1
+
+  cat >&5 << EOF
+This file contains messages produced by the Autodist $ver.
+
+EOF
+}
+
+#
+# Prints to an open log file
+#
+# Arguments: ad_log
+#
+ad_log()
+{
+  if test x$nolog = xfalse; then
+    echo "$1" >&5
+  fi
+}
+
 #
 # Initializes the Autodist environment, creates default distribution
 # directory, and default distribution.
@@ -193,11 +224,11 @@ ad_warning()
 #
 ad_initialize()
 {
-  ad_debug ">ad_initialize"
+  ad_debug "Initializing Autodist environment"
 
   # Create default distdir
   if test '!' -f $distdir; then
-    mkdir -p $distdir
+    mkdir -p -- $distdir
   fi
 
   # Create Autodist configuration file
@@ -210,7 +241,7 @@ ad_initialize()
     cp -p @AUTODISTDIR@/default $distdir
   fi
 
-  ad_debug "<ad_initialize"
+  ad_debug "Autodist environment initialized"
 }
 
 #
@@ -220,7 +251,7 @@ ad_initialize()
 #
 ad_create_distdefs_h()
 {
-  ad_debug ">ad_create_distdefs_h"
+  ad_debug "Creating distdef header file"
 
   fname=$DISTDEFS
   rm -f $fname
@@ -247,7 +278,8 @@ EOF
 
 #endif /* _`echo $DP`_DISTDEFS_H */
 EOF
-  ad_debug "<ad_create_distdefs_h"
+
+  ad_debug "Distdef header file created"
 }
 
 #
@@ -260,7 +292,7 @@ ad_make_configure()
 {
   local run_autoconf=false
 
-  ad_debug ">ad_make_configure"
+  ad_debug "Starting configure creation"
 
   rm -f configure
 
@@ -307,7 +339,7 @@ ad_make_configure()
     fi
   fi
 
-  ad_debug "<ad_make_configure"
+  ad_debug "Ending configure creation"
 }
 
 #
@@ -321,7 +353,11 @@ ad_make_configure_ac()
 {
   local check
 
-  ad_debug ">ad_make_configure_ac: $1"
+  ad_debug "Starting creating configure.ac: $1"
+
+  ad_log ""
+  ad_log "Following configure.ad files were processed into configure.ac:"
+  ad_log "--------------------------------------------------------------"
 
   if test '!' -f $1; then
     ad_fatal "The configure file '$1' does not exist"
@@ -336,13 +372,16 @@ ad_make_configure_ac()
 
   rm -f configure.ac configure.ad.cfs
 
-  cfs=`find . -name configure\*\.ad`
+  cfs=`find . -type f -name configure\*\.ad`
   for i in $cfs
   do
     if test "x$i" = "x$1"; then
       continue
     fi
+
     ad_debug "including $i"
+    ad_log "  $i"
+
     cat $i >> configure.ad.cfs
   done
 
@@ -369,29 +408,35 @@ EOF
 
   ad_debug "creating configure.ac"
   if test -f configure.ad.cfs; then
-    sed '/AD_INCLUDE_CONFIGURE/ r configure.ad.cfs' $1 > $fname.tmp
-    sed -e "/AD_INCLUDE_CONFIGURE/s///" $fname.tmp >> $fname
+    sed '/^AD_INCLUDE_CONFIGURE/ r configure.ad.cfs' $1 > $fname.tmp
+    sed -e "/^AD_INCLUDE_CONFIGURE/d" $fname.tmp >> $fname
     rm -f configure.ad.cfs $fname.tmp
   else
-    cat $1 >> $fname.tmp
+    cat $1 >> $fname
   fi
 
   # Process AD_INIT
   sed -e "/AD_INIT/s//AC_INIT([$distribution], [$dist_version], [$bug_report], [$package])/" $fname > $fname.tmp
 
+  # Remove AD_DISABLE_DEPENDENCIES
+  sed -e "/^AD_DISABLE_DEPENDENCIES/d" $fname.tmp > $fname
+
   # Process for distribution
-  rm -f $fname
-  ad_process_file $fname.tmp $fname
+  rm -f $fname.tmp
+  ad_process_file $fname $fname.tmp false
 
   # Remove any trailing backslashes
-  if test -f "$fname"; then
-    sed -e :a -e '/\\$/N; s/[  ]*\\\n//; ta' < $fname > configure.ac
+  if test -f "$fname.tmp"; then
+    sed -e :a -e '/\\$/N; s/[  ]*\\\n//; ta' < $fname.tmp > configure.ac
   else
-    cp -p $fname.tmp configure.ac
+    cp -p $fname configure.ac
   fi
   rm -f $fname $fname.tmp
 
-  ad_debug "<ad_make_configure_ac: $1"
+  ad_log "  ./configure.ad"
+  ad_log ""
+
+  ad_debug "Ending creating configure.ac: $1"
 }
 
 #
@@ -401,7 +446,7 @@ EOF
 #
 ad_make_makefile_ins()
 {
-  ad_debug ">ad_make_makefile_ins"
+  ad_debug "Starting creating Makefile.in files"
 
   if test "$AUTOMAKE"; then
     ad_debug "Running automake"
@@ -411,7 +456,7 @@ ad_make_makefile_ins()
     fi
   fi
 
-  ad_debug "<ad_make_makefile_ins"
+  ad_debug "Ending creating Makefile.in files"
 }
 
 #
@@ -423,63 +468,117 @@ ad_make_makefile_ins()
 #
 ad_make_makefile_ams()
 {
-  ad_debug ">ad_make_makefile_ams"
+  ad_debug "Starting creating Makefile.am files"
+
+  ad_log ""
+  ad_log "Following Makefile.ad files were processed into Makefile.am files:"
+  ad_log "------------------------------------------------------------------"
 
-  files=`find . -name Makefile\.ad`
+  files=`find . -type f -name Makefile\.ad`
   for ff in $files
   do
+    ad_log "  $ff"
     fname=`echo $ff | sed s/\.ad//`
+    ad_make_makefile_am $ff $fname.am
+  done
+  ad_log ""
+
+  ad_debug "Ending creating Makefile.am files"
+}
+
+#
+# Creates Makefile.am file from the Makefile.ad file.
+#
+# Arguments: ad_make_makefile_am <src> <dst>
+#
+ad_make_makefile_am()
+{
+  local am_deps=true
+  local f=$1
+  local fname=$2
+
+  # Disable dependencies if requested
+  dc=`sed 's/^[        ]*//' < configure.ad | grep -v "^#" \
+    | grep "AD_DISABLE_DEPENDENCIES"`
+  if test "$dc" = "AD_DISABLE_DEPENDENCIES"; then
+    am_deps=false
+  fi
 
-    # Header for the Makefile.am
-  cat > $fname.am <<EOF
+  # Header for the Makefile.am
+  cat > $fname <<EOF
 # Automatically generated by Autodist $ver from Makefile.ad.  Do not edit.
-# To make changes edit the $ff file in the source tree.
+# To make changes edit the $f file in the source tree.
 
-# Source: $ff
+# Source: $f
 # Generated: `date` by `whoami`
 # Distribution: $distribution
 # License: $license
 
 EOF
 
-    # Run the distribution processing for this Makefile.ad
-    ad_debug "Processing $ff to be $fname.am"
-    ad_process_file $ff $fname.tmp
+  # Run the distribution processing for this Makefile.ad
+  ad_debug "Processing $f to be $fname"
+  ad_process_file $f $fname.tmp false
 
-    # Remove any trailing backslashes
-    if test -f "$fname.tmp"; then
-      sed -e :a -e '/\\$/N; s/[        ]*\\\n//; ta' < $fname.tmp >> $fname.am
-    else
-      cat $ff >> $fname.am
-    fi
+  # Remove any trailing backslashes
+  if test -f "$fname.tmp"; then
+    sed -e :a -e '/\\$/N; s/[  ]*\\\n//; ta' < $fname.tmp >> $fname
+  else
+    cat $f >> $fname
+  fi
 
-    rm -f $fname.tmp
-  done
+  # Enable dependencies if requested
+  if test x$am_deps = xtrue; then
+    # Get list of configure.ad's to get them into deps also
+    cfs=`find . -type f -name configure\*\.ad`
+    cfs=`echo $cfs | sed 's/\.\///g'`
+
+    cat >> $fname <<EOF
 
-  ad_debug "<ad_make_makefile_ams"
+# S_AD_ENABLE_DEPENDENCIES
+\$(srcdir)/Makefile.am: Makefile.ad
+       cd \$(top_srcdir) && autodist -p makefile \$(subdir)/Makefile.ad \$(subdir)/Makefile.am && cd \$(subdir)
+\$(srcdir)/configure.ac: $cfs
+       cd \$(top_srcdir) && autodist -p configure \$(top_srcdir)/configure.ad && cd \$(subdir)
+# E_AD_ENABLE_DEPENDENCIES
+EOF
+  fi
+
+  rm -f $fname.tmp
 }
 
 #
 # Processes all files with .ad suffix, with exception of configure*.ad
 # and Makefile.ad files, for distribution from the source tree.
 #
-# Arguments: ad_process_ads
+# Arguments: ad_process_ads false
 #
 ad_process_ads()
 {
-  ad_debug ">ad_process_ads"
+  ad_debug "Starting processing .ad files"
 
-  files=`find . -name \*\.ad \! -name configure\*\.ad \! -name Makefile\.ad`
+  ad_log ""
+  ad_log "Following .ad files were processed:"
+  ad_log "-----------------------------------"
+
+  files=`find . -type f -name \*\.ad \! -name configure\*\.ad \! -name Makefile\.ad`
   for i in $files
   do
     fname=`echo $i | sed s/\.ad//`
 
-    # Run the distribution processing for this file
     ad_debug "Processing $i to be $fname"
-    ad_process_file $i $fname
+    ad_log "  $i into $fname"
+
+    # Run the distribution processing for this file
+    ad_process_file $i $fname false
+    if test -f $fname; then
+      cp -p $i $fname || exit 1
+    fi
+
   done
+  ad_log ""
 
-  ad_debug "<ad_process_ads"
+  ad_debug "Ending processing .ad files"
 }
 
 #
@@ -496,13 +595,19 @@ ad_process_ads()
 # source path.  This, in effect, is a cp utility with ability to create
 # directories if they do not exist.
 #
-# Arguments: ad_dist_includes <includeslist> <recursive>
+# Arguments: ad_dist_includes <includeslist> <recursive> <log>
 #
 ad_dist_includes()
 {
   local incs
 
-  ad_debug ">ad_dist_includes: $1 $2"
+  ad_debug "Starting running includes: $1 $2"
+
+  if test x$3 = xtrue; then
+    ad_log ""
+    ad_log "Following files and directories were included in distribution:"
+    ad_log "--------------------------------------------------------------"
+  fi
 
   # By default do not expand pathnames
   set -f
@@ -537,7 +642,7 @@ ad_dist_includes()
         d=`echo $src | sed 's,/[^/]*$,,'`
         if test "$d" != "$src" && test "$d" != "." && \
           test '!' -d $am_distdir/$d; then
-          mkdir -p $am_distdir/$d || exit 1
+          mkdir -p -- $am_distdir/$d || exit 1
         fi
       else
         # Add to different location
@@ -549,10 +654,13 @@ ad_dist_includes()
         d=`echo $dst | sed 's,/[^/]*$,,'`
         if test "$d" != "$dst" && test "$d" != "." && \
           test '!' -d $am_distdir/$d; then
-          mkdir -p $am_distdir/$d || exit 1
+          mkdir -p -- $am_distdir/$d || exit 1
         fi
       fi
 
+      if test x$3 = xtrue; then
+       ad_log "  $src into $am_distdir/$d"
+      fi
       cp -p $src $am_distdir/$d || exit 1
 
     elif test -d "$src"; then
@@ -560,16 +668,22 @@ ad_dist_includes()
 
       if test "$src" = "$dst"; then
        # Add to same location
-        d=`echo $src | sed 's,/[^/]*$,,'`
-        ds=`echo $src | sed 's/\/$//'`
-        if test "$ds" = "$d"; then
+       d=`echo $src | sed 's,/[^/]*$,,'`
+       ds=`echo $src | sed 's/\/$//'`
+       if test "$ds" = "$d"; then
           d=`echo $d | sed 's,/[^/]*$,,'`
-        fi
-        if test '!' -d $am_distdir/$d && test "$ds" != "$d"; then
-          mkdir -p $am_distdir/$d || exit 1
-        fi
+       fi
+       if test "$ds" = "$d"; then
+         d=""
+       fi
+       if test '!' -d $am_distdir/$d && test "$ds" != "$d"; then
+          mkdir -p -- $am_distdir/$d || exit 1
+       fi
 
-        cp -pR $src $am_distdir/$d || exit 1
+       if test x$3 = xtrue; then
+         ad_log "  $src into $am_distdir/$d"
+       fi
+       cp -pR $src $am_distdir/$d || exit 1
       else
        # Add to different location
         check=`echo "$dst" | sed 's/?//; s/*//; s/\[//; s/\]//'`
@@ -583,9 +697,12 @@ ad_dist_includes()
           d=`echo $d | sed 's,/[^/]*$,,'`
         fi
         if test '!' -d $am_distdir/$d && test "$dst" != "$d"; then
-          mkdir -p $am_distdir/$d || exit 1
+          mkdir -p -- $am_distdir/$d || exit 1
         fi
 
+       if test x$3 = xtrue; then
+         ad_log "  $src into $am_distdir/$dst"
+       fi
         cp -pR $src $am_distdir/$dst || exit 1
       fi
 
@@ -645,9 +762,13 @@ ad_dist_includes()
     dst=
   done
 
+  if test x$3 = xtrue; then
+    ad_log ""
+  fi
+
   set +f
 
-  ad_debug "<ad_dist_includes: $1 $2"
+  ad_debug "Ending running includes: $1 $2"
 }
 
 #
@@ -660,19 +781,35 @@ ad_dist_includes()
 #
 # The path may be file, directory or regular expression.
 #
-# Arguments: ad_dist_includes <excludelist>
+# Arguments: ad_dist_includes <excludelist> <log>
 #
 ad_dist_excludes()
 {
-  ad_debug ">ad_dist_excludes: $1"
+  ad_debug "Starting running excludes: $1"
 
+  if test x$2 = xtrue; then
+    ad_log ""
+    ad_log "Following files and directories were excluded from distribution:"
+    ad_log "----------------------------------------------------------------"
+  fi
+
+  cur=`pwd`
+  cd $am_distdir || exit 1
   for i in $1
   do
     ad_debug "Excluding $i"
-    rm -rf $am_distdir/$i
+    if test x$2 = xtrue; then
+      ad_log "  $i"
+    fi
+    rm -rf $i
   done
+  cd $cur || exit 1
+
+  if test x$2 = xtrue; then
+    ad_log ""
+  fi
 
-  ad_debug "<ad_dist_excludes: $1"
+  ad_debug "Ending running excludes: $1"
 }
 
 #
@@ -686,10 +823,10 @@ ad_dist_excludes()
 #
 ad_process_tree()
 {
-  ad_debug ">ad_process_tree: $1"
+  ad_debug "Starting processing non-source files: $1"
 
   # Take files, except source and .ad files.
-  files=`find $am_distdir \! -name \*\.ad \( \
+  files=`find $am_distdir -type f \! -name \*\.ad \( \
        \! -name \*\.[cC] -a \
        \! -name \*\.[cC][cCpP] -a \
        \! -name \*\.[cC][xX][xX] -a \
@@ -697,24 +834,27 @@ ad_process_tree()
        \! -name \*\.[cC]++ -a \
        \! -name \*\.m -a \
        \! -name \*\.[hH] -a \
-       \! -name \*\.hh \)`
+       \! -name \*\.hh -a \
+       \! -name \*\.[cC]\.in -a \
+       \! -name \*\.[cC][cCpP]\.in -a \
+       \! -name \*\.[cC][xX][xX]\.in -a \
+       \! -name \*\.[cC][pP][pP]\.in -a \
+       \! -name \*\.[cC]++\.in -a \
+       \! -name \*\.m\.in -a \
+       \! -name \*\.[hH]\.in -a \
+       \! -name \*\.hh\.in \)`
   files=`echo $files | sed 's/$am_distdir//'`
 
-  # Take away noprocess list
-  if test -f autodist.noprocess; then
-    files=`echo $files" " | sh autodist.noprocess` || exit 1
-  fi
-
   for ff in $files
   do
-    ad_process_file $ff $ff.tmp
+    ad_process_file $ff $ff.tmp true
     if test -f $ff.tmp; then
       rm -f $ff || exit 1
       mv -f $ff.tmp $ff || exit 1
     fi
   done
 
-  ad_debug "<ad_process_tree: $1"
+  ad_debug "Ending processing non-source files: $1"
 }
 
 #
@@ -730,11 +870,11 @@ ad_process_tree()
 #
 ad_process_source_tree()
 {
-  ad_debug ">ad_process_source_tree: $1"
+  ad_debug "Starting processing source files: $1"
 
   # We take only C/C++ files since they use the C compiler friendly
   # version of distdefs.  Other files are not assumed to use them.
-  files=`find $am_distdir \! -name \*\.ad \( \
+  files=`find $am_distdir -type f \! -name \*\.ad \( \
        -name \*\.[cC] -o \
        -name \*\.[cC][cCpP] -o \
        -name \*\.[cC][xX][xX] -o \
@@ -742,23 +882,43 @@ ad_process_source_tree()
        -name \*\.[cC]++ -o \
        -name \*\.m -o \
        -name \*\.[hH] -o \
-       -name \*\.hh \)`
-
-  # Take away noprocess list
-  if test -f autodist.noprocess; then
-    files=`echo $files" " | sh autodist.noprocess` || exit 1
-  fi
+       -name \*\.hh -o \
+       -name \*\.[cC]\.in -o \
+       -name \*\.[cC][cCpP]\.in -o \
+       -name \*\.[cC][xX][xX]\.in -o \
+       -name \*\.[cC][pP][pP]\.in -o \
+       -name \*\.[cC]++\.in -o \
+       -name \*\.m\.in -o \
+       -name \*\.[hH]\.in -o \
+       -name \*\.hh\.in \)`
 
   for ff in $files
   do
-    ad_process_source_file $ff $ff.tmp
+    ad_process_source_file $ff $ff.tmp true
     if test -f $ff.tmp; then
       rm -f $ff || exit 1
       mv -f $ff.tmp $ff || exit 1
     fi
   done
 
-  ad_debug "<ad_process_source_tree: $1"
+  ad_debug "Ending processing source files: $1"
+}
+
+#
+# Removes Autodist dependencies, as they cannot be delivered to distribution.
+#
+# Arguments: ad_remove_dependencies <distdir>
+#
+ad_remove_dependencies()
+{
+  ad_debug "Removing dependencies"
+
+  ams=`find $1 -type f -name Makefile\.\*`
+  for i in $ams
+  do
+    sed -e "/^# S_AD_ENABLE_DEPENDENCIES/,/^# E_AD_ENABLE_DEPENDENCIES/d" $i > $i.tmp
+    mv $i.tmp $i
+  done
 }
 
 #
@@ -769,7 +929,7 @@ ad_process_source_tree()
 #
 ad_makedist_makesane()
 {
-  ad_debug ">ad_makedist_makesane:"
+  ad_debug "Making distribution file modtimes sane"
 
   # DO NOT change these order unless you know what you are doing.
   if test -f $am_distdir/configure.ac; then
@@ -787,7 +947,7 @@ ad_makedist_makesane()
   configh=`grep "^CONFIG_HEADER" Makefile | cut -d= -f2 | sed 's/^[    ]*//'`
   touch $am_distdir/$configh.in 1>/dev/null 2>/dev/null
 
-  files=`find $am_distdir -name Makefile\.in`
+  files=`find $am_distdir -type f -name Makefile\.in`
   for i in $files
   do
     touch $i
@@ -801,7 +961,7 @@ ad_makedist_makesane()
     touch $am_distdir/config.status
   fi
 
-  ad_debug "<ad_makedist_makesane:"
+  ad_debug "Distribution made sane"
 }
 
 #
@@ -812,7 +972,12 @@ ad_makedist_makesane()
 #
 ad_makedist()
 {
-  ad_debug ">ad_makedist"
+  ad_log_open "makedist.log"
+  ad_debug "Starting distribution creation"
+
+  ad_log "Created distribution"
+  ad_log "--------------------"
+  ad_log ""
 
   if test '!' -f autodist.dist; then
     ad_fatal "Autodist has not been run yet to prepare source tree"
@@ -832,6 +997,9 @@ ad_makedist()
   dist_version=`grep "ver:" < autodist.dist | cut -d: -f2` || exit 1
   am_distdir=`grep "distdir:" < autodist.dist | cut -d: -f2` || exit 1
   ad_parse_distribution $distribution false
+  ad_log "  Distribution: $distribution $dist_version"
+  ad_log "  Destination directory: $am_distdir"
+  ad_log ""
   ad_process_distdefs
 
   if test x$opt_no_dist = xtrue; then
@@ -854,18 +1022,30 @@ ad_makedist()
   ad_run_dist_hooks "$pre_p_dist_hooks"
 
   # Run excludes
-  ad_dist_excludes "$excludes"
+  ad_dist_excludes "$excludes" true
 
   # Run includes
-  ad_dist_includes "$includes"
+  ad_dist_includes "$includes" false true
 
   # Include specific license file if specified
   if test "$license" != ""; then
+    ad_log ""
+    ad_log "License file in distribution:"
+    ad_log "-----------------------------"
+    ad_log "  $license into $am_distdir/COPYING"
+    ad_log ""
     cp -p $license $am_distdir/COPYING || exit 1
   fi
 
-  # Process noprocesses
-  ad_process_noprocess
+  # Remove dependencies
+  ad_remove_dependencies $am_distdir
+
+  # Process noprocesses, first pass
+  ad_process_noprocess true
+
+  ad_log ""
+  ad_log "Following files were not re-licensed:"
+  ad_log "-------------------------------------"
 
   # Process source files
   ad_debug "Process distribution source tree"
@@ -875,6 +1055,11 @@ ad_makedist()
   ad_debug "Process distribution tree"
   ad_process_tree $am_distdir
 
+  ad_log ""
+
+  # Process noprocesses, second pass
+  ad_process_noprocess false
+
   # Run post-process_dist-hooks
   ad_run_dist_hooks "$post_p_dist_hooks"
 
@@ -888,16 +1073,20 @@ ad_makedist()
   # Compress
   ad_debug "Compressing distribution package"
   if test x$ad_gzip = xtrue; then
+    ad_debug "Compressing distribution package $am_distdir.tar.gz"
     gzip -9 -c $am_distdir.tar > $am_distdir.tar.gz || exit 1
   fi
   if test x$ad_bzip2 = xtrue; then
+    ad_debug "Compressing distribution package $am_distdir.tar.bz2"
     bzip2 -9 -c $am_distdir.tar > $am_distdir.tar.bz2 || exit 1
   fi
   if test x$ad_compress = xtrue; then
+    ad_debug "Compressing distribution package $am_distdir.tar.Z"
     compress -c $am_distdir.tar > $am_distdir.tar.Z || exit 1
   fi
   if test x$ad_zip = xtrue; then
     rm -f $am_distdir.zip
+    ad_debug "Compressing distribution package $am_distdir.zip"
     zip -rq $am_distdir.zip $am_distdir || exit 1
   fi
   rm -f $am_distdir.tar
@@ -907,9 +1096,10 @@ ad_makedist()
 
   # Cleanup
   rm -rf $am_distdir
-  rm -f autodist.noprocess
 
-  ad_debug "<ad_makedist"
+  ad_log "Distribution created successfully."
+
+  ad_debug "Ending distribution creation"
 }
 
 #
@@ -929,7 +1119,7 @@ ad_makedist()
 #
 ad_handle_options()
 {
-  ad_debug ">ad_handle_options: $1"
+  ad_debug "Handling options: $1"
 
   for i in $1
   do
@@ -944,8 +1134,6 @@ ad_handle_options()
       continue
     fi
   done
-
-  ad_debug "<ad_handle_options: $1"
 }
 
 #
@@ -955,11 +1143,9 @@ ad_handle_options()
 #
 ad_clear_options()
 {
-  ad_debug ">ad_clear_options"
   opt_template=false
   opt_no_dist=false
   opt_no_inherit=false
-  ad_debug "<ad_clear_options"
 }
 
 #
@@ -989,7 +1175,7 @@ ad_parse_distribution()
   local prpdh
   local popdh
 
-  ad_debug ">ad_parse_distribution: $1 $2"
+  ad_debug "Starting parsing distribution: $1 $2"
 
   if test '!' -f $distdir/$1; then
     ad_fatal "Distribution '$1' is not declared"
@@ -1070,6 +1256,16 @@ ad_parse_distribution()
   ad_debug "licenseh: $licenseh"
 
   if test x$2 = xfalse; then
+    # Take rest of the stuff from top distribution
+
+    # We take precedence on defined and undefined distdefs.  Remove
+    # undefined distdefs if we have defined them.
+    for d in $defs
+    do
+      ad_debug "defining undefined $d distdef"
+      undistdefs=`echo $undistdefs | sed s/$d//g`
+    done
+
     # Get distribution name
     dname=`sed 's/^[   ]*//' < $distdir/$1 | grep -v "^#" \
       | grep "name " | cut -d' ' -f2-`
@@ -1134,7 +1330,7 @@ ad_parse_distribution()
   noprocess="$noprocess $nops"
   undistdefs="$undistdefs $undefs"
 
-  ad_debug "<ad_parse_distribution: $1 $2"
+  ad_debug "Ending parsing distribution: $1 $2"
 }
 
 #
@@ -1145,13 +1341,17 @@ ad_parse_distribution()
 #
 ad_process_distdefs()
 {
-  ad_debug ">ad_process_distdefs"
+  ad_debug "Starting processing distdefs"
+
+  ad_log ""
+  ad_log "Following distdefs were processed:"
+  ad_log "----------------------------------"
 
   # Remove all undefined distribution defines
   for i in $undistdefs
   do
     ad_debug "undefining $i distdef"
-    distdefs=`echo $distdefs | sed s/$i//`
+    distdefs=`echo $distdefs | sed s/$i//g`
   done
 
   rm -f autodist.tmp.defs
@@ -1165,19 +1365,26 @@ ad_process_distdefs()
   distdefs=`echo $distdefs`
   rm -f autodist.tmp.defs
 
+  # Log
+  for i in $distdefs
+  do
+    ad_log "  $i"
+  done
+  ad_log ""
+
   ad_debug "distdefs=$distdefs"
 
-  ad_debug "<ad_process_distdefs"
+  ad_debug "Ending processing distdefs"
 }
 
 #
 # Processes for a license header change.
 #
-# Arguments: ad_process_license_header <scriptfile>
+# Arguments: ad_process_license_header <scriptfile> <sourcefile>
 #
 ad_process_license_header()
 {
-  ad_debug ">ad_process_license_header"
+  ad_debug "Starting license header processing"
 
   # Add : separator at the end
   lics=`echo "$licenseh" | sed 's/$/ : /'`
@@ -1212,52 +1419,87 @@ ad_process_license_header()
     # Awk script to replace the license header
     fl=`sed q $src | sed 's/\\//\\\\\//g' > autodist.lsrc` || exit 1
     ll=`sed -n '$p' $src | sed 's/\\//\\\\\//g' > autodist.ldst` || exit 1
-    echo "/`cat autodist.lsrc`/,/`cat autodist.ldst`/ { FILE1=\"$src\"; FILE2=\"$dst\"; getline F1 < FILE1; getline F2 < FILE2; if (F1) sub(F1, F2); else { F1=\"\$\"; sub(F1, F2); } }" >> $1
+    echo "BEGIN { N=0; } /`cat autodist.lsrc`/,/`cat autodist.ldst`/ { FILE1=\"$src\"; FILE2=\"$dst\"; getline F1 < FILE1; getline F2 < FILE2; if (F1) { N=sub(F1, F2); } else { F1=\"\$\"; N=sub(F1, F2); } if (N == 0) print 0 > \"$2.norelicense\"; } END { if (N == 0) print 0 > \"$2.norelicense\"; }" >> $1
     rm -f autodist.lsrc autodist.ldst
 
     src=
     dst=
   done
 
-  ad_debug "<ad_process_license_header"
+  ad_debug "Ending license header processing"
 }
 
 #
 # Process specified noprocesses.  This is called during makedist.
+# The noprocess first copies the noprocess files and dirs into a temp
+# directory, and then removes them from the distdir.  This way they are
+# not processed by Autodist.  After processing they are returned to their
+# correct locations from the temp dir.  Dirty, yeah, but the way we do
+# this until better one comes along.
 #
-# Arguments: ad_process_noprocess
+# Arguments: ad_process_noprocess <process>
+#
+# If <process> is true this excludes and if false this includes.
 #
 ad_process_noprocess()
 {
-  local np=false
-  local n="sed "
+  ad_debug "Starting running noprocesses"
 
-  ad_debug ">ad_process_noprocess"
+  set -f
 
   cur=`pwd`
-  cd $am_distdir || exit 1
-  for i in $noprocess
-  do
-    # Escape
-    ie=`echo $i | sed 's/\\//\\\\\//g'` || exit 1
 
-    n="$n -e 's/$am_distdir\\/$ie //'"
-    np=true
-  done
-  cd $cur || exit 1
+  if test x$1 = xtrue; then
+    ad_log ""
+    ad_log "Following files and directories were not processed:"
+    ad_log "---------------------------------------------------"
+
+    f="$cur/autodist__noprocess"
+    rm -rf $f
+    mkdir -p -- $f || exit 1
+
+    # First, include them to new location with correct directory structure.
+    old_am_distdir="$am_distdir"
+    cd $am_distdir || exit 1
+    am_distdir="$f"
+    nops=" $noprocess"
+    nops=`echo $nops | sed -e 's/ / : /g' -e 's/^/ : /'` || exit 1
+    ad_dist_includes "$nops" false false
+    am_distdir="$old_am_distdir"
+
+    # Then, remove from distdir (they are in temp dir now)
+    for i in $noprocess
+    do
+      ad_log "  $i"
+      rm -rf $i
+    done
+    cd $cur || exit 1
 
-  rm -f autodist.noprocess
-  if test x$np = xtrue; then
-    echo $n > autodist.noprocess || exit 1
+    ad_log ""
+  else
+    # Copy from the temp dir back to distdir
+    cd autodist__noprocess || exit 1
+    old_am_distdir="$am_distdir"
+    am_distdir="$cur/$old_am_distdir"
+    nops=" $noprocess"
+    nops=`echo $nops | sed -e 's/ / : /g' -e 's/^/ : /'` || exit 1
+
+    ad_dist_includes "$nops" false false
+
+    am_distdir="$old_am_distdir"
+    cd $cur || exit 1
+    rm -rf autodist__noprocess
   fi
 
-  ad_debug "<ad_process_noprocess"
+  set +f
+
+  ad_debug "Ending running noprocesses"
 }
 
 #
 # Process a file given as argument for the distribution.
 #
-# Arguments: ad_process_file <filepath> <dest_filepath>
+# Arguments: ad_process_file <filepath> <dest_filepath> <re-license>
 #
 ad_process_file()
 {
@@ -1271,15 +1513,15 @@ ad_process_file()
     return
   fi
 
-  ad_debug ">ad_process_file: $1 $2"
+  ad_debug "Starting processing file: $1 $2"
 
   f="autodist.tmp.script"
   rm -f $f
 
   # If license header is provided, replace the license header in the file.
-  ad_process_license_header $f
-
-  ad_debug "Getting #ifdef's and #ifndef's"
+  if test x$3 = xtrue; then
+    ad_process_license_header $f $1
+  fi
 
   # Get defined distribution defines
   defs=`awk "/^#ifdef "$DP"_DIST_|^#else "$DP"_DIST_/ { print; }" \
@@ -1356,13 +1598,19 @@ ad_process_file()
 
   rm -f $f
 
-  ad_debug "<ad_process_file: $1 $2"
+  # Log if file was not relicensed
+  if test -f "$1.norelicense"; then
+    ad_log "  $1"
+    rm -f $1.norelicense
+  fi
+
+  ad_debug "Ending processing file: $1 $2"
 }
 
 #
 # Process a source file given as argument for the distribution.
 #
-# Arguments: ad_process_source_file <filepath> <dest_filepath>
+# Arguments: ad_process_source_file <filepath> <dest_filepath> <re-license>
 #
 ad_process_source_file()
 {
@@ -1376,15 +1624,15 @@ ad_process_source_file()
     return
   fi
 
-  ad_debug ">ad_process_source_file: $1 $2"
+  ad_debug "Starting processing source file: $1 $2"
 
   f="autodist.tmp.script"
   rm -f $f
 
   # If license header is provided, replace the license header in the file.
-  ad_process_license_header $f
-
-  ad_debug "Getting #ifdef's and #ifndef's"
+  if test x$3 = xtrue; then
+    ad_process_license_header $f $1
+  fi
 
   # Get defined distribution defines
   defs=`awk '/^#ifdef SILC_DIST_|^#else \/\* SILC_DIST_/ { print; }' \
@@ -1461,7 +1709,67 @@ ad_process_source_file()
 
   rm -f $f
 
-  ad_debug "<ad_process_source_file: $1 $2"
+  # Log if file was not relicensed
+  if test -f "$1.norelicense"; then
+    ad_log "  $1"
+    rm -f $1.norelicense
+  fi
+
+  ad_debug "Ending processing source file: $1 $2"
+}
+
+#
+# Processes a file.  This is the -p, --process option.
+#
+# Arguments: ad_process <type> <src> <dst>
+#
+ad_process()
+{
+  ad_debug "Starting process: $1 $2 $3"
+
+  nolog=true
+
+  if test '!' -f autodist.dist; then
+    ad_fatal "Autodist has not been run yet to prepare source tree"
+  fi
+
+  # Parse distribution
+  distribution=`grep "dist:" < autodist.dist | cut -d: -f2` || exit 1
+  dist_version=`grep "ver:" < autodist.dist | cut -d: -f2` || exit 1
+  ad_parse_distribution $distribution false
+  ad_process_distdefs
+
+  # Process file
+  case "$1" in
+    makefile)
+      if test -z $3; then
+       ad_fatal "File type $1 requires <dst> argument"
+      fi
+      ad_make_makefile_am $2 $3
+      exit 0;;
+
+    configure)
+      ad_make_configure_ac $2
+      exit 0;;
+
+    non-source)
+      if test -z $3; then
+       ad_fatal "File type $1 requires <dst> argument"
+      fi
+      ad_process_file $2 $3 false
+      exit 0;;
+
+    source)
+      if test -z $3; then
+       ad_fatal "File type $1 requires <dst> argument"
+      fi
+      ad_process_source_file $2 $3 false
+      exit 0;;
+
+    *)
+      ad_fatal "Unknown file type: $1";
+      ;;
+  esac
 }
 
 #
@@ -1471,17 +1779,23 @@ ad_process_source_file()
 #
 ad_run_hooks()
 {
-  ad_debug ">ad_run_hooks: $1"
+  ad_debug "Running hooks: $1"
+
+  ad_log ""
+  ad_log "Hooks executed:"
+  ad_log "--------------"
 
   for i in $1
   do
     if test '!' -f $i; then
       ad_fatal "Hook script $i does not exist"
     fi
+    ad_log "  sh $i \"$distribution\" \"$dist_version\" \"$package\""
     sh $i "$distribution" "$dist_version" "$package" || exit 1
   done
+  ad_log ""
 
-  ad_debug "<ad_run_hooks: $1"
+  ad_debug "Ending running hooks: $1"
 }
 
 #
@@ -1491,17 +1805,24 @@ ad_run_hooks()
 #
 ad_run_dist_hooks()
 {
-  ad_debug ">ad_run_dist_hooks: $1"
+  ad_debug "Starting running distributions hooks: $1"
+
+  ad_log ""
+  ad_log "Distribution hooks executed:"
+  ad_log "----------------------------"
 
   for i in $1
   do
     if test '!' -f $i; then
       ad_fatal "Dist hook script $i does not exist"
     fi
+
+    ad_log "  sh $i \"$distribution\" \"$dist_version\" \"$package\" \"$am_distdir\""
     sh $i "$distribution" "$dist_version" "$package" "$am_distdir" || exit 1
   done
+  ad_log ""
 
-  ad_debug "<ad_run_dist_hooks: $1"
+  ad_debug "Ending running distribution hooks"
 }
 
 ###############################################################################
@@ -1510,11 +1831,10 @@ ad_run_dist_hooks()
 usage="Usage: autodist [options] [distribution] [version]"
 help="\
 Autodist prepares source tree for configuration, compilation and
-distribution.  Prepares the source tree from the \`autodist.ad'
-configuration file.  Generates Automake.am files from Automake.ad
-files, configure.ac file from configure.ad file(s), generates the
-configure script by running Autoconf tool, and generates Makefile.in
-files by running Automake tool.
+distribution.  Generates Automake.am files from Automake.ad files, 
+configure.ac file from configure.ad file(s), generates the configure 
+script by running Autoconf tool, and generates Makefile.in files by 
+running Automake tool.
 
 Operation modes:
   -h, --help                print this help, then exit
@@ -1524,6 +1844,10 @@ Operation modes:
   -s, --distdefs [<dist>]   print distribution defines of <dist>, then exit
   -i, --init                initialize Autodist environment, create default
                             distribution directory and distribution, then exit
+  -p, --process <type> <src> [<dst>]
+                            process file <src> into <dst> for distribution,
+                            <type> is 'makefile', 'configure', 'non-source'
+                            or 'source' and defines the type of <src>
   -m, --makedist            create and package distribution
       --gzip                create package compressed with gzip (default)
       --bzip2               create also package compressed with bzip2
@@ -1556,13 +1880,25 @@ while test $# -gt 0; do
     fi
     ad_process_distdefs
     echo "Distdefs:" 1>&2;
-    echo "${distdefs}";
+    for i in $distdefs
+    do
+      echo "$i";
+    done
     exit 0;;
 
   -i | --init)
     ad_initialize;
     exit 0;;
 
+  -p | --process)
+    shift;
+    if test $# -ge 2; then
+      ad_process $1 $2 $3
+    else
+      echo "${usage}" 1>&2;
+    fi
+    exit 0;;
+
   -m | --makedist)
     ad_makedist
     exit 0;;
@@ -1618,6 +1954,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. " 1>
   esac
 done
 
+# Open log file
+ad_log_open "autodist.log"
+
+ad_log "Processing source tree for compilation and configuration"
+ad_log "--------------------------------------------------------"
+ad_log ""
+
 #
 # Parse the requested distribution
 #
@@ -1626,13 +1969,18 @@ if test $# != 0; then
   distfile=$distribution
   shift
 fi
+
 ad_parse_distribution $distribution false
-ad_process_distdefs
 
 if test $# != 0; then
   dist_version="${1}";
 fi
 
+ad_log "  Distribution: $distribution $dist_version"
+ad_log ""
+
+ad_process_distdefs
+
 ad_debug "Preparing source tree for configuration and compilation..."
 ad_debug "Preparing $distribution distribution version $dist_version"
 
@@ -1688,5 +2036,7 @@ echo "distdir:$package-$dist_version" >> autodist.dist
 #
 ad_run_hooks "$post_hooks"
 
+ad_log "Source tree processed successfully."
 ad_debug "Done, now run ./configure and make."
+
 exit 0
index 333ccb347dca478c696e80884a4137478de8d9b6..90b731211ff27885a1de18170956b53d7802528a 100644 (file)
@@ -57,6 +57,11 @@ directory 'distdir', 'autodist.conf' configuration file and the
 default distribution 'default', then exits.
 .PP
 .TP
+\fB\-p\fR, \fB\-\-process\fR \fB<type>\fR \fB<src>\fR \fB<dst>\fR
+Process file <src> into <dst> for distribution, <type> is 'makefile', 
+'configure', 'non-source' or 'source' and defines the type of <src>.
+.PP
+.TP
 \fB\-m\fR, \fB\-\-makedist\fR
 Creates and packages distribution
 .PP
index 928432e43d25f0fbe69f301f426c93cb0d654548..a054dac701185bfb3a39ad51e928f985c4fb31ac 100644 (file)
@@ -80,6 +80,7 @@ Integrating Autodist
 * Makefile.ad files::           Makefile.ad for creating Makefile.am
 * Other .ad files::             Other files with .ad suffix
 * Distdefines::                 Using distdefs in files
+* Dependencies::                Autodist dependency support
 
 Invoking Autodist
 
@@ -240,6 +241,7 @@ as they may not exist yet.
 * Makefile.ad files::           Makefile.ad for creating Makefile.am
 * Other .ad files::             Other files with .ad suffix
 * Distdefines::                 Using distdefs in files
+* Dependencies::                Autodist dependency support
 @end menu
 
 
@@ -500,6 +502,10 @@ Will replace all appearances of the license header in 'license/BSD-header'
 file to the license header in 'license/GPL-header' in any file in the
 distribution.  Note that, the header change will be performed when
 the distribution is packaged (@pxref{Creating distribution, , , , }).
+The 'makedist.log' file created by Autodist during distribution packaging
+will list all files that were not re-licensed.  The log file can be used
+to check that the distribution is re-licensed correctly, and fix any
+possible mistakes.
 
 With 'license-header' directive you may initially set your files in the
 source tree into what ever license you prefer.  However, if you need to
@@ -581,13 +587,14 @@ into the distribution.  The <distfile> specifies the name of the
 inherited distribution.  If the distribution cannot be inherited Autodist
 will give an error.
 
-The 'inherit' will inherit the following information from the distribution:
-distdefs, undefines, includes, excludes and noprocess.  Other information
-will not be inherited.  If the inherited distribution inherits other
-distributions, they will also be inherited automatically.  User should be
-careful when inheriting distributions as it may be possible to create an
-infinite recursion.  The Autodist would allow for this and not detect this
-error.  Zero or more 'inherit' directives may be set for distribution.
+The 'inherit' will inherit the following information from the 
+distribution: distdefs, undefines, includes, excludes and noprocesses.  
+Other information will not be inherited.  If the inherited distribution 
+inherits other distributions, they will also be inherited automatically.  
+User should be careful when inheriting distributions as it may be possible 
+to create an infinite recursion.  The Autodist would allow for this and 
+not detect this error.  Zero or more 'inherit' directives may be set for 
+distribution.
 
 Example:
 @example
@@ -600,6 +607,21 @@ Will inherit distributions 'common', 'client' and 'toolkit' into this
 distribution.  All distdefs, undefines, includes, excludes and noprocesses
 from these distributions are now also part this distribution.
 
+The distribution that is being prepared or packaged take precedence when 
+defining distdefs that were specificly undefined in the inherited 
+distribution.  This means that if the inherited distribution specificly 
+undefines a distdefs but the inheriting distribution (one being prepared 
+or packaged) specificly defines it, the distdef will be defined.  
+Similarly, if the inherited distribution defines a distdef but the 
+inheriting distribution undefines it, the distdef will be undefined.  
+Note that, this precedence works only in the top distribution (the one 
+being prepared or packaged).  If the inherited distribution inherits other 
+distributions, all distdefs (defined and specificly undefined) will be 
+inherited as is.  This means that if one inherited distribution defines a 
+distdef that other inherited distribution distdef undefines, it will be 
+undefined.  However, the top distribution can then override them if 
+needed.
+
 
 @section Directive: define <symbol>
 
@@ -769,26 +791,24 @@ This will exclude the file 'README' and anything that match 'doc/client*'.
 
 @section Directive: noprocess <filename> [...]
 
-The 'noprocess' directive can be used to tell Autodist specificly not to
-process a file.  The Autodist will not process the file during
-preparation or during distribution packaging.  This directive is optional.
-One or more file can be specified in the 'noprocess' directive.  Zero or
-more 'noprocess' directives can be used in distribution.  The <filename>
-can be a single file or a regular expression that will match several files.
-Note that, in current Autodist version 'noprocess' cannot be used to
-specify directories.
+The 'noprocess' directive can be used to tell Autodist specificly not to 
+process files or directories.  The Autodist will not process the files 
+during distribution packaging.  This directive is optional.  One or more 
+files can be specified in the 'noprocess' directive.  Zero or more 
+'noprocess' directives can be used in distribution.  The <filename> can be 
+a single file, a single directory or a regular expression that will match 
+several files and/or directories.
 
 Example:
 @example
 noprocess autodist.texi
-noprocess apps/foo/*
+noprocess apps/foo/
 @end example
 
-Autodist will not process 'autodist.texi' file, and any file that match
-'apps/foo/*'.  Note that, any subdirectory under 'apps/foo/' will not
-match, and will be processed.
+Autodist will not process 'autodist.texi' file, and any files and 
+directories under 'apps/foo/'.
 
-Also note that, 'noprocess' directive cannot be used to disallow 
+Note that, 'noprocess' directive cannot be used to disallow 
 processing of any file with '.ad' suffix.
 
 
@@ -1002,7 +1022,21 @@ macro 'AC_OUTPUT'.  This macro has no arguments.
 Note that, the 'configure.ad' fragments are not real full featured
 configure scripts.  They must not use 'AD_INIT', 'AD_INCLUDE_CONFIGURE',
 'AC_INIT' or any other initialization macros.
+@end defmac
+
+
+@defmac AD_DISABLE_DEPENDENCIES
 
+This macro is used to disable Autodist dependencies.  If this macro is
+used, then after editing 'Makefile.ad' and 'configure.ad' files the
+Autodist must be run manually.  When dependencies are enabled Autodist is
+run automatically when source is compiled with 'make'.  Dependencies make
+the development easier.  This macro has no arguments.
+
+Note that, the dependencies are enabled only in the prepared source tree.  
+Depedencies are not delivered to distribution, as they would require the 
+presence of 'Makefile.ad' and 'configure.ad' files, which are not 
+delivered to distribution.
 @end defmac
 
 @menu
@@ -1050,7 +1084,9 @@ If you need processed files during configuration or compilation then they
 need to have '.ad' suffix.
 
 Note that, the distdef format used in these files must be the non-source
-format.
+format, even if the file is source file.  This is because the distdefs
+are processed during source tree preparation, and the source file will
+have all distdefs removed when it is compiled.
 
 @menu
 * Distdefines::                 Using distdefs in files
@@ -1240,8 +1276,40 @@ The following suffixes will be considered as source files by the Autodist:
     .hh
 @end example
 
+Also, any file that has '.in' suffix with any of the above source file 
+suffixes, the format inside the file must follow the source code format.  
 Using distdefs in any other file must follow the non-source format.
 
+Example:
+@example
+    .c.in
+    .h.in
+@end example
+
+In this example, in both of the files the source code format is used.
+
+
+@node Dependencies
+@section Autodist dependency support
+
+Autodist support dependencies for 'Makefile.ad' and 'configure.ad' files.  
+When these files are edited, they are processed by Autodist automatically 
+when the source tree is compiled with 'make'.  This makes development in 
+the source tree easier, when Autodist does not have to be run manually.
+The dependencies can be disabled by using 'AD_DISABLE_DEPENDENCIES' macro 
+in the 'configure.ad' file.
+
+When editing 'configure.ad' fragments the modifcation is detected when the 
+source tree is compiled with 'make' from the top source directory.  
+Giving 'make' in a subdirectory will not detect a change in 'configure.ad' 
+fragment.
+
+Dependencies are present only in the prepared source tree.  They are not 
+delivered to created distribution, as they depend on 'Makefile.ad' and 
+'configure.ad' files which are not present in the created distribution.  
+Autodist automatically removes the dependencies when the distribution is 
+created.
+
 
 @node Invoking Autodist
 @chapter Invoking Autodist
@@ -1282,6 +1350,12 @@ Initializes Autodist environment.  Creates the default distribution
 directory 'distdir', 'autodist.conf' configuration file and the
 default distribution 'default', then exits.
 
+@item -p
+@itemx --process <type> <src> <dst>
+Process file <src> into <dst> for distribution, <type> is 'makefile',
+'configure', 'non-source' or 'source' and defines the type of <src>,
+then exits.
+
 @item -m
 @itemx --makedist
 Creates and packages distribution
@@ -1391,6 +1465,9 @@ Creating the distribution that file will be read by the Autodist
 automatically.  That file should not be removed or the distribution
 cannot be packaged.
 
+Autodist also created a log file, 'autodist.log', that will include
+messages created by Autodist during preparation.
+
 @menu
 * Creating distribution::       Creating distribution with Autodist
 @end menu
@@ -1432,6 +1509,14 @@ are being packaged you may set 'pre-process-dist-hook',
 distribution file.  Also note that any hooks provided by Automake in 
 Makefiles will be run in normal manner.
 
+When creating the distribution Autodist creates a log file, 
+'makedist.log', that will include messages created by Autodist.  It is 
+suggested that this file is checked after distribution is created.  For 
+example, when the 'license-header' directive is used to re-license the 
+distribution, the 'makedist.log' will include list of files that were not 
+re-licensed.  The log file can be used to verify that the distribution was 
+re-licensed correctly, and fix any possible mistakes.
+
 
 @node Examples
 @chapter Examples
index c1e2ae6532dd10e333584d767869eb78b43892a6..f17d43b162681613106eb56f2f2972cc5f1d10e6 100644 (file)
@@ -22,7 +22,9 @@ TESTS =                       \
        autodist2.test          \
        autodist3.test          \
        autodist4.test          \
-       autodist5.test
+       autodist5.test          \
+       autodist6.test          \
+       autodist7.test
 
 clean-local:
        -rm -rf test
index f475436d5f060cfec41d8800ec8dd842a00d1fda..f1b70935f12bee7733f4f6c310fe5d438bac5188 100755 (executable)
@@ -72,8 +72,12 @@ $AUTODIST || exit 1
 make || exit 1
 echo make ok
 
+echo update test
+touch Makefile.ad
+make || exit 1
+echo update test ok
+
 echo test ok
 
 # Cleanup
 rm -rf subdir distdir
-
diff --git a/apps/autodist/tests/autodist6.test b/apps/autodist/tests/autodist6.test
new file mode 100755 (executable)
index 0000000..c4e2d9e
--- /dev/null
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+AUTODIST=../../autodist
+
+rm -rf test
+mkdir test
+
+cd test || exit 1
+
+chmod +x $AUTODIST || exit 1
+
+cat << EOF > configure.ad
+AD_INIT
+#ifdef _DIST_DEFAULT
+AC_CANONICAL_BUILD
+AM_INIT_AUTOMAKE
+AC_PREREQ(2.52)
+AC_CONFIG_HEADERS(config.h)
+AC_CONFIG_FILES(
+Makefile
+)
+AC_OUTPUT
+echo configure.ad ok
+#else !_DIST_DEFAULT
+echo "ERROR"
+exit 1
+#endif _DIST_DEFAULT
+EOF
+
+cat << EOF > Makefile.ad
+SUBDIRS=       \\
+#ifdef _DIST_NODEF
+       nodef   \\
+       poa     \\
+       paa     \\
+#endif _DIST_NODEF
+       .       \\
+       .       \\
+       .       \\
+       .       \\
+
+EOF
+
+rm -rf distdir subdir
+mkdir -p subdir || exit 1
+
+$AUTODIST -i || exit 1
+if test '!' -d distdir; then
+  echo "error: distdir/ does no exist"
+  exit 1
+fi 
+
+cp -p ../../default distdir || exit 1
+cp -p ../../autodist.conf distdir || exit 1
+
+touch README NEWS AUTHORS ChangeLog
+
+$AUTODIST || exit 1
+
+./configure || exit 1
+make || exit 1
+echo make ok
+
+echo test ok
+
+# Cleanup
+rm -rf subdir distdir
+
diff --git a/apps/autodist/tests/autodist7.test b/apps/autodist/tests/autodist7.test
new file mode 100755 (executable)
index 0000000..6570cab
--- /dev/null
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+AUTODIST=../../autodist
+
+rm -rf test
+mkdir test
+
+cd test || exit 1
+
+chmod +x $AUTODIST || exit 1
+
+cat << EOF > configure.ad
+AD_INIT
+AD_DISABLE_DEPENDENCIES
+#ifdef _DIST_DEFAULT
+AC_CANONICAL_BUILD
+AM_INIT_AUTOMAKE
+AC_PREREQ(2.52)
+AC_CONFIG_HEADERS(config.h)
+AC_CONFIG_FILES(
+Makefile
+)
+AC_OUTPUT
+echo configure.ad ok
+#else !_DIST_DEFAULT
+echo "ERROR"
+exit 1
+#endif _DIST_DEFAULT
+EOF
+
+cat << EOF > Makefile.ad
+SUBDIRS=       \\
+#ifdef _DIST_NODEF
+       nodef   \\
+       poa     \\
+       paa     \\
+#endif _DIST_NODEF
+       .       \\
+       .       \\
+       .       \\
+       .       \\
+
+EOF
+
+rm -rf distdir subdir
+mkdir -p subdir || exit 1
+
+$AUTODIST -i || exit 1
+if test '!' -d distdir; then
+  echo "error: distdir/ does no exist"
+  exit 1
+fi 
+
+cp -p ../../default distdir || exit 1
+cp -p ../../autodist.conf distdir || exit 1
+
+touch README NEWS AUTHORS ChangeLog
+
+$AUTODIST || exit 1
+
+./configure || exit 1
+make || exit 1
+echo make ok
+
+echo test ok
+
+# Cleanup
+rm -rf subdir distdir
+
diff --git a/apps/irssi/configure.ad b/apps/irssi/configure.ad
new file mode 100644 (file)
index 0000000..4b3b1b7
--- /dev/null
@@ -0,0 +1,67 @@
+#ifdef SILC_DIST_CLIENT
+#
+#  apps/irssi/configure.ad
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+# The actual configure script is apps/irssi/configure.in.  This file is
+# for getting irssi specific stuff to top configure script with Autodist
+# without polluting the top configure.ad file with these stuff.
+
+IRSSI_SUBDIR=
+
+#ifdef SILC_DIST_TOOLKIT
+if test x$without_irssi = xfalse; then
+#endif SILC_DIST_TOOLKIT
+
+IRSSI_SUBDIR=irssi
+
+# help directory
+#
+HELPDIR="$silc_prefix/help"
+AC_ARG_WITH(helpdir,
+  [[  --with-helpdir=DIR      directory for SILC Client help files [PREFIX/help]]],
+  [
+    case "$withval" in
+      no|yes)
+        ;;
+      *)
+       HELPDIR="$withval"
+       ;;
+    esac
+  ])
+AC_SUBST(HELPDIR)
+AC_DEFINE_UNQUOTED([SILC_HELPDIR], "$HELPDIR", [SILC_HELPDIR])
+
+# Irssi perl support
+#
+AC_ARG_WITH(perl,
+  [[  --with-perl[=yes|no|module]  Build with Perl support - also specifies
+                               if it should be built into main silc binary
+                               (static, default) or as a module]])
+
+AC_CONFIG_SUBDIRS(apps/irssi)
+AC_CONFIG_FILES(
+apps/irssi/Makefile.defines
+apps/irssi/Makefile.defines_int
+)
+
+irssi="yes"
+#ifdef SILC_DIST_TOOLKIT
+fi     # without_irssi = false
+#endif SILC_DIST_TOOLKIT
+
+AC_SUBST(IRSSI_SUBDIR)
+#endif SILC_DIST_CLIENT
index 02cb3dd807e0caf2caa86bce895c2a587aeb6270..2b248696ef2e148489214b41310b217513e9e01a 100644 (file)
@@ -19,7 +19,7 @@ silc_DEPENDENCIES =           \
 LIBS = $(SILC_COMMON_LIBS)
 silc_LDADD = \
        @COMMON_LIBS@ \
-       -L../../../lib -lsilcclient \
+       -L$(silc_top_srcdir)/lib -lsilcclient \
        @PERL_LINK_LIBS@ \
        @PERL_FE_LINK_LIBS@ \
        @PERL_LINK_FLAGS@ \
index 71298944b95a0cdcc8aa41bd664b5ac2b144936a..b8387ff28d033fbeaa2b28002a6ca2eeb0953edc 100644 (file)
@@ -8,5 +8,5 @@ WriteMakefile('NAME' => 'Irssi::Silc',
              'LIBS' => '',
              'OBJECT' => '$(O_FILES)',
              'TYPEMAPS' => ['../common/typemap'],
-             'INC' => '-I../../.. -I@top_srcdir@/src -I@top_srcdir@/src/core -I@top_srcdir@/src/silc/core -I@top_srcdir@/src/silc -I$(silc_top_srcdir) -I$(silc_top_srcdir)/lib/silccore -I$(silc_top_srcdir)/lib/silccrypt -I$(silc_top_srcdir)/lib/silcmath -I$(silc_top_srcdir)/lib/silcmath/mpi -I$(silc_top_srcdir)/lib/silcske -I$(silc_top_srcdir)/lib/silcsim -I$(silc_top_srcdir)/lib/silcutil -I$(silc_top_srcdir)/lib/silcsftp -I$(silc_top_srcdir)/lib/silcclient -I$(silc_top_srcdir)/lib/contrib -I$(silc_top_srcdir)/includes -I$(silc_top_srcdir)/doc @GLIB_CFLAGS@',
+             'INC' => '-I../../.. -I@top_srcdir@/src -I@top_srcdir@/src/core -I@top_srcdir@/src/silc/core -I@top_srcdir@/src/silc -I$(silc_top_srcdir) -I$(silc_top_srcdir)/lib/silccore -I$(silc_top_srcdir)/lib/silccrypt -I$(silc_top_srcdir)/lib/silcmath -DHAVE_SILCDEFS_H -I$(silc_top_srcdir)/lib/silcske -I$(silc_top_srcdir)/lib/silcsim -I$(silc_top_srcdir)/lib/silcutil -I$(silc_top_srcdir)/lib/silcsftp -I$(silc_top_srcdir)/lib/silcclient -I$(silc_top_srcdir)/lib/contrib -I$(silc_top_srcdir)/includes -I$(silc_top_srcdir)/doc @GLIB_CFLAGS@',
              'VERSION_FROM' => '@srcdir@/Silc.pm');
index e61e1c1d023ae4ce8826bb35c19565a511685d52..47c927b4baffa668ba048daced079a36ab00742e 100644 (file)
@@ -4,13 +4,13 @@
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001, 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 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
@@ -48,8 +48,6 @@ static int idletag = -1;
 
 SilcClient silc_client = NULL;
 extern SilcClientOperations ops;
-extern bool silc_debug;
-extern bool silc_debug_hexdump;
 
 void silc_expandos_init(void);
 void silc_expandos_deinit(void);
@@ -94,8 +92,8 @@ static void destroy_server_connect(SERVER_CONNECT_REC *conn)
 static void silc_init_userinfo(void)
 {
   const char *set, *nick, *user_name;
-  char *str;   
-        
+  char *str;
+
   /* check if nick/username/realname wasn't read from setup.. */
   set = settings_get_str("real_name");
   if (set == NULL || *set == '\0') {
@@ -105,7 +103,7 @@ static void silc_init_userinfo(void)
     settings_set_str("real_name",
                     str != NULL ? str : silc_get_real_name());
   }
+
   /* username */
   user_name = settings_get_str("user_name");
   if (user_name == NULL || *user_name == '\0') {
@@ -125,10 +123,10 @@ static void silc_init_userinfo(void)
     if (!str)
       str = g_getenv("IRCNICK");
     settings_set_str("nick", str != NULL ? str : user_name);
-    
+
     nick = settings_get_str("nick");
   }
-                
+
   /* alternate nick */
   set = settings_get_str("alternate_nick");
   if (set == NULL || *set == '\0') {
@@ -165,14 +163,15 @@ static void sig_setup_changed(void)
   bool debug = settings_get_bool("debug");
   if (debug) {
     const char *debug_string = settings_get_str("debug_string");
-    i_debug = silc_debug = TRUE;
+    i_debug = TRUE;
+    silc_log_debug(TRUE);
     if (strlen(debug_string))
       silc_log_set_debug_string(debug_string);
     silc_log_set_debug_callbacks(silc_irssi_debug_print, NULL, NULL, NULL);
     return;
   }
   if (i_debug)
-    silc_debug = FALSE;
+    silc_log_debug(FALSE);
 #endif
 }
 
@@ -180,7 +179,7 @@ static void sig_setup_changed(void)
 
 static bool silc_log_misc(SilcLogType type, char *message, void *context)
 {
-  printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s: %s", 
+  printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s: %s",
            (type == SILC_LOG_INFO ? "[Info]" :
             type == SILC_LOG_WARNING ? "[Warning]" : "[Error]"), message);
   return TRUE;
@@ -202,7 +201,7 @@ static void silc_register_cipher(SilcClient client, const char *cipher)
        silc_cipher_register(&(silc_default_ciphers[i]));
        break;
       }
-    
+
     if (!silc_cipher_is_supported(cipher)) {
       SILC_LOG_ERROR(("Unknown cipher `%s'", cipher));
       exit(1);
@@ -223,7 +222,7 @@ static void silc_register_hash(SilcClient client, const char *hash)
        silc_hash_register(&(silc_default_hash[i]));
        break;
       }
-    
+
     if (!silc_hash_is_supported(hash)) {
       SILC_LOG_ERROR(("Unknown hash function `%s'", hash));
       exit(1);
@@ -244,7 +243,7 @@ static void silc_register_hmac(SilcClient client, const char *hmac)
        silc_hmac_register(&(silc_default_hmacs[i]));
        break;
       }
-    
+
     if (!silc_hmac_is_supported(hmac)) {
       SILC_LOG_ERROR(("Unknown HMAC `%s'", hmac));
       exit(1);
@@ -257,18 +256,18 @@ static void silc_register_hmac(SilcClient client, const char *hmac)
 
 /* Finalize init. Init finish signal calls this. */
 
-void silc_opt_callback(poptContext con, 
+void silc_opt_callback(poptContext con,
                       enum poptCallbackReason reason,
                       const struct poptOption *opt,
                       const char *arg, void *data)
 {
   if (strcmp(opt->longName, "nick") == 0) {
-    g_free(silc_client->nickname);  
+    g_free(silc_client->nickname);
     silc_client->nickname = g_strdup(arg);
   }
 
   if (strcmp(opt->longName, "hostname") == 0) {
-    silc_free(silc_client->hostname);  
+    silc_free(silc_client->hostname);
     silc_client->hostname = g_strdup(arg);
   }
 
@@ -297,11 +296,11 @@ void silc_opt_callback(poptContext con,
   }
 
   if (strcmp(opt->longName, "debug") == 0) {
-    silc_debug = TRUE;
-    silc_debug_hexdump = TRUE;
+    silc_log_debug(TRUE);
+    silc_log_debug_hexdump(TRUE);
     silc_log_set_debug_string(arg);
 #ifndef SILC_DEBUG
-    fprintf(stdout, 
+    fprintf(stdout,
            "Run-time debugging is not enabled. To enable it recompile\n"
            "the client with --enable-debug configuration option.\n");
     sleep(1);
@@ -476,14 +475,14 @@ void silc_core_init(void)
   rec->create_channel_setup = create_channel_setup;
   rec->create_server_connect = create_server_connect;
   rec->destroy_server_connect = destroy_server_connect;
-  rec->server_init_connect = silc_server_init_connect; 
+  rec->server_init_connect = silc_server_init_connect;
   rec->server_connect = silc_server_connect;
-  rec->channel_create = (CHANNEL_REC *(*) (SERVER_REC *, const char *, 
+  rec->channel_create = (CHANNEL_REC *(*) (SERVER_REC *, const char *,
                                           const char *, int))
     silc_channel_create;
   rec->query_create = (QUERY_REC *(*) (const char *, const char *, int))
     silc_query_create;
-  
+
   chat_protocol_register(rec);
   g_free(rec);
 
@@ -504,7 +503,7 @@ void silc_core_deinit(void)
 {
   if (idletag != -1)
     g_source_remove(idletag);
-  
+
   signal_emit("chat protocol deinit", 1,
        chat_protocol_find("SILC"));
   signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed);
@@ -517,9 +516,9 @@ void silc_core_deinit(void)
   silc_expandos_deinit();
   silc_lag_deinit();
   silc_chatnets_deinit();
-  
+
   chat_protocol_unregister("SILC");
-  
+
   g_free(silc_client->username);
   g_free(silc_client->realname);
   silc_free(silc_client->hostname);
index d166e1fb1fd97906c0a210a2e53eb874036c00f0..0352ea8729b15aef7dc618bea0f9931ac142a9c0 100644 (file)
@@ -36,9 +36,50 @@ silcd_SOURCES = \
        serverid.c \
        server_version.c
 
-LIBS = $(SILC_COMMON_LIBS) -lsilc
+LIBS = $(SILC_COMMON_LIBS)
 LDADD =
 
 EXTRA_DIST = *.h
 
+install-dirs-server:
+       -mkdir -p $(docdir)
+       -mkdir -p $(etcdir)
+       -mkdir -p $(logsdir)
+       -mkdir -p $(mandir)/man5
+       -mkdir -p $(mandir)/man8
+
+doc-install-server:
+       -$(INSTALL_DATA) $(top_srcdir)/doc/example_silcd.conf $(docdir)/
+       -@if test -f $(top_srcdir)/doc/silcd.8 ; then \
+        $(INSTALL_DATA) $(top_srcdir)/doc/silcd.8 $(mandir)/man8; \
+       fi
+       -@if test -f $(top_srcdir)/doc/silcd.conf.5 ; then \
+        $(INSTALL_DATA) $(top_srcdir)/doc/silcd.conf.5 $(mandir)/man5; \
+       fi
+
+etc-install-server:
+       -@if test '!' -f $(etcdir)/silcd.conf ; then \
+         $(INSTALL_DATA) $(top_srcdir)/doc/example_silcd.conf \
+               $(etcdir)/silcd.conf; \
+         $(INSTALL_DATA) $(top_srcdir)/doc/silcalgs.conf \
+               $(etcdir)/silcalgs.conf; \
+          chmod go= $(etcdir)/silcd.conf; \
+       fi
+
+examples-install:
+       -mkdir -p $(docdir)/examples/
+       -$(INSTALL_DATA) $(top_srcdir)/doc/examples/* $(docdir)/examples/
+
+generate-server-key:
+       -@if test '!' -f $(etcdir)/silcd.pub ; then \
+         $(sbindir)/silcd -C $(etcdir); \
+       fi
+
+install-data-hook:             \
+       install-dirs-server     \
+       doc-install-server      \
+       etc-install-server      \
+       examples-install        \
+       generate-server-key
+
 include $(top_srcdir)/Makefile.defines.in
index c11e549777c0eab75d36b8fe2e98df05f0a7475f..82bc2f6ee035a5af7853e0b511cfaa9b37af9b7d 100644 (file)
@@ -74,6 +74,7 @@ SilcServerCommand silc_command_list[] =
   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(service, SERVICE, SILC_CF_LAG_STRICT | SILC_CF_REG),
 
   SILC_SERVER_CMD(connect, PRIV_CONNECT,
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
@@ -1806,12 +1807,14 @@ SILC_SERVER_CMD_FUNC(stats)
      statistical information. */
   if (!cmd->pending && server->server_type != SILC_ROUTER &&
       !server->standalone) {
+    SilcBuffer idp;
+
     /* Statistics */
     cmd->server->stat.commands_sent++;
 
     /* Send request to our router */
-    SilcBuffer idp = silc_id_payload_encode(server->router->id,
-                                           SILC_ID_SERVER);
+    idp = silc_id_payload_encode(server->router->id,
+                                SILC_ID_SERVER);
     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS,
                                            ++server->cmd_ident, 1,
                                            1, idp->data, idp->len);
@@ -2414,6 +2417,18 @@ SILC_SERVER_CMD_FUNC(join)
       goto out;
     }
 
+#ifndef SILC_DIST_INPLACE
+    /* Limit how many channels client can join */
+    if (!cmd->pending && entry->channels &&
+       silc_hash_table_count(entry->channels) >=
+       server->config->param.chlimit) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                                           SILC_STATUS_ERR_RESOURCE_LIMIT,
+                                           0);
+      goto out;
+    }
+#endif /* SILC_DIST_INPLACE */
+
     silc_free(client_id);
     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
 
@@ -2632,8 +2647,13 @@ SILC_SERVER_CMD_FUNC(motd)
       /* Send motd */
       motd = silc_file_readfile(server->config->server_info->motd_file,
                                &motd_len);
-      if (!motd)
+      if (!motd) {
+       /* No motd */
+       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
+                                      SILC_STATUS_OK, 0, ident, 1,
+                                      2, idp->data, idp->len);
        goto out;
+      }
 
       motd[motd_len] = 0;
       silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_MOTD,
@@ -5086,6 +5106,50 @@ SILC_SERVER_CMD_FUNC(getkey)
   silc_server_command_free(cmd);
 }
 
+/* Server side of command SERVICE. */
+/* XXX currently this just sends empty reply back */
+
+SILC_SERVER_CMD_FUNC(service)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcUInt32 tmp_len, auth_len;
+  unsigned char *service_name, *auth;
+  bool send_list = FALSE;
+  SilcUInt16 ident = silc_command_get_ident(cmd->payload);
+
+  SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SERVICE, cmd, 0, 256);
+
+  /* Get requested service */
+  service_name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (service_name && tmp_len) {
+    /* Verify service name */
+    if (!silc_identifier_verify(service_name, tmp_len,
+                               SILC_STRING_UTF8, 256)) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_SERVICE,
+                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
+                                           0);
+      goto out;
+    }
+  }
+
+  /* Get authentication payload if present */
+  auth = silc_argument_get_arg_type(cmd->args, 2, &auth_len);
+  if (auth) {
+    /* XXX */
+  }
+
+
+  send_list = TRUE;
+
+  /* Send our service list back */
+  silc_server_send_command_reply(server, cmd->sock, SILC_COMMAND_SERVICE,
+                                SILC_STATUS_OK, 0, ident, 0);
+
+ out:
+  silc_server_command_free(cmd);
+}
+
 
 /* Private range commands, specific to this implementation */
 
index 9cd04d79171152ca71cd5b48637173f51a0dc41a..ba7fd2ce2d9383105a580b9de52890fac712f866 100644 (file)
@@ -4,13 +4,12 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -21,8 +20,8 @@
 #ifndef COMMAND_H
 #define COMMAND_H
 
-/* 
-   Structure holding one command and pointer to its function. 
+/*
+   Structure holding one command and pointer to its function.
 
    SilcCommandCb cb
 
@@ -35,7 +34,7 @@
    SilcCommandFlag flags
 
        Flags for the command. These set how command behaves on different
-       situations. 
+       situations.
 
 */
 typedef struct {
@@ -79,9 +78,9 @@ typedef struct SilcServerCommandPendingStruct {
 { silc_server_command_##func, SILC_COMMAND_##cmd, flags }
 
 /* Macro used to declare command functions. The `context' will be the
-   SilcServerCommandContext and the `context2' is the 
+   SilcServerCommandContext and the `context2' is the
    SilcServerCommandReplyContext if this function is called from the
-   command reply as pending command callback. Otherwise `context2' 
+   command reply as pending command callback. Otherwise `context2'
    is NULL. */
 #define SILC_SERVER_CMD_FUNC(func) \
 void silc_server_command_##func(void *context, void *context2)
@@ -104,7 +103,7 @@ void silc_server_command_process(SilcServer server,
                                 SilcPacketContext *packet);
 SilcServerCommandContext silc_server_command_alloc();
 void silc_server_command_free(SilcServerCommandContext ctx);
-SilcServerCommandContext 
+SilcServerCommandContext
 silc_server_command_dup(SilcServerCommandContext ctx);
 bool silc_server_command_pending(SilcServer server,
                                 SilcCommand reply_cmd,
@@ -122,7 +121,7 @@ void silc_server_command_pending_del(SilcServer server,
                                     SilcUInt16 ident);
 SilcServerCommandPendingCallbacks
 silc_server_command_pending_check(SilcServer server,
-                                 SilcCommand command, 
+                                 SilcCommand command,
                                  SilcUInt16 ident,
                                  SilcUInt32 *callbacks_count);
 SILC_SERVER_CMD_FUNC(whois);
@@ -152,6 +151,7 @@ SILC_SERVER_CMD_FUNC(silcoper);
 SILC_SERVER_CMD_FUNC(leave);
 SILC_SERVER_CMD_FUNC(users);
 SILC_SERVER_CMD_FUNC(getkey);
+SILC_SERVER_CMD_FUNC(service);
 
 SILC_SERVER_CMD_FUNC(connect);
 SILC_SERVER_CMD_FUNC(close);
index 198b7167ef56e7c994c10b8c0a274ed0ab6c5083..506c7f1e79b7094791a0a9e17c834b2bdecf159e 100644 (file)
@@ -1219,7 +1219,7 @@ SILC_SERVER_CMD_REPLY_FUNC(join)
 
   /* Get channel public key list */
   tmp = silc_argument_get_arg_type(cmd->args, 16, &len);
-  if (tmp && server->server_type == SILC_SERVER)
+  if (tmp && server->server_type != SILC_ROUTER)
     silc_server_set_channel_pk_list(server, NULL, entry, tmp, len);
 
   /* The the user limit */
index d758333b066f6fa7490212ea567f139e77a72f3b..c39b95d9976db2c63a3e408572e5d5f559891349 100644 (file)
@@ -1,6 +1,6 @@
 #ifdef SILC_DIST_SERVER
 #
-#  silcd/configure.ad
+#  apps/silcd/configure.ad
 #
 #  Author: Pekka Riikonen <priikone@silcnet.org>
 #
 #  GNU General Public License for more details.
 #
 
+SILCD_SUBDIR=
+
+#ifdef SILC_DIST_TOOLKIT
+if test x$without_silcd = xfalse; then
+#endif SILC_DIST_TOOLKIT
+
+SILCD_SUBDIR=silcd
+
 # Logs directory
 #
 LOGSDIR="$silc_prefix/logs"
@@ -65,16 +73,15 @@ AC_ARG_WITH(silcd-pid-file,
   ])
 AC_SUBST(PIDFILE)
 
-#ifdef SILC_DIST_TOOLKIT
-if test x$without_silcd = xfalse ; then
-#endif SILC_DIST_TOOLKIT
-  AC_CONFIG_FILES(
-silcd/Makefile
+AC_CONFIG_FILES(
+apps/silcd/Makefile
 doc/example_silcd.conf
 )
+
+silcd="yes"
 #ifdef SILC_DIST_TOOLKIT
-fi
+fi     # without_silcd = false
 #endif SILC_DIST_TOOLKIT
 
-silcd="yes"
+AC_SUBST(SILCD_SUBDIR)
 #endif SILC_DIST_SERVER
index fa24ff21e4f1af12ef652e0c7d49d049c7d51a82..86c17cc2a10dc5ca8511d5582a74183cdcf88e5d 100644 (file)
@@ -613,7 +613,7 @@ void silc_server_notify(SilcServer server,
       /* If we received same mode from our primary check whether founder
         mode and key in the notify is set.  We update the founder key
         here since we may have wrong one */
-      if (server->server_type == SILC_SERVER &&
+      if (server->server_type != SILC_ROUTER &&
          sock == SILC_PRIMARY_ROUTE(server) &&
          mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
        SILC_LOG_DEBUG(("Founder public key received from router"));
@@ -811,7 +811,10 @@ void silc_server_notify(SilcServer server,
     /* Process channel public key(s). */
     tmp = silc_argument_get_arg_type(args, 7, &tmp_len);
     if (tmp && mode & SILC_CHANNEL_MODE_CHANNEL_AUTH) {
-      SilcStatus ret =
+      SilcStatus ret;
+      SILC_LOG_DEBUG(("Channel public key list received from router"));
+
+      ret =
        silc_server_set_channel_pk_list(server, sock, channel, tmp, tmp_len);
 
       /* If list was set already we will enforce the same list to server. */
index cf5ddde8a3c2f1cb4a774b270240e9a459597f45..f5a2ffe71fd2d1fcb9d9ac48ca36d3541245f459 100644 (file)
@@ -295,7 +295,7 @@ bool silc_server_init(SilcServer server)
 #ifdef SILC_DEBUG
   /* Set debugging on if configured */
   if (server->config->debug_string) {
-    silc_debug = TRUE;
+    silc_log_debug(TRUE);
     silc_log_set_debug_string(server->config->debug_string);
   }
 #endif /* SILC_DEBUG */
@@ -572,7 +572,7 @@ bool silc_server_rehash(SilcServer server)
   SILC_LOG_INFO(("Rehashing server"));
 
   /* Reset the logging system */
-  silc_log_quick = TRUE;
+  silc_log_quick(TRUE);
   silc_log_flush_all();
 
   /* Start the main rehash phase (read again the config file) */
@@ -764,7 +764,7 @@ bool silc_server_rehash(SilcServer server)
 #ifdef SILC_DEBUG
   /* Set debugging on if configured */
   if (server->config->debug_string) {
-    silc_debug = TRUE;
+    silc_log_debug(TRUE);
     silc_log_set_debug_string(server->config->debug_string);
   }
 #endif /* SILC_DEBUG */
index 55e5f1fc0f0e6e708d08b1c97f4a3faaaf9b7c78..07f5d63d24b468694a8046e1cfe692528404a4b5 100644 (file)
@@ -86,6 +86,7 @@ typedef struct {
 #define SILC_SERVER_QOS_BYTES_LIMIT    2048      /* Default QoS bytes limit */
 #define SILC_SERVER_QOS_LIMIT_SEC      0         /* Default QoS limit sec */
 #define SILC_SERVER_QOS_LIMIT_USEC     500000    /* Default QoS limit usec */
+#define SILC_SERVER_CH_JOIN_LIMIT      50        /* Default join limit */
 
 /* Macros */
 
index f54145da589c2cd00c4601e13bc4d36101bde079..b9b769713e601c1e3849d5a1c93fbe397a1edb5d 100644 (file)
@@ -1543,6 +1543,7 @@ void silc_server_query_send_reply(SilcServer server,
                                         3, nh, strlen(nh));
          sent_reply = TRUE;
        } else {
+         memset(uh, 0, sizeof(uh));
          silc_strncat(uh, sizeof(uh), entry->username,
                       strlen(entry->username));
          if (!strchr(entry->username, '@') && entry->connection) {
@@ -1562,6 +1563,7 @@ void silc_server_query_send_reply(SilcServer server,
        break;
 
       case SILC_COMMAND_WHOWAS:
+       memset(uh, 0, sizeof(uh));
        silc_strncat(uh, sizeof(uh), entry->username, strlen(entry->username));
        if (!strchr(entry->username, '@'))
          silc_strncat(uh, sizeof(uh), "@-private-", 10);
index 1f202168f5e55317be877f49083c5c4e1d1caa16..05197afcf13eeed65a0a360372def2b7bdfbc8c4 100644 (file)
@@ -1893,11 +1893,16 @@ bool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
     tmp = silc_argument_get_first_arg(args, &type, &len);
     while (tmp) {
       if (type == 1) {
-       /* Check validity of the string */
+       /* Check validity of the string.  Actually we should parse the
+          whole string and verify all components individually. */
        if (!silc_utf8_valid(tmp, len) || !len) {
          tmp = silc_argument_get_next_arg(args, &type, &len);
          continue;
        }
+       if (strchr(tmp, ',')) {
+         tmp = silc_argument_get_next_arg(args, &type, &len);
+         continue;
+       }
 
        /* Check if the string is added already */
        silc_hash_table_list(list, &htl);
@@ -1978,11 +1983,16 @@ bool silc_server_inviteban_process(SilcServer server, SilcHashTable list,
     tmp = silc_argument_get_first_arg(args, &type, &len);
     while (tmp) {
       if (type == 1) {
-       /* Check validity of the string */
+       /* Check validity of the string.  Actually we should parse the
+          whole string and verify all components individually. */
        if (!silc_utf8_valid(tmp, len)) {
          tmp = silc_argument_get_next_arg(args, &type, &len);
          continue;
        }
+       if (strchr(tmp, ',')) {
+         tmp = silc_argument_get_next_arg(args, &type, &len);
+         continue;
+       }
 
        /* Delete from the list */
        silc_hash_table_list(list, &htl);
@@ -2097,8 +2107,8 @@ silc_server_process_channel_pk(SilcServer server,
 
   if (type == 0x00) {
     /* Add new public key to channel public key list */
-    SILC_LOG_DEBUG(("Add new channel public key to channel %s",
-                   channel->channel_name));
+    SILC_LOG_DEBUG(("Add new channel public key %s to channel %s",
+                   chpk->identifier, channel->channel_name));
 
     /* Check for resource limit */
     if (silc_hash_table_count(channel->channel_pubkeys) > 64) {
index 545a39ffc91396eeba5d85e8cd2fbdffbbfc9432..2582f6a8d4fdaa56931b10155fb0f87b669549b6 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
-  Copyright (C) 1997 - 2004 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -97,6 +96,7 @@ my_set_param_defaults(SilcServerConfigConnParams *params,
   SET_PARAM_DEFAULT(qos_bytes_limit, SILC_SERVER_QOS_BYTES_LIMIT);
   SET_PARAM_DEFAULT(qos_limit_sec, SILC_SERVER_QOS_LIMIT_SEC);
   SET_PARAM_DEFAULT(qos_limit_usec, SILC_SERVER_QOS_LIMIT_USEC);
+  SET_PARAM_DEFAULT(chlimit, SILC_SERVER_CH_JOIN_LIMIT);
 
 #undef SET_PARAM_DEFAULT
 }
@@ -305,6 +305,9 @@ SILC_CONFIG_CALLBACK(fetch_generic)
   else if (!strcmp(name, "qos_limit_usec")) {
     config->param.qos_limit_usec = *(SilcUInt32 *)val;
   }
+  else if (!strcmp(name, "channel_join_limit")) {
+    config->param.chlimit = *(SilcUInt32 *)val;
+  }
   else if (!strcmp(name, "debug_string")) {
     CONFIG_IS_DOUBLE(config->debug_string);
     config->debug_string = (*(char *)val ? strdup((char *) val) : NULL);
@@ -1168,6 +1171,7 @@ static const SilcConfigTable table_general[] = {
   { "qos_bytes_limit",         SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
   { "qos_limit_sec",           SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
   { "qos_limit_usec",          SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
+  { "channel_join_limit",      SILC_CONFIG_ARG_INT,    fetch_generic,  NULL },
   { "debug_string",                    SILC_CONFIG_ARG_STR,    fetch_generic,  NULL },
   { 0, 0, 0, 0 }
 };
@@ -1915,11 +1919,11 @@ void silc_server_config_setlogfiles(SilcServer server)
 
   SILC_LOG_DEBUG(("Setting configured log file names and options"));
 
-  silc_log_timestamp = config->logging_timestamp;
-  silc_log_quick = config->logging_quick;
-  silc_log_flushdelay = (config->logging_flushdelay ?
-                        config->logging_flushdelay :
-                        SILC_SERVER_LOG_FLUSH_DELAY);
+  silc_log_timestamp(config->logging_timestamp);
+  silc_log_quick(config->logging_quick);
+  silc_log_flushdelay(config->logging_flushdelay ?
+                     config->logging_flushdelay :
+                     SILC_SERVER_LOG_FLUSH_DELAY);
 
   if ((this = config->logging_fatals))
     silc_log_set_file(SILC_LOG_FATAL, this->file, this->maxsize,
index 2104976ed3e87275c5c485ab67a941d792cd930f..cc1ecb21bcd8268309cf3d7c4627bb4736348140 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -94,6 +93,7 @@ typedef struct SilcServerConfigConnParams {
   SilcUInt32 qos_bytes_limit;
   SilcUInt32 qos_limit_sec;
   SilcUInt32 qos_limit_usec;
+  SilcUInt32 chlimit;
   unsigned int key_exchange_pfs      : 1;
   unsigned int reconnect_keep_trying : 1;
   unsigned int anonymous             : 1;
index 10222098a6d152a058fae57afb43ebda638211b4..9c02f13af4b36ca99172b19304e4ac5ae4fff795 100644 (file)
@@ -33,6 +33,7 @@ static SilcServer silcd;
 
 static void silc_usage(void);
 
+#ifdef HAVE_GETOPT_LONG
 /* Long command line options */
 static struct option long_opts[] =
 {
@@ -53,6 +54,7 @@ static struct option long_opts[] =
 
   { NULL, 0, NULL, 0 }
 };
+#endif /* HAVE_GETOPT_LONG */
 
 /* Command line option variables */
 static char *opt_keypath = NULL;
@@ -590,8 +592,12 @@ int main(int argc, char **argv)
 
   /* Parse command line arguments */
   if (argc > 1) {
+#ifdef HAVE_GETOPT_LONG
     while ((opt = getopt_long(argc, argv, "f:p:d:D:xhFVC:",
                              long_opts, &option_index)) != EOF) {
+#else
+    while ((opt = getopt(argc, argv, "f:p:d:D:xhFVC:")) != EOF) {
+#endif /* HAVE_GETOPT_LONG */
       switch(opt) {
        case 'h':
          silc_usage();
@@ -606,11 +612,11 @@ int main(int argc, char **argv)
          break;
        case 'd':
 #ifdef SILC_DEBUG
-         silc_debug = TRUE;
+         silc_log_debug(TRUE);
+         silc_log_quick(TRUE);
          if (optarg)
            silc_log_set_debug_string(optarg);
          foreground = TRUE;        /* implied */
-         silc_log_quick = TRUE;    /* implied */
 #else
          fprintf(stderr,
                  "Run-time debugging is not enabled. To enable it recompile\n"
@@ -619,11 +625,11 @@ int main(int argc, char **argv)
          break;
        case 'D':
 #ifdef SILC_DEBUG
-         silc_debug = TRUE;
+         silc_log_debug(TRUE);
+         silc_log_quick(TRUE);
          if (optarg)
            silc_get_debug_level(atoi(optarg));
          foreground = TRUE;        /* implied */
-         silc_log_quick = TRUE;    /* implied */
 #else
          fprintf(stderr,
                  "Run-time debugging is not enabled. To enable it recompile\n"
@@ -632,10 +638,10 @@ int main(int argc, char **argv)
          break;
        case 'x':
 #ifdef SILC_DEBUG
-         silc_debug_hexdump = TRUE;
-         silc_debug = TRUE; /* implied */
+         silc_log_debug(TRUE);
+         silc_log_debug_hexdump(TRUE);
+         silc_log_quick(TRUE);
          foreground = TRUE; /* implied */
-         silc_log_quick = TRUE; /* implied */
 #else
          fprintf(stderr,
                  "Run-time debugging is not enabled. To enable it recompile\n"
@@ -766,12 +772,9 @@ int main(int argc, char **argv)
       snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
       silc_file_writefile(pidfile, buf, strlen(buf));
     }
-  }
 
-  /* Drop root if we are not in debug mode, so you don't need to bother about
-     file writing permissions and so on */
-  if (!silc_debug)
     silc_server_drop_privs(silcd);
+  }
 
   /* Run the server. When this returns the server has been stopped
      and we will exit. */
diff --git a/apps/silcstress/Makefile.am b/apps/silcstress/Makefile.am
new file mode 100644 (file)
index 0000000..2c2aaa9
--- /dev/null
@@ -0,0 +1,25 @@
+#
+#  Makefile.am
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
+
+bin_PROGRAMS = silcstress
+silcstress_SOURCES = silcstress.c
+
+LIBS = -lsilcclient $(SILC_COMMON_LIBS)
+
+include $(top_srcdir)/Makefile.defines.in
diff --git a/apps/silcstress/configure.ad b/apps/silcstress/configure.ad
new file mode 100644 (file)
index 0000000..4fa59e0
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef SILC_DIST_INPLACE
+#
+#  apps/silcstress/configure.ad
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+#
+# Makefile outputs
+#
+AC_CONFIG_FILES(
+apps/silcstress/Makefile
+)
+#endif SILC_DIST_INPLACE
diff --git a/apps/silcstress/silcstress.c b/apps/silcstress/silcstress.c
new file mode 100644 (file)
index 0000000..874c5b1
--- /dev/null
@@ -0,0 +1,631 @@
+/*
+
+  silcstress.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+
+/*
+  TODO:
+
+  - join to created clients with another client, to get the sent messages
+    as reply (channel message).
+  - create x clients
+
+*/
+
+/*
+  Results:
+
+  SILC Server 0.9.20 (release), Linux 2.6.11, RAM 512 MB:
+
+    - 3000 channels == silcd size 6 MB (-c 3000 -n)
+    - 10000 channels == silcd size 17 MB (-c 10000 -n)
+    - 30000 channels == silcd size 48 MB (-c 30000 -n)
+      (creating 30000 channels take 14 minutes, because JOIN is LAG_STRICT
+       command, which prevents one client flooding server with commands +
+       Qos was enabled too)
+
+
+  SILC Server 0.9.20 (debug, stack-trace), Linux 2.6.11, RAM 512 MB:
+
+    - 3000 channels == silcd size 10 MB (-c 3000 -n)
+    - 10000 channels == silcd size 37 MB (-c 10000 -n)
+
+    - 1 channel, default data flood, QoS == silcd load < 1.0%
+    - 10 channels, default data flood, QoS == silcd load < 4.0%
+    - 100 channels, default data flood, QoS == silcd load < 5.0%
+      (Qos: rate=20, bytes_limit=500B, usec_limit=200000)
+
+*/
+
+#include "silcincludes.h"
+#include "silcclient.h"
+
+typedef struct {
+  SilcClient client;
+  SilcClientConnection conn;
+  int msize;
+  int loops;
+  int flood;
+  int channels;
+  int threads;
+  bool nosend;
+  SilcMutex m;
+} *SilcStress;
+
+typedef struct {
+  SilcStress sc;
+  SilcDList channels;
+} *SilcStressWorker;
+
+SilcClientOperations ops;
+
+/* Long command line options */
+static struct option long_opts[] =
+{
+  { "server", 1, NULL,'s' },
+  { "port", 1, NULL,'p' },
+  { "channels", 1, NULL,'c' },
+  { "msize", 1, NULL,'m' },
+  { "loops", 1, NULL,'l' },
+  { "flood", 1, NULL,'f' },
+  { "nosend", 0, NULL,'n' },
+  { "threads", 1, NULL,'t' },
+  { "debug", 2, NULL, 'd' },
+  { "help", 0, NULL, 'h' },
+  { "version", 0, NULL,'V' },
+
+  { NULL, 0, NULL, 0 }
+};
+
+static void silc_stress_usage(void)
+{
+  printf(""
+"Usage: silcstress [options]\n"
+"\n"
+"  Generic Options:\n"
+"  -s  --server=server           Server to connect\n"
+"  -p  --port=NUMBER             Server port to connect (def: 706)\n"
+"  -c  --channels=NUMBER         Number of channels to create (def: 1)\n"
+"  -m  --msize=NUMBER            Size of message in bytes (def: 512)\n"
+"  -l  --loops=NUMBER            Number of loops to send data (def: 1024)\n"
+"  -f  --flood=NUMBER            Send message in every usec (def: 50000)\n"
+"  -n  --nosend                  Don't send any data\n"
+"  -t  --threads=NUMBER          Number of threads to use (def: 1)\n"
+"  -d  --debug=string            Enable debugging\n"
+"  -h  --help                    Display this message and exit\n"
+"  -V  --version                 Display version and exit\n"
+"\n");
+  exit(0);
+}
+
+int main(int argc, char **argv)
+{
+  int opt, option_index;
+  int c = 1, port = 706, b = 512, l = 1024, f = 50000, n = FALSE, t = 1;
+  char *server = NULL;
+  SilcStress sc;
+
+  if (argc > 1) {
+    while ((opt = getopt_long(argc, argv, "d:hVc:s:p:m:l:f:nt:",
+                             long_opts, &option_index)) != EOF) {
+      switch(opt) {
+       case 'h':
+         silc_stress_usage();
+         break;
+       case 'V':
+         printf("SILC Stress, version %s\n", silc_dist_version);
+         printf("(c) 2005 Pekka Riikonen <priikone@silcnet.org>\n");
+         exit(0);
+         break;
+       case 'd':
+#ifdef SILC_DEBUG
+         silc_log_debug(TRUE);
+         silc_log_debug_hexdump(TRUE);
+         silc_log_quick(TRUE);
+         if (optarg)
+           silc_log_set_debug_string(optarg);
+#else
+         fprintf(stderr,
+                 "Run-time debugging is not enabled. To enable it recompile\n"
+                 "the server with --enable-debug configuration option.\n");
+#endif
+         break;
+       case 'c':
+         c = atoi(optarg);
+         break;
+       case 'l':
+         l = atoi(optarg);
+         break;
+       case 'f':
+         f = atoi(optarg);
+         break;
+       case 'm':
+         b = atoi(optarg);
+         break;
+       case 't':
+         t = atoi(optarg);
+         break;
+       case 'p':
+         port = atoi(optarg);
+         break;
+       case 's':
+         server = strdup(optarg);
+         break;
+       case 'n':
+         n = TRUE;
+         break;
+       default:
+         silc_stress_usage();
+         break;
+      }
+    }
+  }
+
+  if (!server)
+    silc_stress_usage();
+
+  sc = silc_calloc(1, sizeof(*sc));
+  if (!sc)
+    return 1;
+  sc->channels = c;
+  sc->msize = b;
+  sc->loops = l;
+  sc->flood = f;
+  sc->nosend = n;
+  sc->threads = t;
+
+  sc->client = silc_client_alloc(&ops, NULL, sc, NULL);
+  if (!sc->client)
+    return 1;
+
+  sc->client->username = silc_get_username();
+  sc->client->hostname = silc_net_localhost();
+  sc->client->realname = strdup("SILC STRESS");
+
+  if (!silc_client_init(sc->client))
+    return 1;
+
+  if (!silc_load_key_pair("silcstress.pub", "silcstress.prv", "",
+                         &sc->client->pkcs,
+                         &sc->client->public_key,
+                         &sc->client->private_key)) {
+    if (!silc_create_key_pair("rsa", 2048, "silcstress.pub",
+                             "silcstress.prv", NULL, "",
+                             &sc->client->pkcs,
+                             &sc->client->public_key,
+                             &sc->client->private_key, FALSE)) {
+      return 1;
+    }
+  }
+
+  silc_mutex_alloc(&sc->m);
+
+  silc_client_connect_to_server(sc->client, NULL, port, server, sc);
+
+  silc_client_run(sc->client);
+
+  silc_mutex_free(sc->m);
+  silc_client_free(sc->client);
+  silc_free(sc);
+  silc_free(server);
+
+  return 0;
+}
+
+/* Worker thread */
+
+static void *
+silc_stress_worker(void *context)
+{
+  SilcStressWorker w = context;
+  SilcClient client = w->sc->client;
+  SilcClientConnection conn = w->sc->conn;
+  SilcChannelEntry channel;
+  char *tmp;
+  int i;
+
+  tmp = silc_calloc(w->sc->msize, sizeof(*tmp));
+  if (!tmp) {
+    fprintf(stderr, "out of mem\n");
+    silc_dlist_uninit(w->channels);
+    return NULL;
+  }
+
+  memset(tmp, 'M', w->sc->msize);
+
+  for (i = 0; i < w->sc->loops; i++) {
+    silc_dlist_start(w->channels);
+    while ((channel = silc_dlist_get(w->channels)) != SILC_LIST_END) {
+      /* Our packet routines don't like threads, so let's lock :( */
+      silc_mutex_lock(w->sc->m);
+      if (!w->sc->conn) {
+       silc_dlist_uninit(w->channels);
+       return NULL;
+      }
+      silc_client_send_channel_message(client, conn, channel, NULL, 0,
+                                      tmp, w->sc->msize, TRUE);
+      silc_mutex_unlock(w->sc->m);
+    }
+    usleep(w->sc->flood);
+  }
+
+  silc_dlist_uninit(w->channels);
+  silc_free(tmp);
+
+  return NULL;
+}
+
+
+/* "say" client operation is a message from the client library to the
+   application.  It may include error messages or something else.  We
+   just dump them to screen. */
+
+static void
+silc_say(SilcClient client, SilcClientConnection conn,
+        SilcClientMessageType type, char *msg, ...)
+{
+  char str[200];
+  va_list va;
+  va_start(va, msg);
+  vsnprintf(str, sizeof(str) - 1, msg, va);
+  fprintf(stdout, "%s\n", str);
+  va_end(va);
+}
+
+
+/* Message for a channel. The `sender' is the sender of the message
+   The `channel' is the channel. The `message' is the message.  Note
+   that `message' maybe NULL.  The `flags' indicates message flags
+   and it is used to determine how the message can be interpreted
+   (like it may tell the message is multimedia message). */
+
+static void
+silc_channel_message(SilcClient client, SilcClientConnection conn,
+                    SilcClientEntry sender, SilcChannelEntry channel,
+                    SilcMessagePayload payload,
+                    SilcChannelPrivateKey key,
+                    SilcMessageFlags flags, const unsigned char *message,
+                    SilcUInt32 message_len)
+{
+
+}
+
+
+/* Private message to the client. The `sender' is the sender of the
+   message. The message is `message'and maybe NULL.  The `flags'
+   indicates message flags  and it is used to determine how the message
+   can be interpreted (like it may tell the message is multimedia
+   message). */
+
+static void
+silc_private_message(SilcClient client, SilcClientConnection conn,
+                    SilcClientEntry sender, SilcMessagePayload payload,
+                    SilcMessageFlags flags,
+                    const unsigned char *message,
+                    SilcUInt32 message_len)
+{
+}
+
+
+/* Notify message to the client. The notify arguments are sent in the
+   same order as servers sends them. The arguments are same as received
+   from the server except for ID's.  If ID is received application receives
+   the corresponding entry to the ID. For example, if Client ID is received
+   application receives SilcClientEntry.  Also, if the notify type is
+   for channel the channel entry is sent to application (even if server
+   does not send it because client library gets the channel entry from
+   the Channel ID in the packet's header). */
+
+static void
+silc_notify(SilcClient client, SilcClientConnection conn,
+           SilcNotifyType type, ...)
+{
+
+}
+
+
+/* Command handler. This function is called always in the command function.
+   If error occurs it will be called as well. `conn' is the associated
+   client connection. `cmd_context' is the command context that was
+   originally sent to the command. `success' is FALSE if error occurred
+   during command. `command' is the command being processed. It must be
+   noted that this is not reply from server. This is merely called just
+   after application has called the command. Just to tell application
+   that the command really was processed. */
+
+static void
+silc_command(SilcClient client, SilcClientConnection conn,
+            SilcClientCommandContext cmd_context, bool success,
+            SilcCommand command, SilcStatus status)
+{
+  /* If error occurred in client library with our command, print the error */
+  if (status != SILC_STATUS_OK)
+    fprintf(stderr, "COMMAND %s: %s\n",
+           silc_get_command_name(command),
+           silc_get_status_message(status));
+}
+
+
+/* Command reply handler. This function is called always in the command reply
+   function. If error occurs it will be called as well. Normal scenario
+   is that it will be called after the received command data has been parsed
+   and processed. The function is used to pass the received command data to
+   the application.
+
+   `conn' is the associated client connection. `cmd_payload' is the command
+   payload data received from server and it can be ignored. It is provided
+   if the application would like to re-parse the received command data,
+   however, it must be noted that the data is parsed already by the library
+   thus the payload can be ignored. `success' is FALSE if error occurred.
+   In this case arguments are not sent to the application. The `status' is
+   the command reply status server returned. The `command' is the command
+   reply being processed. The function has variable argument list and each
+   command defines the number and type of arguments it passes to the
+   application (on error they are not sent). */
+
+static void
+silc_command_reply(SilcClient client, SilcClientConnection conn,
+                  SilcCommandPayload cmd_payload, bool success,
+                  SilcCommand command, SilcStatus status, ...)
+{
+  SilcStress sc = client->application;
+  va_list va;
+
+  /* If error occurred in client library with our command, print the error */
+  if (status != SILC_STATUS_OK)
+    fprintf(stderr, "COMMAND REPLY %s: %s\n",
+           silc_get_command_name(command),
+           silc_get_status_message(status));
+
+  va_start(va, status);
+
+  /* Check for successful JOIN */
+  if (command == SILC_COMMAND_JOIN && sc->nosend == FALSE &&
+      silc_hash_table_count(conn->local_entry->channels) == sc->channels) {
+    /* Create worker threads for data sending */
+    SilcStressWorker w;
+    SilcHashTableList htl;
+    SilcChannelUser chu;
+    int i, k;
+
+    printf("Creating %d threads (%d channels/thread)\n",
+          sc->threads, silc_hash_table_count(conn->local_entry->channels) /
+          sc->threads);
+
+    silc_hash_table_list(conn->local_entry->channels, &htl);
+    for (i = 0; i < sc->threads; i++) {
+
+      w = silc_calloc(1, sizeof(*w));
+      if (!w) {
+       fprintf(stderr, "out of mem\n");
+       exit(1);
+      }
+
+      w->sc = sc;
+      w->channels = silc_dlist_init();
+      if (!w->channels) {
+       fprintf(stderr, "out of mem\n");
+       exit(1);
+      }
+
+      for (k = 0; k < (silc_hash_table_count(conn->local_entry->channels) /
+                      sc->threads); k++)
+       while (silc_hash_table_get(&htl, NULL, (void *)&chu))
+         silc_dlist_add(w->channels, chu->channel);
+
+      silc_thread_create(silc_stress_worker, w, FALSE);
+    }
+    silc_hash_table_list_reset(&htl);
+  }
+
+  va_end(va);
+}
+
+
+/* Called to indicate that connection was either successfully established
+   or connecting failed.  This is also the first time application receives
+   the SilcClientConnection objecet which it should save somewhere.
+   If the `success' is FALSE the application must always call the function
+   silc_client_close_connection. */
+
+static void
+silc_connected(SilcClient client, SilcClientConnection conn,
+              SilcClientConnectionStatus status)
+{
+  SilcStress sc = client->application;
+  char tmp[16];
+  int i;
+
+  if (status != SILC_CLIENT_CONN_SUCCESS) {
+    fprintf(stderr, "Could not connect to server\n");
+    silc_client_close_connection(client, conn);
+    return;
+  }
+
+  fprintf(stdout, "Connected to server.\n");
+
+  /* Save the connection context */
+  sc->conn = conn;
+
+  /* Join channels */
+  for (i = 0; i < sc->channels; i++) {
+    memset(tmp, 0, sizeof(tmp));
+    snprintf(tmp, sizeof(tmp) - 1, "JOIN %d", i);
+
+    /* Our packet routines don't like threads, so let's lock :( */
+    silc_mutex_lock(sc->m);
+    silc_client_command_call(client, conn, tmp);
+    silc_mutex_unlock(sc->m);
+    usleep(50000);
+  }
+}
+
+
+/* Called to indicate that connection was disconnected to the server.
+   The `status' may tell the reason of the disconnection, and if the
+   `message' is non-NULL it may include the disconnection message
+   received from server. */
+
+static void
+silc_disconnected(SilcClient client, SilcClientConnection conn,
+                 SilcStatus status, const char *message)
+{
+  SilcStress sc = client->application;
+
+  /* We got disconnected from server */
+  sc->conn = NULL;
+  fprintf(stdout, "%s:%s\n", silc_get_status_message(status),
+         message);
+}
+
+
+/* Find authentication method and authentication data by hostname and
+   port. The hostname may be IP address as well. When the authentication
+   method has been resolved the `completion' callback with the found
+   authentication method and authentication data is called. The `conn'
+   may be NULL. */
+
+static void
+silc_get_auth_method(SilcClient client, SilcClientConnection conn,
+                    char *hostname, SilcUInt16 port,
+                    SilcGetAuthMeth completion,
+                    void *context)
+{
+  completion(TRUE, SILC_AUTH_NONE, NULL, 0, context);
+}
+
+
+/* Verifies received public key. The `conn_type' indicates which entity
+   (server, client etc.) has sent the public key. If user decides to trust
+   the application may save the key as trusted public key for later
+   use. The `completion' must be called after the public key has been
+   verified. */
+
+static void
+silc_verify_public_key(SilcClient client, SilcClientConnection conn,
+                      SilcSocketType conn_type, unsigned char *pk,
+                      SilcUInt32 pk_len, SilcSKEPKType pk_type,
+                      SilcVerifyPublicKey completion, void *context)
+{
+  completion(TRUE, context);
+}
+
+
+/* Ask (interact, that is) a passphrase from user. The passphrase is
+   returned to the library by calling the `completion' callback with
+   the `context'. The returned passphrase SHOULD be in UTF-8 encoded,
+   if not then the library will attempt to encode. */
+
+static void
+silc_ask_passphrase(SilcClient client, SilcClientConnection conn,
+                   SilcAskPassphrase completion, void *context)
+{
+  completion(NULL, 0, context);
+}
+
+
+/* Notifies application that failure packet was received.  This is called
+   if there is some protocol active in the client.  The `protocol' is the
+   protocol context.  The `failure' is opaque pointer to the failure
+   indication.  Note, that the `failure' is protocol dependant and
+   application must explicitly cast it to correct type.  Usually `failure'
+   is 32 bit failure type (see protocol specs for all protocol failure
+   types). */
+
+static void
+silc_failure(SilcClient client, SilcClientConnection conn,
+            SilcProtocol protocol, void *failure)
+{
+  fprintf(stderr, "Connecting failed (protocol failure)\n");
+}
+
+
+/* Asks whether the user would like to perform the key agreement protocol.
+   This is called after we have received an key agreement packet or an
+   reply to our key agreement packet. This returns TRUE if the user wants
+   the library to perform the key agreement protocol and FALSE if it is not
+   desired (application may start it later by calling the function
+   silc_client_perform_key_agreement). If TRUE is returned also the
+   `completion' and `context' arguments must be set by the application. */
+
+static bool
+silc_key_agreement(SilcClient client, SilcClientConnection conn,
+                  SilcClientEntry client_entry, const char *hostname,
+                  SilcUInt16 port, SilcKeyAgreementCallback *completion,
+                  void **context)
+{
+  return FALSE;
+}
+
+
+/* Notifies application that file transfer protocol session is being
+   requested by the remote client indicated by the `client_entry' from
+   the `hostname' and `port'. The `session_id' is the file transfer
+   session and it can be used to either accept or reject the file
+   transfer request, by calling the silc_client_file_receive or
+   silc_client_file_close, respectively. */
+
+static void
+silc_ftp(SilcClient client, SilcClientConnection conn,
+        SilcClientEntry client_entry, SilcUInt32 session_id,
+        const char *hostname, SilcUInt16 port)
+{
+
+}
+
+
+/* Delivers SILC session detachment data indicated by `detach_data' to the
+   application.  If application has issued SILC_COMMAND_DETACH command
+   the client session in the SILC network is not quit.  The client remains
+   in the network but is detached.  The detachment data may be used later
+   to resume the session in the SILC Network.  The appliation is
+   responsible of saving the `detach_data', to for example in a file.
+
+   The detachment data can be given as argument to the functions
+   silc_client_connect_to_server, or silc_client_add_connection when
+   creating connection to remote server, inside SilcClientConnectionParams
+   structure.  If it is provided the client library will attempt to resume
+   the session in the network.  After the connection is created
+   successfully, the application is responsible of setting the user
+   interface for user into the same state it was before detaching (showing
+   same channels, channel modes, etc).  It can do this by fetching the
+   information (like joined channels) from the client library. */
+
+static void
+silc_detach(SilcClient client, SilcClientConnection conn,
+           const unsigned char *detach_data, SilcUInt32 detach_data_len)
+{
+
+}
+
+SilcClientOperations ops = {
+  silc_say,
+  silc_channel_message,
+  silc_private_message,
+  silc_notify,
+  silc_command,
+  silc_command_reply,
+  silc_connected,
+  silc_disconnected,
+  silc_get_auth_method,
+  silc_verify_public_key,
+  silc_ask_passphrase,
+  silc_failure,
+  silc_key_agreement,
+  silc_ftp,
+  silc_detach
+};
index c019c6989eaf63f372e45e45c54a250804fb72f3..0182a49af1304f2720cc67d2b01b31732463cb96 100644 (file)
@@ -56,7 +56,9 @@ __SILC_HAVE_SIM=""
 __SILC_ENABLE_DEBUG=""
 
 AC_PROG_RANLIB
+#ifndef SILC_DIST_TOOLKIT
 AC_DISABLE_SHARED
+#endif SILC_DIST_TOOLKIT
 AC_PROG_LIBTOOL
 
 # Header checking
@@ -153,7 +155,7 @@ fi
 #
 AC_CHECK_HEADER(regex.h,
   [
-    AC_DEFINE([HAVE_REGEX], [], [HAVE_REGEX])
+    AC_DEFINE([HAVE_REGEX_H], [], [HAVE_REGEX_H])
     have_regex=1
   ], have_regex=0
 )
@@ -165,7 +167,13 @@ AC_CHECK_FUNC(getopt_long,
     have_getopt_long=1
   ], have_getopt_long=0
 )
-AM_CONDITIONAL(HAVE_GETOPT_LONG, test x$have_getopt_long = x1)
+
+AC_CHECK_FUNC(getopt,
+  [
+    AC_DEFINE([HAVE_GETOPT], [], [HAVE_GETOPT])
+    have_getopt=1
+  ], have_getopt=0
+)
 
 ##
 ##  Enable/disable checking
@@ -282,6 +290,18 @@ AC_DEFUN([SILC_ADD_CFLAGS],
   unset tmp_CFLAGS
 ])
 
+# Function to check if compiler flag works, destination specifiable
+# Usage: SILC_ADD_CC_FLAGS(VAR, FLAGS, [ACTION-IF-FAILED])
+AC_DEFUN([SILC_ADD_CC_FLAGS],
+[ tmp_CFLAGS="$1_CFLAGS"
+  $1_CFLAGS="${$1_CFLAGS} $2"
+  AC_MSG_CHECKING(whether $CC accepts $2 flag)
+  AC_TRY_LINK([], [], [AC_MSG_RESULT(yes)], [AC_MSG_RESULT(no)
+                                      $1_CFLAGS="$tmp_CFLAGS"
+                                      $3])
+  unset tmp_CFLAGS
+])
+
 if test "$GCC"; then
   # GCC specific options
   if test "x$summary_debug" = "xyes"; then
@@ -297,6 +317,9 @@ else
     alpha*-dec-osf*)
       SILC_ADD_CFLAGS(-g3 -O2, SILC_ADD_CFLAGS(-g3 -O, SILC_ADD_CFLAGS(-O)))
       ;;
+    mips*-sgi-irix*)
+      SILC_ADD_CFLAGS(-g3 -O2, SILC_ADD_CFLAGS(-g3 -O, SILC_ADD_CFLAGS(-O)))
+      ;;
     *)
       SILC_ADD_CFLAGS(-g)
       SILC_ADD_CFLAGS(-O2, SILC_ADD_CFLAGS(-O))
@@ -343,11 +366,7 @@ AC_SUBST(FIX_SHA1)
 #ifdef SILC_DIST_AUTODIST
 AC_PREFIX_DEFAULT(/usr/local)
 #else !SILC_DIST_AUTODIST
-#ifdef SILC_DIST_SILCMAP
-AC_PREFIX_DEFAULT(/usr/local)
-#else !SILC_DIST_SILCMAP
 AC_PREFIX_DEFAULT(/usr/local/silc)
-#endif SILC_DIST_SILCMAP
 #endif SILC_DIST_AUTODIST
 if test "x$prefix" != xNONE; then
   silc_prefix="$prefix"
@@ -396,44 +415,6 @@ AC_SUBST(DOCDIR)
 AC_DEFINE_UNQUOTED([SILC_DOCDIR], "$DOCDIR", [SILC_DOCDIR])
 #endif SILC_DIST_AUTODIST
 
-#ifdef SILC_DIST_CLIENT
-# help directory
-#
-HELPDIR="$silc_prefix/help"
-AC_ARG_WITH(helpdir,
-  [[  --with-helpdir=DIR      directory for SILC help files [PREFIX/help]]],
-  [
-    case "$withval" in
-      no|yes)
-        ;;
-      *)
-       HELPDIR="$withval"
-       ;;
-    esac
-  ])
-AC_SUBST(HELPDIR)
-AC_DEFINE_UNQUOTED([SILC_HELPDIR], "$HELPDIR", [SILC_HELPDIR])
-#endif SILC_DIST_CLIENT
-
-#ifdef SILC_DIST_SIM
-# SIM modules directory
-#
-MODULESDIR="$silc_prefix/modules"
-AC_ARG_WITH(simdir,
-  [[  --with-simdir=DIR       directory for SIM modules [PREFIX/modules]]],
-  [
-    case "$withval" in
-      no|yes)
-        ;;
-      *)
-        MODULESDIR="$withval"
-        ;;
-    esac
-  ])
-AC_SUBST(MODULESDIR)
-AC_DEFINE_UNQUOTED([SILC_MODULESDIR], "$MODULESDIR", [SILC_MODULESDIR])
-#endif SILC_DIST_SIM
-
 #ifdef SILC_DIST_COMPILER
 ##
 ##  With/without checkings
@@ -442,9 +423,10 @@ AC_DEFINE_UNQUOTED([SILC_MODULESDIR], "$MODULESDIR", [SILC_MODULESDIR])
 #
 # SILC library checking
 compile_libs=true
+LIBSUBDIR=lib
 
 #ifndef SILC_DIST_TOOLKIT
-AC_ARG_WITH(silc-includes, 
+AC_ARG_WITH(silc-includes,
   [  --with-silc-includes=DIR SILC Toolkit includes [search in DIR]],
   [ac_silc_includes="$withval"], [ac_silc_includes="no"])
 AC_ARG_WITH(silc-libs,
@@ -457,9 +439,11 @@ if test -n "$with_silc_includes" || test -n "$with_silc_libs"; then
   if test "$ac_silc_includes" != "no"; then
     compile_libs=false
     SILC_LIB_INCLUDES="-I$ac_silc_includes"
+    LIBSUBDIR=
   fi
   if test "$ac_silc_libs" != "no"; then
     compile_libs=false
+    LIBSUBDIR=
     LIBS="$LIBS -L$ac_silc_libs"
   fi
 
@@ -477,23 +461,25 @@ if test -n "$with_silc_includes" || test -n "$with_silc_libs"; then
 
 else
   # pkg-config check
-#ifdef SILC_DIST_SILCMAP
-  PKG_CHECK_MODULES(SILC, silc, compile_libs=false)
-  PKG_CHECK_MODULES(SILCCLIENT, silcclient, compile_libs=false)
-#else !SILC_DIST_SILCMAP
   PKG_CHECK_MODULES(SILC, silc, compile_libs=false, compile_libs=true)
+#ifdef SILC_DIST_CLIENTLIB
   PKG_CHECK_MODULES(SILCCLIENT, silcclient, compile_libs=false, compile_libs=true)
-#endif SILC_DIST_SILCMAP
+#endif SILC_DIST_CLIENTLIB
 
   if test x$compile_libs = xfalse; then
+    LIBSUBDIR=
     LIBS="$LIBS $SILC_LIBS"
     CFLAGS="$CFLAGS $SILC_CFLAGS"
+#ifdef SILC_DIST_CLIENTLIB
     LIBS="$LIBS $SILCCLIENT_LIBS"
     CFLAGS="$CFLAGS $SILCCLIENT_CFLAGS"
+#endif SILC_DIST_CLIENTLIB
   fi
 fi
 #endif SILC_DIST_TOOLKIT
 
+AC_SUBST(LIBSUBDIR)
+
 # SOCKS4 support checking
 #
 SAVE_LIBS="$LIBS"
@@ -611,7 +597,7 @@ fi
 
 #ifdef SILC_DIST_MATH
 # MP library checking. First check whether user wants to use GMP and use
-# it if found. If not or not defined then compile the MPI library in the
+# it if found. If not or not defined then compile the default library in the
 # source tree.
 #
 mp_gmp=false
@@ -620,7 +606,7 @@ SAVE_CFLAGS="$CFLAGS"
 SAVE_LDFLAGS="$LDFLAGS"
 AC_MSG_CHECKING(whether to search for GMP)
 AC_ARG_WITH(gmp,
-  [[  --with-gmp[=DIR]        use GMP instead of MPI [search in DIR/lib and DIR/include]]],
+  [[  --with-gmp[=DIR]        use GMP instead of SILC Math [search in DIR/lib and DIR/include]]],
   [
     case "$withval" in
       no)
@@ -656,10 +642,10 @@ AC_ARG_WITH(gmp,
   )
 
 AM_CONDITIONAL(SILC_MP_GMP, test x$mp_gmp = xtrue)
-AM_CONDITIONAL(SILC_MP_NSS_MPI, test x$mp_gmp = xfalse)
+AM_CONDITIONAL(SILC_MP_SILCMATH, test x$mp_gmp = xfalse)
 if test x$mp_gmp = xfalse; then
-  AC_DEFINE([SILC_MP_NSS_MPI], [], [MPI])
-  AC_MSG_RESULT(Using NSS MPI as a MP library.)
+  AC_DEFINE([SILC_MP_SILCMAP], [], [SILCMATH])
+  AC_MSG_RESULT(Using SILC Math as a MP library.)
 fi
 #endif SILC_DIST_MATH
 
@@ -999,43 +985,41 @@ AM_CONDITIONAL(SILC_BEOS, test xfalse = xtrue)
 AM_CONDITIONAL(SILC_OS2, test xfalse = xtrue)
 
 #ifdef SILC_DIST_TOOLKIT
-# --without-irssi
+# --with-irssi
 #
-without_irssi=false
+without_irssi=true
 AC_MSG_CHECKING(whether to compile Irssi SILC Client)
 AC_ARG_WITH(irssi,
-  [  --without-irssi         compile without Irssi SILC Client],
+  [  --with-irssi            compile with Irssi SILC Client],
   [
-    AC_MSG_RESULT(no)
-    without_irssi=true
+    AC_MSG_RESULT(yes)
+    without_irssi=false
   ],
   [
-    AC_MSG_RESULT(yes)
+    AC_MSG_RESULT(no)
+    without_irssi=true
   ])
+AM_CONDITIONAL(with_irssi, test xwithout_irssi = xfalse)
 
-# --without-silcd
+# --with-silcd
 #
-without_silcd=false
+without_silcd=true
 AC_MSG_CHECKING(whether to compile SILC Server)
 AC_ARG_WITH(silcd,
-  [  --without-silcd         compile without SILC Server],
+  [  --with-silcd            compile with SILC Server],
   [
-    AC_MSG_RESULT(no)
-    without_silcd=true
+    AC_MSG_RESULT(yes)
+    without_silcd=false
   ],
   [
-    AC_MSG_RESULT(yes)
+    AC_MSG_RESULT(no)
+    without_silcd=true
   ])
 #endif SILC_DIST_TOOLKIT
-
-#ifdef SILC_DIST_CLIENT
-# Irssi perl support
-#
-AC_ARG_WITH(perl,
-  [[  --with-perl[=yes|no|module]  Build with Perl support - also specifies
-                               if it should be built into main silc binary
-                               (static, default) or as a module]])
-#endif SILC_DIST_CLIENT
+#ifdef SILC_DIST_INPLACE
+without_irssi=false
+without_silcd=false
+#endif SILC_DIST_INPLACE
 
 libtoolfix=true
 AC_MSG_CHECKING(whether to do libtoolfix)
@@ -1051,7 +1035,6 @@ AC_ARG_WITH(libtoolfix,
 
 AC_SUBST(ETCDIR)
 AC_DEFINE_UNQUOTED([SILC_ETCDIR], "$ETCDIR", [SILC_ETCDIR])
-
 #endif SILC_DIST_COMPILER
 
 ##
@@ -1061,20 +1044,6 @@ AC_DEFINE_UNQUOTED([SILC_ETCDIR], "$ETCDIR", [SILC_ETCDIR])
 # Make enable-shared aware
 AM_CONDITIONAL(SILC_ENABLE_SHARED, test "$enable_shared" = yes)
 
-# Other configure scripts
-#
-
-#ifdef SILC_DIST_TOOLKIT
-if test x$without_irssi = xfalse; then
-#endif SILC_DIST_TOOLKIT
-#ifdef SILC_DIST_CLIENT
-  AC_CONFIG_SUBDIRS(irssi)
-  irssi="yes"
-#endif SILC_DIST_CLIENT
-#ifdef SILC_DIST_TOOLKIT
-fi
-#endif SILC_DIST_TOOLKIT
-
 SILC_TOP_SRCDIR=`pwd`
 
 # Included configure scripts
@@ -1126,22 +1095,8 @@ apps/Makefile
 #endif SILC_DIST_APPS
 )
 
-#ifdef SILC_DIST_TOOLKIT
-if test x$without_irssi = xfalse ; then
-#endif SILC_DIST_TOOLKIT
-#ifdef SILC_DIST_CLIENT
-  AC_CONFIG_FILES(
-irssi/Makefile.defines
-irssi/Makefile.defines_int
-)
-#endif SILC_DIST_CLIENT
-#ifdef SILC_DIST_TOOLKIT
-fi
-#endif SILC_DIST_TOOLKIT
-
 #ifdef SILC_DIST_TOOLKIT
 AC_CONFIG_FILES(
-silc/Makefile
 win32/Makefile
 win32/libsilc/Makefile
 win32/libsilcclient/Makefile
@@ -1173,15 +1128,7 @@ echo " bin directory .................: $s_bindir"
 echo " sbin directory ................: $s_sbindir"
 echo " etc directory .................: $ETCDIR"
 echo " man directory .................: $s_mandir"
-#ifdef SILC_DIST_DOC
 echo " doc directory .................: $DOCDIR"
-#endif SILC_DIST_DOC
-#ifdef SILC_DIST_CLIENT
-echo " help directory ................: $HELPDIR"
-#endif SILC_DIST_CLIENT
-#ifdef SILC_DIST_SERVER
-echo " logs directory ................: $LOGSDIR"
-#endif SILC_DIST_SERVER
 #ifdef SILC_DIST_SIM
 echo " SIM directory .................: $MODULESDIR"
 #endif SILC_DIST_SIM
@@ -1205,8 +1152,6 @@ echo " Compile SILC Client ...........: $irssi"
 
 #ifdef SILC_DIST_SERVER
 echo " Compile SILC Server ...........: $silcd"
-echo " Server configuration file .....: $summary_silcd_configfile"
-echo " Server PID file ...............: $PIDFILE"
 #endif SILC_DIST_SERVER
 
 #ifdef SILC_DIST_SIM
@@ -1235,11 +1180,9 @@ fi
 echo " Assembler optimizations .......: $summary_asm"
 
 #ifdef SILC_DIST_MATH
-mp="MPI"
 if test x$mp_gmp = xtrue; then
-  mp="GMP"
+  echo " Arithmetic library ............: GMP"
 fi
-echo " Arithmetic library ............: $mp"
 #endif SILC_DIST_MATH
 
 threads="no"
@@ -1251,4 +1194,3 @@ echo " Debugging enabled .............: $summary_debug"
 echo ""
 echo "Compile the sources with 'make' or 'gmake' command."
 #endif SILC_DIST_COMPILER
-
diff --git a/distdir/TOOLKIT b/distdir/TOOLKIT
new file mode 100644 (file)
index 0000000..d99d8f3
--- /dev/null
@@ -0,0 +1,25 @@
+The SILC Toolkit distribution is dual-licensed distribution.  The 
+following licenses govern this distribution, and you are free to choose 
+either one of the licenses:
+
+ - GNU General Public License, Version 2       (see file GPL)
+ - Revised BSD License                         (see file BSD)
+
+Choose GNU GPL if your application is also GNU GPL or other similar 
+compatible Open Source licensed application.
+
+Choose Revised BSD license if your application is also BSD licensed or 
+commercial application.
+
+NOTE: The files under the subdirectory apps/ are only GNU GPL licensed 
+example application code.  They are not compiled by default in SILC 
+Toolkit, and not delivered into the any compiled binary or library.  They 
+are not dual-licensed code.
+
+Always verify the license from the file you are using.
+
+All code that is included in the compiled libraries (*) are dual-licensed
+and you may freely choose the license you wish to use from the above list.
+
+(*) lib/silcutil/silcconfig.c and lib/silcutil/silcconfig.h files are only 
+    GNU GPL licensed.  They are not dual licensed.
diff --git a/distdir/TOOLKIT-header b/distdir/TOOLKIT-header
new file mode 100644 (file)
index 0000000..e8625e8
--- /dev/null
@@ -0,0 +1,8 @@
+  The contents of this file are subject to one of the Licenses specified 
+  in the COPYING file;  You may not use this file except in compliance 
+  with the License.
+
+  The software distributed under the License is distributed on an "AS IS"
+  basis, in the hope that it will be useful, but WITHOUT WARRANTY OF ANY
+  KIND, either expressed or implied.  See the COPYING file for more
+  information.
index 3fa00057ccecac8f6ebda94a53aea0eb921c7722..af1cfad2847c700cf9429dbca67196b64261ff4d 100644 (file)
@@ -1,11 +1,15 @@
 # Common SILC source tree distdefs
 option template
 define SILC_DIST_SILC
+define SILC_DIST_APPS
 define SILC_DIST_LIB
 define SILC_DIST_INCLUDES
 define SILC_DIST_DOC
 define SILC_DIST_SIM
-define SILC_DIST_MPI
-define SILC_DIST_MATH
 define SILC_DIST_SFTP
 define SILC_DIST_COMPILER
+
+# Math library, define only TMA or TFM, not both.
+define SILC_DIST_MATH
+define SILC_DIST_TMA
+#define SILC_DIST_TFM
index a000fd977bb06380a16f3a78843f976f8b25cfd1..9c3a9060884bb9a6417e5c83191872d5faefb3ba 100644 (file)
@@ -12,5 +12,10 @@ inherit common
 inherit client
 inherit server
 inherit toolkit
+
 define SILC_DIST_INPLACE
+
+# SFTP is undefined in server, so force it here
+define SILC_DIST_SFTP
+
 pre-hook distdir/pre-run
index f6e4f38e5c253c7813ddfe81e00e46e63cf9da8e..375b98633b57e5e0149ebcd72abcb216f18f3da6 100644 (file)
@@ -10,4 +10,5 @@ distdir=$4
 
 if test -d $distdir; then
   rm -rf `find $distdir -name CVS`
+  rm -rf `find $distdir -name Makefile`
 fi
diff --git a/distdir/pre-dist-toolkit b/distdir/pre-dist-toolkit
new file mode 100644 (file)
index 0000000..8f2f17a
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+distribution=$1
+dist_version=$2
+package=$3
+distdir=$4
+
+./configure --with-irssi --with-silcd
+
+cd doc
+make dist-hook
+rm -rf toolkit
+make toolkit-ref-html
+cp ../lib/doc/*.gif toolkit
+cd ..
+
index cc716ca107c32821b8f234549aca6305f16540b8..7b9df250fab52f5495ab20380cb02a96779b4fae 100644 (file)
@@ -6,13 +6,14 @@ package=$3
 
 # preparing irssi
 echo "Preparing irssi"
-file=irssi/irssi-version.h.in
+cur=`pwd`
+file=apps/irssi/irssi-version.h.in
 touch $file
-cd irssi
-ln -fs ../Makefile.defines.in Makefile.defines.in
-ln -fs ../Makefile.defines_int.in Makefile.defines_int.in
+cd apps/irssi
+ln -fs ../../Makefile.defines.in Makefile.defines.in
+ln -fs ../../Makefile.defines_int.in Makefile.defines_int.in
 sh autogen.sh 2>/dev/null 1>/dev/null
-cd ..
+cd $cur
 version_date=`date +%Y%m%d`
 echo "/* automatically created by autogen.sh */" > $file
 echo "#define IRSSI_VERSION \"$dist_version (Irssi base: @VERSION@ - SILC base: SILC $dist_version)\"" >>$file
index de5af055a80a802e9e51450a4cc02cb313d71444..bb062bd210f0633249209364c876d73ac6573562 100644 (file)
@@ -2,17 +2,39 @@ name Toolkit
 package silc-toolkit
 bug-report silc-devel@lists.silcnet.org
 
+# Inherits
 inherit common
 inherit client
 inherit server
+
+# License
+license distdir/TOOLKIT
+include distdir/GPL GPL
+include distdir/BSD BSD
+license-header distdir/GPL-header distdir/TOOLKIT-header
+
+# Distdefs
 define SILC_DIST_TOOLKIT
+# SFTP is undefined in server, so force it here
+define SILC_DIST_SFTP
 
+# Includes
 include README.CVS
 include README.WIN32
 include README.MACOSX
-include silcer
+include apps/silcer
+include apps/silc
 include tutorial
 
+# Noprocess to optimize packaging and avoid re-licensing of certain files
+noprocess COPYING GPL BSD
+noprocess doc/toolkit/
+noprocess apps/
+noprocess win32/
+noprocess lib/silcutil/silcconfig.[ch]
+
 pre-hook distdir/pre-run
 post-process-dist-hook distdir/post-process-dist
+pre-dist-hook distdir/pre-dist-toolkit
 post-dist-hook distdir/post-dist
+
index 85e313cdde1887192466bfb01c1a91c24951cc23..f5926593553c7199241d5bb1445aa9be1a8ae10d 100644 (file)
@@ -51,7 +51,6 @@ toolkit-ref-pdf:
         fi
 
 dist-hook:
-       rm -rf `find $(top_distdir)/doc -name CVS`
        $(SILC_TOP_SRCDIR)/scripts/manpages.pl
        touch draft-riikonen-silc-spec-08.txt
        touch draft-riikonen-silc-pp-09.txt
@@ -84,6 +83,25 @@ dist-hook:
        touch draft-riikonen-presence-attrs-03.txt
 #endif SILC_DIST_TOOLKIT
 
+doc-install:
+       -mkdir -p $(docdir)
+#ifdef SILC_DIST_TOOLKIT
+       -$(INSTALL_DATA) $(top_srcdir)/doc/CodingStyle $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/GPL $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/BSD $(docdir)/
+#endif SILC_DIST_TOOLKIT
+       -$(INSTALL_DATA) $(top_srcdir)/doc/FAQ $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/doc/*.txt $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/COPYING $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/CHANGES $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/CREDITS $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/README* $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/INSTALL $(docdir)/
+       -$(INSTALL_DATA) $(top_srcdir)/TODO $(docdir)/
+
+install-data-hook:     \
+       doc-install
+
 EXTRA_DIST =                   \
 #ifdef SILC_DIST_CLIENT
        silc.1                  \
@@ -99,3 +117,5 @@ EXTRA_DIST =                         \
        example_silcd.conf      \
        silcalgs.conf           \
        draft-riikonen*.txt
+
+include $(top_srcdir)/Makefile.defines.in
index a5312e248b649a028d973b4118b1e2403db5a3eb..9820b2ba60540377dce226c570e07c12853e3c36 100644 (file)
@@ -159,6 +159,9 @@ General {
        #qos_limit_sec = 0;
        #qos_limit_usec = 500000;
 
+       # Limit on how many channels one client can join.  Default is 50.
+       #channel_join_limit = 100;
+
        # Debug string.  Debug string can be set to print debugging from
        # the running server.  The debug is redirected to stderr.
        # debug_string = "";
index 23e8f340e8b10e4f80bc1c0677226d9854466a15..50f98475e774d7534e0d2a0e424410d9ad9b3508 100644 (file)
@@ -143,8 +143,12 @@ extern "C" {
 #include <grp.h>
 #include <sys/times.h>
 
-#ifdef HAVE_GETOPT_H
+#if defined(HAVE_GETOPT_H) && defined(HAVE_GETOPT)
 #include <getopt.h>
+#else
+#if defined(HAVE_SILCDEFS_H)
+#include "getopti.h"
+#endif /* HAVE_SILCDEFS_H */
 #endif
 
 #ifdef SOCKS5
@@ -185,7 +189,9 @@ extern "C" {
 #endif
 
 #ifndef HAVE_REGEX_H
-#include "regex.h"
+#if defined(HAVE_SILCDEFS_H)
+#include "regexpr.h"
+#endif /* HAVE_SILCDEFS_H */
 #else
 #include <regex.h>
 #endif
@@ -224,10 +230,6 @@ extern "C" {
 
 #endif                         /* !SILC_WIN32 */
 
-#ifndef HAVE_GETOPT_LONG
-#include "getopt.h"
-#endif
-
 /* Include generic SILC type definitions */
 #include "silctypes.h"
 #include "silcversion.h"
index 92eb37e33d993c2f816a7d6d9f7eca526899c20c..cd9420096305bd015d22e29fbb26b2f0281cf29f 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001, 2003 Pekka Riikonen
+  Copyright (C) 2001 - 2003 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index c662a01b2e17cf696eaa124b0e85c3c54c533d48..4e1d1ca1d7112ee57dea2a52f4d6e652a89c0be7 100644 (file)
@@ -111,3 +111,17 @@ pkgconfig_DATA = silc.pc silcclient.pc
 EXTRA_DIST = silc.pc.in silcclient.pc.in
 #endif SILC_DIST_TOOLKIT
 
+#ifdef SILC_DIST_TOOLKIT
+toolkit-install:
+       -mkdir -p $(docdir)/toolkit/
+       -$(INSTALL_DATA) $(top_srcdir)/doc/toolkit/* $(docdir)/toolkit
+       -$(INSTALL_DATA) $(top_srcdir)/lib/doc/*.gif $(docdir)/toolkit
+       -cp -R $(top_srcdir)/tutorial $(docdir)
+#endif SILC_DIST_TOOLKIT
+
+install-data-hook:     \
+#ifdef SILC_DIST_TOOLKIT
+       toolkit-install
+#endif SILC_DIST_TOOLKIT
+
+include $(top_srcdir)/Makefile.defines.in
index ff9e2a3c99acf4d1da9d4a8d7f7fd8112e01808e..a0383356484c67fb7ab8095dd555cf997cafa7e0 100644 (file)
@@ -29,9 +29,6 @@ SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silccore"
 SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silccrypt"
 #ifdef SILC_DIST_MATH
 SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcmath"
-#ifdef SILC_DIST_MPI
-SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcmath/mpi"
-#endif SILC_DIST_MPI
 #endif SILC_DIST_MATH
 SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcutil"
 SILC_LIB_INCLUDES="$SILC_LIB_INCLUDES -I$SILC_TOP_SRCDIR/lib/silcske"
@@ -86,6 +83,25 @@ AC_SUBST(LIBSILCCLIENT_CURRENT)
 AC_SUBST(LIBSILCCLIENT_REVISION)
 AC_SUBST(LIBSILCCLIENT_AGE)
 
+#ifdef SILC_DIST_SIM
+# SIM modules directory
+#
+MODULESDIR="$silc_prefix/modules"
+AC_ARG_WITH(simdir,
+  [[  --with-simdir=DIR       directory for SIM modules [PREFIX/modules]]],
+  [
+    case "$withval" in
+      no|yes)
+        ;;
+      *)
+        MODULESDIR="$withval"
+        ;;
+    esac
+  ])
+AC_SUBST(MODULESDIR)
+AC_DEFINE_UNQUOTED([SILC_MODULESDIR], "$MODULESDIR", [SILC_MODULESDIR])
+#endif SILC_DIST_SIM
+
 #ifdef SILC_DIST_TOOLKIT
 # Stack trace checking
 #
@@ -125,9 +141,6 @@ lib/silcutil/win32/Makefile
 lib/silcutil/beos/Makefile
 lib/silcutil/os2/Makefile
 lib/silcutil/epoc/Makefile
-#ifdef SILC_DIST_MATH
-lib/silcmath/Makefile
-#endif SILC_DIST_MATH
 #ifdef SILC_DIST_SFTP
 lib/silcsftp/Makefile
 #endif SILC_DIST_SFTP
similarity index 72%
rename from lib/contrib/Makefile.am
rename to lib/contrib/Makefile.ad
index 74faaf72f5c3c2496684e4d6f0337fa34ea2aab5..60055fd12d60d2400105d34a0d18fbf549fadb6c 100644 (file)
@@ -19,25 +19,33 @@ AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
 noinst_LTLIBRARIES = libcontrib.la
 
-if HAVE_GETOPT_LONG
-GETOPT =
-else
-GETOPT = getopt.c getopt1.c
-endif
-
 if HAVE_REGEX
 REGEX =
 else
-REGEX = regex.c
+REGEX = regexpr.c
 endif
 
 STRINGPREP = nfkc.c rfc3454.c stringprep.c
 
 if SILC_WIN32
-libcontrib_la_SOURCES = $(STRINGPREP)
+libcontrib_la_SOURCES = getopti.c $(STRINGPREP)
+else
+libcontrib_la_SOURCES = getopti.c $(STRINGPREP) $(REGEX)
+endif
+
+#ifdef SILC_DIST_TOOLKIT
+if HAVE_REGEX
+REGEXH =
 else
-libcontrib_la_SOURCES = $(STRINGPREP) $(GETOPT) $(REGEX)
+REGEXH = regexpr.h
 endif
+include_HEADERS =       \
+       $(REGEXH)       \
+       getopti.h       \
+       gunicomp.h      \
+       gunidecomp.h    \
+       stringprep.h
+#endif SILC_DIST_TOOLKIT
 
 EXTRA_DIST = *.c *.h
 
diff --git a/lib/contrib/getopt.c b/lib/contrib/getopt.c
deleted file mode 100644 (file)
index 0b47ea7..0000000
+++ /dev/null
@@ -1,748 +0,0 @@
-/* Getopt for GNU.
-   NOTE: getopt is now part of the C library, so if you don't know what
-   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
-   before changing it!
-
-   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
-       Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-\f
-
-#ifndef __STDC__
-/* This is a separate conditional since some stdc systems
-   reject `defined (const)'.  */
-#ifndef const
-#define const
-#endif
-#endif
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.  */
-#ifndef _NO_PROTO
-#define _NO_PROTO
-#endif
-
-#include <stdio.h>
-#include <string.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
-
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-
-
-/* This needs to come after some library #include
-   to get __GNU_LIBRARY__ defined.  */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
-   contain conflicting prototypes for getopt.  */
-#include <stdlib.h>
-#endif /* GNU C library.  */
-
-/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
-   long-named option.  Because this is not POSIX.2 compliant, it is
-   being phased out.  */
-/* #define GETOPT_COMPAT */
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
-   but it behaves differently for the user, since it allows the user
-   to intersperse the options with the other arguments.
-
-   As `getopt' works, it permutes the elements of ARGV so that,
-   when it is done, all the options precede everything else.  Thus
-   all application programs are extended to handle flexible argument order.
-
-   Setting the environment variable POSIXLY_CORRECT disables permutation.
-   Then the behavior is completely standard.
-
-   GNU application programs can use a third alternative mode in which
-   they can distinguish the relative order of options and other arguments.  */
-
-#include "getopt.h"
-
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
-
-char *optarg = 0;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
-
-   On entry to `getopt', zero means this is the first call; initialize.
-
-   When `getopt' returns EOF, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, `optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-/* XXX 1003.2 says this must be 1 before any call.  */
-int optind = 0;
-
-/* The next char to be scanned in the option-element
-   in which the last option character we returned was found.
-   This allows us to pick up the scan where we left off.
-
-   If this is zero, or a null string, it means resume the scan
-   by advancing to the next ARGV-element.  */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
-   for unrecognized options.  */
-
-int opterr = 1;
-
-/* Set to an option character which was unrecognized.
-   This must be initialized on some systems to avoid linking in the
-   system's own getopt implementation.  */
-
-int optopt = '?';
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
-   If the caller did not specify anything,
-   the default is REQUIRE_ORDER if the environment variable
-   POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
-   REQUIRE_ORDER means don't recognize them as options;
-   stop option processing when the first non-option is seen.
-   This is what Unix does.
-   This mode of operation is selected by either setting the environment
-   variable POSIXLY_CORRECT, or using `+' as the first character
-   of the list of option characters.
-
-   PERMUTE is the default.  We permute the contents of ARGV as we scan,
-   so that eventually all the non-options are at the end.  This allows options
-   to be given in any order, even with programs that were not written to
-   expect this.
-
-   RETURN_IN_ORDER is an option available to programs that were written
-   to expect options and other ARGV-elements in any order and that care about
-   the ordering of the two.  We describe each non-option ARGV-element
-   as if it were the argument of an option with character code 1.
-   Using `-' as the first character of the list of option characters
-   selects this mode of operation.
-
-   The special argument `--' forces an end of option-scanning regardless
-   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
-   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
-
-static enum
-{
-  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-\f
-#ifdef __GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
-   because there are many ways it can cause trouble.
-   On some systems, it contains special magic macros that don't work
-   in GCC.  */
-#include <string.h>
-#define        my_index        strchr
-#else
-
-/* Avoid depending on library functions or files
-   whose names are inconsistent.  */
-
-char *getenv ();
-
-static char *
-my_index (str, chr)
-     const char *str;
-     int chr;
-{
-  while (*str)
-    {
-      if (*str == chr)
-       return (char *) str;
-      str++;
-    }
-  return 0;
-}
-
-/* If using GCC, we can safely declare strlen this way.
-   If not using GCC, it is ok not to declare it.
-   (Supposedly there are some machines where it might get a warning,
-   but changing this conditional to __STDC__ is too risky.)  */
-#ifdef __GNUC__
-#ifdef IN_GCC
-#include "gstddef.h"
-#else
-#include <stddef.h>
-#endif
-extern size_t strlen (const char *);
-#endif
-
-#endif                         /* GNU C library.  */
-\f
-/* Handle permutation of arguments.  */
-
-/* Describe the part of ARGV that contains non-options that have
-   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
-   `last_nonopt' is the index after the last of them.  */
-
-static int first_nonopt;
-static int last_nonopt;
-
-/* Exchange two adjacent subsequences of ARGV.
-   One subsequence is elements [first_nonopt,last_nonopt)
-   which contains all the non-options that have been skipped so far.
-   The other is elements [last_nonopt,optind), which contains all
-   the options processed since those non-options were skipped.
-
-   `first_nonopt' and `last_nonopt' are relocated so that they describe
-   the new indices of the non-options in ARGV after they are moved.  */
-
-static void
-exchange (argv)
-     char **argv;
-{
-  int bottom = first_nonopt;
-  int middle = last_nonopt;
-  int top = optind;
-  char *tem;
-
-  /* Exchange the shorter segment with the far end of the longer segment.
-     That puts the shorter segment into the right place.
-     It leaves the longer segment in the right place overall,
-     but it consists of two parts that need to be swapped next.  */
-
-  while (top > middle && middle > bottom)
-    {
-      if (top - middle > middle - bottom)
-       {
-         /* Bottom segment is the short one.  */
-         int len = middle - bottom;
-         register int i;
-
-         /* Swap it with the top part of the top segment.  */
-         for (i = 0; i < len; i++)
-           {
-             tem = argv[bottom + i];
-             argv[bottom + i] = argv[top - (middle - bottom) + i];
-             argv[top - (middle - bottom) + i] = tem;
-           }
-         /* Exclude the moved bottom segment from further swapping.  */
-         top -= len;
-       }
-      else
-       {
-         /* Top segment is the short one.  */
-         int len = top - middle;
-         register int i;
-
-         /* Swap it with the bottom part of the bottom segment.  */
-         for (i = 0; i < len; i++)
-           {
-             tem = argv[bottom + i];
-             argv[bottom + i] = argv[middle + i];
-             argv[middle + i] = tem;
-           }
-         /* Exclude the moved top segment from further swapping.  */
-         bottom += len;
-       }
-    }
-
-  /* Update records for the slots the non-options now occupy.  */
-
-  first_nonopt += (optind - last_nonopt);
-  last_nonopt = optind;
-}
-\f
-/* Scan elements of ARGV (whose length is ARGC) for option characters
-   given in OPTSTRING.
-
-   If an element of ARGV starts with '-', and is not exactly "-" or "--",
-   then it is an option element.  The characters of this element
-   (aside from the initial '-') are option characters.  If `getopt'
-   is called repeatedly, it returns successively each of the option characters
-   from each of the option elements.
-
-   If `getopt' finds another option character, it returns that character,
-   updating `optind' and `nextchar' so that the next call to `getopt' can
-   resume the scan with the following option character or ARGV-element.
-
-   If there are no more option characters, `getopt' returns `EOF'.
-   Then `optind' is the index in ARGV of the first ARGV-element
-   that is not an option.  (The ARGV-elements have been permuted
-   so that those that are not options now come last.)
-
-   OPTSTRING is a string containing the legitimate option characters.
-   If an option character is seen that is not listed in OPTSTRING,
-   return '?' after printing an error message.  If you set `opterr' to
-   zero, the error message is suppressed but we still return '?'.
-
-   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
-   so the following text in the same ARGV-element, or the text of the following
-   ARGV-element, is returned in `optarg'.  Two colons mean an option that
-   wants an optional arg; if there is text in the current ARGV-element,
-   it is returned in `optarg', otherwise `optarg' is set to zero.
-
-   If OPTSTRING starts with `-' or `+', it requests different methods of
-   handling the non-option ARGV-elements.
-   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
-   Long-named options begin with `--' instead of `-'.
-   Their names may be abbreviated as long as the abbreviation is unique
-   or is an exact match for some defined option.  If they have an
-   argument, it follows the option name in the same ARGV-element, separated
-   from the option name by a `=', or else the in next ARGV-element.
-   When `getopt' finds a long-named option, it returns 0 if that option's
-   `flag' field is nonzero, the value of the option's `val' field
-   if the `flag' field is zero.
-
-   The elements of ARGV aren't really const, because we permute them.
-   But we pretend they're const in the prototype to be compatible
-   with other systems.
-
-   LONGOPTS is a vector of `struct option' terminated by an
-   element containing a name which is zero.
-
-   LONGIND returns the index in LONGOPT of the long-named option found.
-   It is only valid when a long-named option has been found by the most
-   recent call.
-
-   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
-   long-named options.  */
-
-int
-_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
-     int argc;
-     char *const *argv;
-     const char *optstring;
-     const struct option *longopts;
-     int *longind;
-     int long_only;
-{
-  int option_index;
-
-  optarg = 0;
-
-  /* Initialize the internal data when the first call is made.
-     Start processing options with ARGV-element 1 (since ARGV-element 0
-     is the program name); the sequence of previously skipped
-     non-option ARGV-elements is empty.  */
-
-  if (optind == 0)
-    {
-      first_nonopt = last_nonopt = optind = 1;
-
-      nextchar = NULL;
-
-      /* Determine how to handle the ordering of options and nonoptions.  */
-
-      if (optstring[0] == '-')
-       {
-         ordering = RETURN_IN_ORDER;
-         ++optstring;
-       }
-      else if (optstring[0] == '+')
-       {
-         ordering = REQUIRE_ORDER;
-         ++optstring;
-       }
-      else if (getenv ("POSIXLY_CORRECT") != NULL)
-       ordering = REQUIRE_ORDER;
-      else
-       ordering = PERMUTE;
-    }
-
-  if (nextchar == NULL || *nextchar == '\0')
-    {
-      if (ordering == PERMUTE)
-       {
-         /* If we have just processed some options following some non-options,
-            exchange them so that the options come first.  */
-
-         if (first_nonopt != last_nonopt && last_nonopt != optind)
-           exchange ((char **) argv);
-         else if (last_nonopt != optind)
-           first_nonopt = optind;
-
-         /* Now skip any additional non-options
-            and extend the range of non-options previously skipped.  */
-
-         while (optind < argc
-                && (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
-                && (longopts == NULL
-                    || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif                         /* GETOPT_COMPAT */
-                )
-           optind++;
-         last_nonopt = optind;
-       }
-
-      /* Special ARGV-element `--' means premature end of options.
-        Skip it like a null option,
-        then exchange with previous non-options as if it were an option,
-        then skip everything else like a non-option.  */
-
-      if (optind != argc && !strcmp (argv[optind], "--"))
-       {
-         optind++;
-
-         if (first_nonopt != last_nonopt && last_nonopt != optind)
-           exchange ((char **) argv);
-         else if (first_nonopt == last_nonopt)
-           first_nonopt = optind;
-         last_nonopt = argc;
-
-         optind = argc;
-       }
-
-      /* If we have done all the ARGV-elements, stop the scan
-        and back over any non-options that we skipped and permuted.  */
-
-      if (optind == argc)
-       {
-         /* Set the next-arg-index to point at the non-options
-            that we previously skipped, so the caller will digest them.  */
-         if (first_nonopt != last_nonopt)
-           optind = first_nonopt;
-         return EOF;
-       }
-
-      /* If we have come to a non-option and did not permute it,
-        either stop the scan or describe it to the caller and pass it by.  */
-
-      if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
-         && (longopts == NULL
-             || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif                         /* GETOPT_COMPAT */
-         )
-       {
-         if (ordering == REQUIRE_ORDER)
-           return EOF;
-         optarg = argv[optind++];
-         return 1;
-       }
-
-      /* We have found another option-ARGV-element.
-        Start decoding its characters.  */
-
-      nextchar = (argv[optind] + 1
-                 + (longopts != NULL && argv[optind][1] == '-'));
-    }
-
-  if (longopts != NULL
-      && ((argv[optind][0] == '-'
-          && (argv[optind][1] == '-' || long_only))
-#ifdef GETOPT_COMPAT
-         || argv[optind][0] == '+'
-#endif                         /* GETOPT_COMPAT */
-         ))
-    {
-      const struct option *p;
-      char *s = nextchar;
-      int exact = 0;
-      int ambig = 0;
-      const struct option *pfound = NULL;
-      int indfound = 0;
-
-      while (*s && *s != '=')
-       s++;
-
-      /* Test all options for either exact match or abbreviated matches.  */
-      for (p = longopts, option_index = 0; p->name;
-          p++, option_index++)
-       if (!strncmp (p->name, nextchar, s - nextchar))
-         {
-           if (s - nextchar == strlen (p->name))
-             {
-               /* Exact match found.  */
-               pfound = p;
-               indfound = option_index;
-               exact = 1;
-               break;
-             }
-           else if (pfound == NULL)
-             {
-               /* First nonexact match found.  */
-               pfound = p;
-               indfound = option_index;
-             }
-           else
-             /* Second nonexact match found.  */
-             ambig = 1;
-         }
-
-      if (ambig && !exact)
-       {
-         if (opterr)
-           fprintf (stderr, "%s: option `%s' is ambiguous\n",
-                    argv[0], argv[optind]);
-         nextchar += strlen (nextchar);
-         optind++;
-         return '?';
-       }
-
-      if (pfound != NULL)
-       {
-         option_index = indfound;
-         optind++;
-         if (*s)
-           {
-             /* Don't test has_arg with >, because some C compilers don't
-                allow it to be used on enums.  */
-             if (pfound->has_arg)
-               optarg = s + 1;
-             else
-               {
-                 if (opterr)
-                   {
-                     if (argv[optind - 1][1] == '-')
-                       /* --option */
-                       fprintf (stderr,
-                                "%s: option `--%s' doesn't allow an argument\n",
-                                argv[0], pfound->name);
-                     else
-                       /* +option or -option */
-                       fprintf (stderr,
-                            "%s: option `%c%s' doesn't allow an argument\n",
-                            argv[0], argv[optind - 1][0], pfound->name);
-                   }
-                 nextchar += strlen (nextchar);
-                 return '?';
-               }
-           }
-         else if (pfound->has_arg == 1)
-           {
-             if (optind < argc)
-               optarg = argv[optind++];
-             else
-               {
-                 if (opterr)
-                   fprintf (stderr, "%s: option `%s' requires an argument\n",
-                            argv[0], argv[optind - 1]);
-                 nextchar += strlen (nextchar);
-                 return optstring[0] == ':' ? ':' : '?';
-               }
-           }
-         nextchar += strlen (nextchar);
-         if (longind != NULL)
-           *longind = option_index;
-         if (pfound->flag)
-           {
-             *(pfound->flag) = pfound->val;
-             return 0;
-           }
-         return pfound->val;
-       }
-      /* Can't find it as a long option.  If this is not getopt_long_only,
-        or the option starts with '--' or is not a valid short
-        option, then it's an error.
-        Otherwise interpret it as a short option.  */
-      if (!long_only || argv[optind][1] == '-'
-#ifdef GETOPT_COMPAT
-         || argv[optind][0] == '+'
-#endif                         /* GETOPT_COMPAT */
-         || my_index (optstring, *nextchar) == NULL)
-       {
-         if (opterr)
-           {
-             if (argv[optind][1] == '-')
-               /* --option */
-               fprintf (stderr, "%s: unrecognized option `--%s'\n",
-                        argv[0], nextchar);
-             else
-               /* +option or -option */
-               fprintf (stderr, "%s: unrecognized option `%c%s'\n",
-                        argv[0], argv[optind][0], nextchar);
-           }
-         nextchar = (char *) "";
-         optind++;
-         return '?';
-       }
-    }
-
-  /* Look at and handle the next option-character.  */
-
-  {
-    char c = *nextchar++;
-    char *temp = my_index (optstring, c);
-
-    /* Increment `optind' when we start to process its last character.  */
-    if (*nextchar == '\0')
-      ++optind;
-
-    if (temp == NULL || c == ':')
-      {
-       if (opterr)
-         {
-#if 0
-           if (c < 040 || c >= 0177)
-             fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
-                      argv[0], c);
-           else
-             fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
-#else
-           /* 1003.2 specifies the format of this message.  */
-           fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
-#endif
-         }
-       optopt = c;
-       return '?';
-      }
-    if (temp[1] == ':')
-      {
-       if (temp[2] == ':')
-         {
-           /* This is an option that accepts an argument optionally.  */
-           if (*nextchar != '\0')
-             {
-               optarg = nextchar;
-               optind++;
-             }
-           else
-             optarg = 0;
-           nextchar = NULL;
-         }
-       else
-         {
-           /* This is an option that requires an argument.  */
-           if (*nextchar != '\0')
-             {
-               optarg = nextchar;
-               /* If we end this ARGV-element by taking the rest as an arg,
-                  we must advance to the next element now.  */
-               optind++;
-             }
-           else if (optind == argc)
-             {
-               if (opterr)
-                 {
-#if 0
-                   fprintf (stderr, "%s: option `-%c' requires an argument\n",
-                            argv[0], c);
-#else
-                   /* 1003.2 specifies the format of this message.  */
-                   fprintf (stderr, "%s: option requires an argument -- %c\n",
-                            argv[0], c);
-#endif
-                 }
-               optopt = c;
-               if (optstring[0] == ':')
-                 c = ':';
-               else
-                 c = '?';
-             }
-           else
-             /* We already incremented `optind' once;
-                increment it again when taking next ARGV-elt as argument.  */
-             optarg = argv[optind++];
-           nextchar = NULL;
-         }
-      }
-    return c;
-  }
-}
-
-int
-getopt (argc, argv, optstring)
-     int argc;
-     char *const *argv;
-     const char *optstring;
-{
-  return _getopt_internal (argc, argv, optstring,
-                          (const struct option *) 0,
-                          (int *) 0,
-                          0);
-}
-
-#endif /* _LIBC or not __GNU_LIBRARY__.  */
-\f
-#ifdef TEST
-
-/* Compile with -DTEST to make an executable for use in testing
-   the above definition of `getopt'.  */
-
-int
-main (argc, argv)
-     int argc;
-     char **argv;
-{
-  int c;
-  int digit_optind = 0;
-
-  while (1)
-    {
-      int this_option_optind = optind ? optind : 1;
-
-      c = getopt (argc, argv, "abc:d:0123456789");
-      if (c == EOF)
-       break;
-
-      switch (c)
-       {
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-         if (digit_optind != 0 && digit_optind != this_option_optind)
-           printf ("digits occur in two different argv-elements.\n");
-         digit_optind = this_option_optind;
-         printf ("option %c\n", c);
-         break;
-
-       case 'a':
-         printf ("option a\n");
-         break;
-
-       case 'b':
-         printf ("option b\n");
-         break;
-
-       case 'c':
-         printf ("option c with value `%s'\n", optarg);
-         break;
-
-       case '?':
-         break;
-
-       default:
-         printf ("?? getopt returned character code 0%o ??\n", c);
-       }
-    }
-
-  if (optind < argc)
-    {
-      printf ("non-option ARGV-elements: ");
-      while (optind < argc)
-       printf ("%s ", argv[optind++]);
-      printf ("\n");
-    }
-
-  exit (0);
-}
-
-#endif /* TEST */
diff --git a/lib/contrib/getopt.h b/lib/contrib/getopt.h
deleted file mode 100644 (file)
index 45541f5..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Declarations for getopt.
-   Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-#ifndef _GETOPT_H
-#define _GETOPT_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
-
-   On entry to `getopt', zero means this is the first call; initialize.
-
-   When `getopt' returns EOF, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, `optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
-   for unrecognized options.  */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized.  */
-
-extern int optopt;
-
-/* Describe the long-named options requested by the application.
-   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
-   of `struct option' terminated by an element containing a name which is
-   zero.
-
-   The field `has_arg' is:
-   no_argument         (or 0) if the option does not take an argument,
-   required_argument   (or 1) if the option requires an argument,
-   optional_argument   (or 2) if the option takes an optional argument.
-
-   If the field `flag' is not NULL, it points to a variable that is set
-   to the value given in the field `val' when the option is found, but
-   left unchanged if the option is not found.
-
-   To have a long-named option do something other than set an `int' to
-   a compiled-in constant, such as set a value from `optarg', set the
-   option's `flag' field to zero and its `val' field to a nonzero
-   value (the equivalent single-letter option character, if there is
-   one).  For long options that have a zero `flag' field, `getopt'
-   returns the contents of the `val' field.  */
-
-struct option
-{
-#if    __STDC__
-  const char *name;
-#else
-  char *name;
-#endif
-  /* has_arg can't be an enum because some compilers complain about
-     type mismatches in all the code that assumes it is an int.  */
-  int has_arg;
-  int *flag;
-  int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'.  */
-
-#define        no_argument             0
-#define required_argument      1
-#define optional_argument      2
-
-#if __STDC__
-#if defined(__GNU_LIBRARY__)
-/* Many other libraries have conflicting prototypes for getopt, with
-   differences in the consts, in stdlib.h.  To avoid compilation
-   errors, only prototype getopt for the GNU C library.  */
-extern int getopt (int argc, char *const *argv, const char *shortopts);
-#else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-#endif /* not __GNU_LIBRARY__ */
-extern int getopt_long (int argc, char *const *argv, const char *shortopts,
-                       const struct option *longopts, int *longind);
-extern int getopt_long_only (int argc, char *const *argv,
-                            const char *shortopts,
-                            const struct option *longopts, int *longind);
-
-/* Internal only.  Users should not call this directly.  */
-extern int _getopt_internal (int argc, char *const *argv,
-                            const char *shortopts,
-                            const struct option *longopts, int *longind,
-                            int long_only);
-#else /* not __STDC__ */
-extern int getopt ();
-extern int getopt_long ();
-extern int getopt_long_only ();
-
-extern int _getopt_internal ();
-#endif /* not __STDC__ */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _GETOPT_H */
diff --git a/lib/contrib/getopt1.c b/lib/contrib/getopt1.c
deleted file mode 100644 (file)
index fe6bdd9..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/* getopt_long and getopt_long_only entry points for GNU getopt.
-   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
-       Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-\f
-
-#include "getopt.h"
-
-#ifndef __STDC__
-/* This is a separate conditional since some stdc systems
-   reject `defined (const)'.  */
-#ifndef const
-#define const
-#endif
-#endif
-
-#include <stdio.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
-
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-
-
-/* This needs to come after some library #include
-   to get __GNU_LIBRARY__ defined.  */
-#ifdef __GNU_LIBRARY__
-#include <stdlib.h>
-#else
-char *getenv ();
-#endif
-
-#ifndef        NULL
-#define NULL 0
-#endif
-
-int
-getopt_long (argc, argv, options, long_options, opt_index)
-     int argc;
-     char *const *argv;
-     const char *options;
-     const struct option *long_options;
-     int *opt_index;
-{
-  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
-}
-
-/* Like getopt_long, but '-' as well as '--' can indicate a long option.
-   If an option that starts with '-' (not '--') doesn't match a long option,
-   but does match a short option, it is parsed as a short option
-   instead.  */
-
-int
-getopt_long_only (argc, argv, options, long_options, opt_index)
-     int argc;
-     char *const *argv;
-     const char *options;
-     const struct option *long_options;
-     int *opt_index;
-{
-  return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
-}
-
-
-#endif /* _LIBC or not __GNU_LIBRARY__.  */
-\f
-#ifdef TEST
-
-#include <stdio.h>
-
-int
-main (argc, argv)
-     int argc;
-     char **argv;
-{
-  int c;
-  int digit_optind = 0;
-
-  while (1)
-    {
-      int this_option_optind = optind ? optind : 1;
-      int option_index = 0;
-      static struct option long_options[] =
-      {
-       {"add", 1, 0, 0},
-       {"append", 0, 0, 0},
-       {"delete", 1, 0, 0},
-       {"verbose", 0, 0, 0},
-       {"create", 0, 0, 0},
-       {"file", 1, 0, 0},
-       {0, 0, 0, 0}
-      };
-
-      c = getopt_long (argc, argv, "abc:d:0123456789",
-                      long_options, &option_index);
-      if (c == EOF)
-       break;
-
-      switch (c)
-       {
-       case 0:
-         printf ("option %s", long_options[option_index].name);
-         if (optarg)
-           printf (" with arg %s", optarg);
-         printf ("\n");
-         break;
-
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-       case '5':
-       case '6':
-       case '7':
-       case '8':
-       case '9':
-         if (digit_optind != 0 && digit_optind != this_option_optind)
-           printf ("digits occur in two different argv-elements.\n");
-         digit_optind = this_option_optind;
-         printf ("option %c\n", c);
-         break;
-
-       case 'a':
-         printf ("option a\n");
-         break;
-
-       case 'b':
-         printf ("option b\n");
-         break;
-
-       case 'c':
-         printf ("option c with value `%s'\n", optarg);
-         break;
-
-       case 'd':
-         printf ("option d with value `%s'\n", optarg);
-         break;
-
-       case '?':
-         break;
-
-       default:
-         printf ("?? getopt returned character code 0%o ??\n", c);
-       }
-    }
-
-  if (optind < argc)
-    {
-      printf ("non-option ARGV-elements: ");
-      while (optind < argc)
-       printf ("%s ", argv[optind++]);
-      printf ("\n");
-    }
-
-  exit (0);
-}
-
-#endif /* TEST */
diff --git a/lib/contrib/getopti.c b/lib/contrib/getopti.c
new file mode 100644 (file)
index 0000000..086cbb0
--- /dev/null
@@ -0,0 +1,70 @@
+/* Our own convenience getopt.  Public Domain. */
+#include "silcincludes.h"
+
+#ifndef SILC_EPOC
+#if !defined(HAVE_GETOPT) && !defined(HAVE_GETOPT_H)
+int    opterr = 1;
+int    optind = 1;
+int    optopt;
+char   *optarg;
+
+#define GETOPT_ERR(s, c)                       \
+do {                                           \
+  if (opterr) {                                        \
+    char errbuf[2];                            \
+    errbuf[0] = c;                             \
+    errbuf[1] = '\n';                          \
+    (void) write(2, argv[0], strlen(argv[0])); \
+    (void) write(2, s, strlen(s));             \
+    (void) write(2, errbuf, 2);                        \
+  }                                            \
+} while(0)
+
+int getopt(int argc, char * const *argv, const char *optstring)
+{
+  static int sp = 1;
+  register int c;
+  register char *cp;
+
+  if (sp == 1) {
+    if (optind >= argc ||
+       argv[optind][0] != '-' || argv[optind][1] == '\0') {
+      return EOF;
+    } else if (strcmp(argv[optind], "--") == 0) {
+      optind++;
+      return EOF;
+    }
+  }
+  optopt = c = argv[optind][sp];
+
+  if (c == ':' || (cp=strchr(optstring, c)) == NULL) {
+    GETOPT_ERR(": illegal option -- ", c);
+    if (argv[optind][++sp] == '\0') {
+      optind++;
+      sp = 1;
+    }
+    return '?';
+  }
+
+  if (*++cp == ':') {
+    if (argv[optind][sp+1] != '\0')
+      optarg = &argv[optind++][sp+1];
+    else if (++optind >= argc) {
+      GETOPT_ERR(": option requires an argument -- ", c);
+      sp = 1;
+      return '?';
+    } else
+      optarg = argv[optind++];
+    sp = 1;
+  } else {
+    if (argv[optind][++sp] == '\0') {
+      sp = 1;
+      optind++;
+    }
+    optarg = NULL;
+  }
+
+  return c;
+}
+#endif /* !HAVE_GETOPT && !HAVE_GETOPT_H */
+#endif /* !SILC_EPOC */
diff --git a/lib/contrib/getopti.h b/lib/contrib/getopti.h
new file mode 100644 (file)
index 0000000..449e4b5
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef GETOPTI_H
+#define GETOPTI_H
+
+#ifndef SILC_EPOC
+#if !defined(HAVE_GETOPT) && !defined(HAVE_GETOPT_H)
+/* Our own convenience getopt. */
+extern int opterr;
+extern int optind;
+extern int optopt;
+extern char *optarg;
+int getopt(int argc, char * const *argv, const char *optstring);
+#endif /* !HAVE_GETOPT && !HAVE_GETOPT_H */
+#endif /* !SILC_EPOC */
+
+#endif /* GETOPTI_H */
diff --git a/lib/contrib/regex.c b/lib/contrib/regex.c
deleted file mode 100644 (file)
index 6aec434..0000000
+++ /dev/null
@@ -1,4955 +0,0 @@
-/* Extended regular expression matching and search library,
-   version 0.12.
-   (Implements POSIX draft P10003.2/D11.2, except for
-   internationalization features.)
-
-   Copyright (C) 1993 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/* AIX requires this to be the first thing in the file. */
-#if defined (_AIX) && !defined (REGEX_MALLOC)
-  #pragma alloca
-#endif
-
-/*
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-*/
-
-/* We need this for `regex.h', and perhaps for the Emacs include files.  */
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
-ifdef HAVE_CONFIG_H
-##include "config.h"
-#endif
-*/
-
-/* The `emacs' switch turns on certain matching commands
-   that make sense only in Emacs. */
-#ifdef emacs
-
-#include "lisp.h"
-#include "buffer.h"
-#include "syntax.h"
-
-/* Emacs uses `NULL' as a predicate.  */
-#undef NULL
-
-#else  /* not emacs */
-
-/* We used to test for `BSTRING' here, but only GCC and Emacs define
-   `BSTRING', as far as I know, and neither of them use this code.  */
-#if HAVE_STRING_H || STDC_HEADERS
-#include <string.h>
-#ifndef bcmp
-#define bcmp(s1, s2, n)        memcmp ((s1), (s2), (n))
-#endif
-#ifndef bcopy
-#define bcopy(s, d, n) memcpy ((d), (s), (n))
-#endif
-#ifndef bzero
-#define bzero(s, n)    memset ((s), 0, (n))
-#endif
-#else
-#include <strings.h>
-#endif
-
-#include <stdlib.h>
-
-/* Define the syntax stuff for \<, \>, etc.  */
-
-/* This must be nonzero for the wordchar and notwordchar pattern
-   commands in re_match_2.  */
-#ifndef Sword 
-#define Sword 1
-#endif
-
-#ifdef SYNTAX_TABLE
-
-extern char *re_syntax_table;
-
-#else /* not SYNTAX_TABLE */
-
-/* How many characters in the character set.  */
-#define CHAR_SET_SIZE 256
-
-static char re_syntax_table[CHAR_SET_SIZE];
-
-static void
-init_syntax_once ()
-{
-   register int c;
-   static int done = 0;
-
-   if (done)
-     return;
-
-   bzero (re_syntax_table, sizeof re_syntax_table);
-
-   for (c = 'a'; c <= 'z'; c++)
-     re_syntax_table[c] = Sword;
-
-   for (c = 'A'; c <= 'Z'; c++)
-     re_syntax_table[c] = Sword;
-
-   for (c = '0'; c <= '9'; c++)
-     re_syntax_table[c] = Sword;
-
-   re_syntax_table['_'] = Sword;
-
-   done = 1;
-}
-
-#endif /* not SYNTAX_TABLE */
-
-#define SYNTAX(c) re_syntax_table[c]
-
-#endif /* not emacs */
-\f
-/* Get the interface, including the syntax bits.  */
-#include "regex.h"
-
-/* isalpha etc. are used for the character classes.  */
-#include <ctype.h>
-
-#ifndef isascii
-#define isascii(c) 1
-#endif
-
-#ifdef isblank
-#define ISBLANK(c) (isascii (c) && isblank (c))
-#else
-#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
-#endif
-#ifdef isgraph
-#define ISGRAPH(c) (isascii (c) && isgraph (c))
-#else
-#define ISGRAPH(c) (isascii (c) && isprint (c) && !isspace (c))
-#endif
-
-#define ISPRINT(c) (isascii (c) && isprint (c))
-#define ISDIGIT(c) (isascii (c) && isdigit (c))
-#define ISALNUM(c) (isascii (c) && isalnum (c))
-#define ISALPHA(c) (isascii (c) && isalpha (c))
-#define ISCNTRL(c) (isascii (c) && iscntrl (c))
-#define ISLOWER(c) (isascii (c) && islower (c))
-#define ISPUNCT(c) (isascii (c) && ispunct (c))
-#define ISSPACE(c) (isascii (c) && isspace (c))
-#define ISUPPER(c) (isascii (c) && isupper (c))
-#define ISXDIGIT(c) (isascii (c) && isxdigit (c))
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/* We remove any previous definition of `SIGN_EXTEND_CHAR',
-   since ours (we hope) works properly with all combinations of
-   machines, compilers, `char' and `unsigned char' argument types.
-   (Per Bothner suggested the basic approach.)  */
-#undef SIGN_EXTEND_CHAR
-#if __STDC__
-#define SIGN_EXTEND_CHAR(c) ((signed char) (c))
-#else  /* not __STDC__ */
-/* As in Harbison and Steele.  */
-#define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
-#endif
-\f
-/* Should we use malloc or alloca?  If REGEX_MALLOC is not defined, we
-   use `alloca' instead of `malloc'.  This is because using malloc in
-   re_search* or re_match* could cause memory leaks when C-g is used in
-   Emacs; also, malloc is slower and causes storage fragmentation.  On
-   the other hand, malloc is more portable, and easier to debug.  
-   
-   Because we sometimes use alloca, some routines have to be macros,
-   not functions -- `alloca'-allocated space disappears at the end of the
-   function it is called in.  */
-
-#ifdef REGEX_MALLOC
-
-#define REGEX_ALLOCATE malloc
-#define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize)
-
-#else /* not REGEX_MALLOC  */
-
-/* Emacs already defines alloca, sometimes.  */
-#ifndef alloca
-
-/* Make alloca work the best possible way.  */
-#ifdef __GNUC__
-#define alloca __builtin_alloca
-#else /* not __GNUC__ */
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#else /* not __GNUC__ or HAVE_ALLOCA_H */
-#ifndef _AIX /* Already did AIX, up at the top.  */
-char *alloca ();
-#endif /* not _AIX */
-#endif /* not HAVE_ALLOCA_H */ 
-#endif /* not __GNUC__ */
-
-#endif /* not alloca */
-
-#define REGEX_ALLOCATE alloca
-
-/* Assumes a `char *destination' variable.  */
-#define REGEX_REALLOCATE(source, osize, nsize)                         \
-  (destination = (char *) alloca (nsize),                              \
-   bcopy (source, destination, osize),                                 \
-   destination)
-
-#endif /* not REGEX_MALLOC */
-
-
-/* True if `size1' is non-NULL and PTR is pointing anywhere inside
-   `string1' or just past its end.  This works if PTR is NULL, which is
-   a good thing.  */
-#define FIRST_STRING_P(ptr)                                    \
-  (size1 && string1 <= (ptr) && (ptr) <= string1 + size1)
-
-/* (Re)Allocate N items of type T using malloc, or fail.  */
-#define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t)))
-#define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t)))
-#define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t)))
-
-#define BYTEWIDTH 8 /* In bits.  */
-
-#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
-
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-
-typedef char boolean;
-#define false 0
-#define true 1
-\f
-/* These are the command codes that appear in compiled regular
-   expressions.  Some opcodes are followed by argument bytes.  A
-   command code can specify any interpretation whatsoever for its
-   arguments.  Zero bytes may appear in the compiled regular expression.
-
-   The value of `exactn' is needed in search.c (search_buffer) in Emacs.
-   So regex.h defines a symbol `RE_EXACTN_VALUE' to be 1; the value of
-   `exactn' we use here must also be 1.  */
-
-typedef enum
-{
-  no_op = 0,
-
-        /* Followed by one byte giving n, then by n literal bytes.  */
-  exactn = 1,
-
-        /* Matches any (more or less) character.  */
-  anychar,
-
-        /* Matches any one char belonging to specified set.  First
-           following byte is number of bitmap bytes.  Then come bytes
-           for a bitmap saying which chars are in.  Bits in each byte
-           are ordered low-bit-first.  A character is in the set if its
-           bit is 1.  A character too large to have a bit in the map is
-           automatically not in the set.  */
-  charset,
-
-        /* Same parameters as charset, but match any character that is
-           not one of those specified.  */
-  charset_not,
-
-        /* Start remembering the text that is matched, for storing in a
-           register.  Followed by one byte with the register number, in
-           the range 0 to one less than the pattern buffer's re_nsub
-           field.  Then followed by one byte with the number of groups
-           inner to this one.  (This last has to be part of the
-           start_memory only because we need it in the on_failure_jump
-           of re_match_2.)  */
-  start_memory,
-
-        /* Stop remembering the text that is matched and store it in a
-           memory register.  Followed by one byte with the register
-           number, in the range 0 to one less than `re_nsub' in the
-           pattern buffer, and one byte with the number of inner groups,
-           just like `start_memory'.  (We need the number of inner
-           groups here because we don't have any easy way of finding the
-           corresponding start_memory when we're at a stop_memory.)  */
-  stop_memory,
-
-        /* Match a duplicate of something remembered. Followed by one
-           byte containing the register number.  */
-  duplicate,
-
-        /* Fail unless at beginning of line.  */
-  begline,
-
-        /* Fail unless at end of line.  */
-  endline,
-
-        /* Succeeds if at beginning of buffer (if emacs) or at beginning
-           of string to be matched (if not).  */
-  begbuf,
-
-        /* Analogously, for end of buffer/string.  */
-  endbuf,
-        /* Followed by two byte relative address to which to jump.  */
-  jump, 
-
-       /* Same as jump, but marks the end of an alternative.  */
-  jump_past_alt,
-
-        /* Followed by two-byte relative address of place to resume at
-           in case of failure.  */
-  on_failure_jump,
-       
-        /* Like on_failure_jump, but pushes a placeholder instead of the
-           current string position when executed.  */
-  on_failure_keep_string_jump,
-  
-        /* Throw away latest failure point and then jump to following
-           two-byte relative address.  */
-  pop_failure_jump,
-
-        /* Change to pop_failure_jump if know won't have to backtrack to
-           match; otherwise change to jump.  This is used to jump
-           back to the beginning of a repeat.  If what follows this jump
-           clearly won't match what the repeat does, such that we can be
-           sure that there is no use backtracking out of repetitions
-           already matched, then we change it to a pop_failure_jump.
-           Followed by two-byte address.  */
-  maybe_pop_jump,
-
-        /* Jump to following two-byte address, and push a dummy failure
-           point. This failure point will be thrown away if an attempt
-           is made to use it for a failure.  A `+' construct makes this
-           before the first repeat.  Also used as an intermediary kind
-           of jump when compiling an alternative.  */
-  dummy_failure_jump,
-
-       /* Push a dummy failure point and continue.  Used at the end of
-          alternatives.  */
-  push_dummy_failure,
-
-        /* Followed by two-byte relative address and two-byte number n.
-           After matching N times, jump to the address upon failure.  */
-  succeed_n,
-
-        /* Followed by two-byte relative address, and two-byte number n.
-           Jump to the address N times, then fail.  */
-  jump_n,
-
-        /* Set the following two-byte relative address to the
-           subsequent two-byte number.  The address *includes* the two
-           bytes of number.  */
-  set_number_at,
-
-  wordchar,    /* Matches any word-constituent character.  */
-  notwordchar, /* Matches any char that is not a word-constituent.  */
-
-  wordbeg,     /* Succeeds if at word beginning.  */
-  wordend,     /* Succeeds if at word end.  */
-
-  wordbound,   /* Succeeds if at a word boundary.  */
-  notwordbound /* Succeeds if not at a word boundary.  */
-
-#ifdef emacs
-  ,before_dot, /* Succeeds if before point.  */
-  at_dot,      /* Succeeds if at point.  */
-  after_dot,   /* Succeeds if after point.  */
-
-       /* Matches any character whose syntax is specified.  Followed by
-           a byte which contains a syntax code, e.g., Sword.  */
-  syntaxspec,
-
-       /* Matches any character whose syntax is not that specified.  */
-  notsyntaxspec
-#endif /* emacs */
-} re_opcode_t;
-\f
-/* Common operations on the compiled pattern.  */
-
-/* Store NUMBER in two contiguous bytes starting at DESTINATION.  */
-
-#define STORE_NUMBER(destination, number)                              \
-  do {                                                                 \
-    (destination)[0] = (number) & 0377;                                        \
-    (destination)[1] = (number) >> 8;                                  \
-  } while (0)
-
-/* Same as STORE_NUMBER, except increment DESTINATION to
-   the byte after where the number is stored.  Therefore, DESTINATION
-   must be an lvalue.  */
-
-#define STORE_NUMBER_AND_INCR(destination, number)                     \
-  do {                                                                 \
-    STORE_NUMBER (destination, number);                                        \
-    (destination) += 2;                                                        \
-  } while (0)
-
-/* Put into DESTINATION a number stored in two contiguous bytes starting
-   at SOURCE.  */
-
-#define EXTRACT_NUMBER(destination, source)                            \
-  do {                                                                 \
-    (destination) = *(source) & 0377;                                  \
-    (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8;          \
-  } while (0)
-
-#ifdef DEBUG
-static void
-extract_number (dest, source)
-    int *dest;
-    unsigned char *source;
-{
-  int temp = SIGN_EXTEND_CHAR (*(source + 1)); 
-  *dest = *source & 0377;
-  *dest += temp << 8;
-}
-
-#ifndef EXTRACT_MACROS /* To debug the macros.  */
-#undef EXTRACT_NUMBER
-#define EXTRACT_NUMBER(dest, src) extract_number (&dest, src)
-#endif /* not EXTRACT_MACROS */
-
-#endif /* DEBUG */
-
-/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number.
-   SOURCE must be an lvalue.  */
-
-#define EXTRACT_NUMBER_AND_INCR(destination, source)                   \
-  do {                                                                 \
-    EXTRACT_NUMBER (destination, source);                              \
-    (source) += 2;                                                     \
-  } while (0)
-
-#ifdef DEBUG
-static void
-extract_number_and_incr (destination, source)
-    int *destination;
-    unsigned char **source;
-{ 
-  extract_number (destination, *source);
-  *source += 2;
-}
-
-#ifndef EXTRACT_MACROS
-#undef EXTRACT_NUMBER_AND_INCR
-#define EXTRACT_NUMBER_AND_INCR(dest, src) \
-  extract_number_and_incr (&dest, &src)
-#endif /* not EXTRACT_MACROS */
-
-#endif /* DEBUG */
-\f
-/* If DEBUG is defined, Regex prints many voluminous messages about what
-   it is doing (if the variable `debug' is nonzero).  If linked with the
-   main program in `iregex.c', you can enter patterns and strings
-   interactively.  And if linked with the main program in `main.c' and
-   the other test files, you can run the already-written tests.  */
-
-#ifdef DEBUG
-
-/* We use standard I/O for debugging.  */
-#include <stdio.h>
-
-/* It is useful to test things that ``must'' be true when debugging.  */
-#include <assert.h>
-
-static int debug = 0;
-
-#define DEBUG_STATEMENT(e) e
-#define DEBUG_PRINT1(x) if (debug) printf (x)
-#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
-#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)                          \
-  if (debug) print_partial_compiled_pattern (s, e)
-#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)                 \
-  if (debug) print_double_string (w, s1, sz1, s2, sz2)
-
-
-extern void printchar ();
-
-/* Print the fastmap in human-readable form.  */
-
-void
-print_fastmap (fastmap)
-    char *fastmap;
-{
-  unsigned was_a_range = 0;
-  unsigned i = 0;  
-  
-  while (i < (1 << BYTEWIDTH))
-    {
-      if (fastmap[i++])
-       {
-         was_a_range = 0;
-          printchar (i - 1);
-          while (i < (1 << BYTEWIDTH)  &&  fastmap[i])
-            {
-              was_a_range = 1;
-              i++;
-            }
-         if (was_a_range)
-            {
-              printf ("-");
-              printchar (i - 1);
-            }
-        }
-    }
-  putchar ('\n'); 
-}
-
-
-/* Print a compiled pattern string in human-readable form, starting at
-   the START pointer into it and ending just before the pointer END.  */
-
-void
-print_partial_compiled_pattern (start, end)
-    unsigned char *start;
-    unsigned char *end;
-{
-  int mcnt, mcnt2;
-  unsigned char *p = start;
-  unsigned char *pend = end;
-
-  if (start == NULL)
-    {
-      printf ("(null)\n");
-      return;
-    }
-    
-  /* Loop over pattern commands.  */
-  while (p < pend)
-    {
-      switch ((re_opcode_t) *p++)
-       {
-        case no_op:
-          printf ("/no_op");
-          break;
-
-       case exactn:
-         mcnt = *p++;
-          printf ("/exactn/%d", mcnt);
-          do
-           {
-              putchar ('/');
-             printchar (*p++);
-            }
-          while (--mcnt);
-          break;
-
-       case start_memory:
-          mcnt = *p++;
-          printf ("/start_memory/%d/%d", mcnt, *p++);
-          break;
-
-       case stop_memory:
-          mcnt = *p++;
-         printf ("/stop_memory/%d/%d", mcnt, *p++);
-          break;
-
-       case duplicate:
-         printf ("/duplicate/%d", *p++);
-         break;
-
-       case anychar:
-         printf ("/anychar");
-         break;
-
-       case charset:
-        case charset_not:
-          {
-            register int c;
-
-            printf ("/charset%s",
-                   (re_opcode_t) *(p - 1) == charset_not ? "_not" : "");
-            
-            assert (p + *p < pend);
-
-            for (c = 0; c < *p; c++)
-              {
-                unsigned bit;
-                unsigned char map_byte = p[1 + c];
-                
-                putchar ('/');
-
-               for (bit = 0; bit < BYTEWIDTH; bit++)
-                  if (map_byte & (1 << bit))
-                    printchar (c * BYTEWIDTH + bit);
-              }
-           p += 1 + *p;
-           break;
-         }
-
-       case begline:
-         printf ("/begline");
-          break;
-
-       case endline:
-          printf ("/endline");
-          break;
-
-       case on_failure_jump:
-          extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_jump/0/%d", mcnt);
-          break;
-
-       case on_failure_keep_string_jump:
-          extract_number_and_incr (&mcnt, &p);
-         printf ("/on_failure_keep_string_jump/0/%d", mcnt);
-          break;
-
-       case dummy_failure_jump:
-          extract_number_and_incr (&mcnt, &p);
-         printf ("/dummy_failure_jump/0/%d", mcnt);
-          break;
-
-       case push_dummy_failure:
-          printf ("/push_dummy_failure");
-          break;
-          
-        case maybe_pop_jump:
-          extract_number_and_incr (&mcnt, &p);
-         printf ("/maybe_pop_jump/0/%d", mcnt);
-         break;
-
-        case pop_failure_jump:
-         extract_number_and_incr (&mcnt, &p);
-         printf ("/pop_failure_jump/0/%d", mcnt);
-         break;          
-          
-        case jump_past_alt:
-         extract_number_and_incr (&mcnt, &p);
-         printf ("/jump_past_alt/0/%d", mcnt);
-         break;          
-          
-        case jump:
-         extract_number_and_incr (&mcnt, &p);
-         printf ("/jump/0/%d", mcnt);
-         break;
-
-        case succeed_n: 
-          extract_number_and_incr (&mcnt, &p);
-          extract_number_and_incr (&mcnt2, &p);
-         printf ("/succeed_n/0/%d/0/%d", mcnt, mcnt2);
-          break;
-        
-        case jump_n: 
-          extract_number_and_incr (&mcnt, &p);
-          extract_number_and_incr (&mcnt2, &p);
-         printf ("/jump_n/0/%d/0/%d", mcnt, mcnt2);
-          break;
-        
-        case set_number_at: 
-          extract_number_and_incr (&mcnt, &p);
-          extract_number_and_incr (&mcnt2, &p);
-         printf ("/set_number_at/0/%d/0/%d", mcnt, mcnt2);
-          break;
-        
-        case wordbound:
-         printf ("/wordbound");
-         break;
-
-       case notwordbound:
-         printf ("/notwordbound");
-          break;
-
-       case wordbeg:
-         printf ("/wordbeg");
-         break;
-          
-       case wordend:
-         printf ("/wordend");
-          
-#ifdef emacs
-       case before_dot:
-         printf ("/before_dot");
-          break;
-
-       case at_dot:
-         printf ("/at_dot");
-          break;
-
-       case after_dot:
-         printf ("/after_dot");
-          break;
-
-       case syntaxspec:
-          printf ("/syntaxspec");
-         mcnt = *p++;
-         printf ("/%d", mcnt);
-          break;
-         
-       case notsyntaxspec:
-          printf ("/notsyntaxspec");
-         mcnt = *p++;
-         printf ("/%d", mcnt);
-         break;
-#endif /* emacs */
-
-       case wordchar:
-         printf ("/wordchar");
-          break;
-         
-       case notwordchar:
-         printf ("/notwordchar");
-          break;
-
-       case begbuf:
-         printf ("/begbuf");
-          break;
-
-       case endbuf:
-         printf ("/endbuf");
-          break;
-
-        default:
-          printf ("?%d", *(p-1));
-       }
-    }
-  printf ("/\n");
-}
-
-
-void
-print_compiled_pattern (bufp)
-    struct re_pattern_buffer *bufp;
-{
-  unsigned char *buffer = bufp->buffer;
-
-  print_partial_compiled_pattern (buffer, buffer + bufp->used);
-  printf ("%d bytes used/%d bytes allocated.\n", bufp->used, bufp->allocated);
-
-  if (bufp->fastmap_accurate && bufp->fastmap)
-    {
-      printf ("fastmap: ");
-      print_fastmap (bufp->fastmap);
-    }
-
-  printf ("re_nsub: %d\t", bufp->re_nsub);
-  printf ("regs_alloc: %d\t", bufp->regs_allocated);
-  printf ("can_be_null: %d\t", bufp->can_be_null);
-  printf ("newline_anchor: %d\n", bufp->newline_anchor);
-  printf ("no_sub: %d\t", bufp->no_sub);
-  printf ("not_bol: %d\t", bufp->not_bol);
-  printf ("not_eol: %d\t", bufp->not_eol);
-  printf ("syntax: %d\n", bufp->syntax);
-  /* Perhaps we should print the translate table?  */
-}
-
-
-void
-print_double_string (where, string1, size1, string2, size2)
-    const char *where;
-    const char *string1;
-    const char *string2;
-    int size1;
-    int size2;
-{
-  unsigned this_char;
-  
-  if (where == NULL)
-    printf ("(null)");
-  else
-    {
-      if (FIRST_STRING_P (where))
-        {
-          for (this_char = where - string1; this_char < size1; this_char++)
-            printchar (string1[this_char]);
-
-          where = string2;    
-        }
-
-      for (this_char = where - string2; this_char < size2; this_char++)
-        printchar (string2[this_char]);
-    }
-}
-
-#else /* not DEBUG */
-
-#undef assert
-#define assert(e)
-
-#define DEBUG_STATEMENT(e)
-#define DEBUG_PRINT1(x)
-#define DEBUG_PRINT2(x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4)
-#define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
-#define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
-
-#endif /* not DEBUG */
-\f
-/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
-   also be assigned to arbitrarily: each pattern buffer stores its own
-   syntax, so it can be changed between regex compilations.  */
-reg_syntax_t re_syntax_options = RE_SYNTAX_EMACS;
-
-
-/* Specify the precise syntax of regexps for compilation.  This provides
-   for compatibility for various utilities which historically have
-   different, incompatible syntaxes.
-
-   The argument SYNTAX is a bit mask comprised of the various bits
-   defined in regex.h.  We return the old syntax.  */
-
-reg_syntax_t
-re_set_syntax (syntax)
-    reg_syntax_t syntax;
-{
-  reg_syntax_t ret = re_syntax_options;
-  
-  re_syntax_options = syntax;
-  return ret;
-}
-\f
-/* This table gives an error message for each of the error codes listed
-   in regex.h.  Obviously the order here has to be same as there.  */
-
-static const char *re_error_msg[] =
-  { NULL,                                      /* REG_NOERROR */
-    "No match",                                        /* REG_NOMATCH */
-    "Invalid regular expression",              /* REG_BADPAT */
-    "Invalid collation character",             /* REG_ECOLLATE */
-    "Invalid character class name",            /* REG_ECTYPE */
-    "Trailing backslash",                      /* REG_EESCAPE */
-    "Invalid back reference",                  /* REG_ESUBREG */
-    "Unmatched [ or [^",                       /* REG_EBRACK */
-    "Unmatched ( or \\(",                      /* REG_EPAREN */
-    "Unmatched \\{",                           /* REG_EBRACE */
-    "Invalid content of \\{\\}",               /* REG_BADBR */
-    "Invalid range end",                       /* REG_ERANGE */
-    "Memory exhausted",                                /* REG_ESPACE */
-    "Invalid preceding regular expression",    /* REG_BADRPT */
-    "Premature end of regular expression",     /* REG_EEND */
-    "Regular expression too big",              /* REG_ESIZE */
-    "Unmatched ) or \\)",                      /* REG_ERPAREN */
-  };
-\f
-/* Subroutine declarations and macros for regex_compile.  */
-
-static void store_op1 (), store_op2 ();
-static void insert_op1 (), insert_op2 ();
-static boolean at_begline_loc_p (), at_endline_loc_p ();
-static boolean group_in_compile_stack ();
-static reg_errcode_t compile_range ();
-
-/* Fetch the next character in the uncompiled pattern---translating it 
-   if necessary.  Also cast from a signed character in the constant
-   string passed to us by the user to an unsigned char that we can use
-   as an array index (in, e.g., `translate').  */
-#define PATFETCH(c)                                                    \
-  do {if (p == pend) return REG_EEND;                                  \
-    c = (unsigned char) *p++;                                          \
-    if (translate) c = translate[c];                                   \
-  } while (0)
-
-/* Fetch the next character in the uncompiled pattern, with no
-   translation.  */
-#define PATFETCH_RAW(c)                                                        \
-  do {if (p == pend) return REG_EEND;                                  \
-    c = (unsigned char) *p++;                                          \
-  } while (0)
-
-/* Go backwards one character in the pattern.  */
-#define PATUNFETCH p--
-
-
-/* If `translate' is non-null, return translate[D], else just D.  We
-   cast the subscript to translate because some data is declared as
-   `char *', to avoid warnings when a string constant is passed.  But
-   when we use a character as a subscript we must make it unsigned.  */
-#define TRANSLATE(d) (translate ? translate[(unsigned char) (d)] : (d))
-
-
-/* Macros for outputting the compiled pattern into `buffer'.  */
-
-/* If the buffer isn't allocated when it comes in, use this.  */
-#define INIT_BUF_SIZE  32
-
-/* Make sure we have at least N more bytes of space in buffer.  */
-#define GET_BUFFER_SPACE(n)                                            \
-    while (b - bufp->buffer + (n) > bufp->allocated)                   \
-      EXTEND_BUFFER ()
-
-/* Make sure we have one more byte of buffer space and then add C to it.  */
-#define BUF_PUSH(c)                                                    \
-  do {                                                                 \
-    GET_BUFFER_SPACE (1);                                              \
-    *b++ = (unsigned char) (c);                                                \
-  } while (0)
-
-
-/* Ensure we have two more bytes of buffer space and then append C1 and C2.  */
-#define BUF_PUSH_2(c1, c2)                                             \
-  do {                                                                 \
-    GET_BUFFER_SPACE (2);                                              \
-    *b++ = (unsigned char) (c1);                                       \
-    *b++ = (unsigned char) (c2);                                       \
-  } while (0)
-
-
-/* As with BUF_PUSH_2, except for three bytes.  */
-#define BUF_PUSH_3(c1, c2, c3)                                         \
-  do {                                                                 \
-    GET_BUFFER_SPACE (3);                                              \
-    *b++ = (unsigned char) (c1);                                       \
-    *b++ = (unsigned char) (c2);                                       \
-    *b++ = (unsigned char) (c3);                                       \
-  } while (0)
-
-
-/* Store a jump with opcode OP at LOC to location TO.  We store a
-   relative address offset by the three bytes the jump itself occupies.  */
-#define STORE_JUMP(op, loc, to) \
-  store_op1 (op, loc, (to) - (loc) - 3)
-
-/* Likewise, for a two-argument jump.  */
-#define STORE_JUMP2(op, loc, to, arg) \
-  store_op2 (op, loc, (to) - (loc) - 3, arg)
-
-/* Like `STORE_JUMP', but for inserting.  Assume `b' is the buffer end.  */
-#define INSERT_JUMP(op, loc, to) \
-  insert_op1 (op, loc, (to) - (loc) - 3, b)
-
-/* Like `STORE_JUMP2', but for inserting.  Assume `b' is the buffer end.  */
-#define INSERT_JUMP2(op, loc, to, arg) \
-  insert_op2 (op, loc, (to) - (loc) - 3, arg, b)
-
-
-/* This is not an arbitrary limit: the arguments which represent offsets
-   into the pattern are two bytes long.  So if 2^16 bytes turns out to
-   be too small, many things would have to change.  */
-#define MAX_BUF_SIZE (1L << 16)
-
-
-/* Extend the buffer by twice its current size via realloc and
-   reset the pointers that pointed into the old block to point to the
-   correct places in the new one.  If extending the buffer results in it
-   being larger than MAX_BUF_SIZE, then flag memory exhausted.  */
-#define EXTEND_BUFFER()                                                        \
-  do {                                                                         \
-    unsigned char *old_buffer = bufp->buffer;                          \
-    if (bufp->allocated == MAX_BUF_SIZE)                               \
-      return REG_ESIZE;                                                        \
-    bufp->allocated <<= 1;                                             \
-    if (bufp->allocated > MAX_BUF_SIZE)                                        \
-      bufp->allocated = MAX_BUF_SIZE;                                  \
-    bufp->buffer = (unsigned char *) realloc (bufp->buffer, bufp->allocated);\
-    if (bufp->buffer == NULL)                                          \
-      return REG_ESPACE;                                               \
-    /* If the buffer moved, move all the pointers into it.  */         \
-    if (old_buffer != bufp->buffer)                                    \
-      {                                                                        \
-        b = (b - old_buffer) + bufp->buffer;                           \
-        begalt = (begalt - old_buffer) + bufp->buffer;                 \
-        if (fixup_alt_jump)                                            \
-          fixup_alt_jump = (fixup_alt_jump - old_buffer) + bufp->buffer;\
-        if (laststart)                                                 \
-          laststart = (laststart - old_buffer) + bufp->buffer;         \
-        if (pending_exact)                                             \
-          pending_exact = (pending_exact - old_buffer) + bufp->buffer; \
-      }                                                                        \
-  } while (0)
-
-
-/* Since we have one byte reserved for the register number argument to
-   {start,stop}_memory, the maximum number of groups we can report
-   things about is what fits in that byte.  */
-#define MAX_REGNUM 255
-
-/* But patterns can have more than `MAX_REGNUM' registers.  We just
-   ignore the excess.  */
-typedef unsigned regnum_t;
-
-
-/* Macros for the compile stack.  */
-
-/* Since offsets can go either forwards or backwards, this type needs to
-   be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1.  */
-typedef int pattern_offset_t;
-
-typedef struct
-{
-  pattern_offset_t begalt_offset;
-  pattern_offset_t fixup_alt_jump;
-  pattern_offset_t inner_group_offset;
-  pattern_offset_t laststart_offset;  
-  regnum_t regnum;
-} compile_stack_elt_t;
-
-
-typedef struct
-{
-  compile_stack_elt_t *stack;
-  unsigned size;
-  unsigned avail;                      /* Offset of next open position.  */
-} compile_stack_type;
-
-
-#define INIT_COMPILE_STACK_SIZE 32
-
-#define COMPILE_STACK_EMPTY  (compile_stack.avail == 0)
-#define COMPILE_STACK_FULL  (compile_stack.avail == compile_stack.size)
-
-/* The next available element.  */
-#define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail])
-
-
-/* Set the bit for character C in a list.  */
-#define SET_LIST_BIT(c)                               \
-  (b[((unsigned char) (c)) / BYTEWIDTH]               \
-   |= 1 << (((unsigned char) c) % BYTEWIDTH))
-
-
-/* Get the next unsigned number in the uncompiled pattern.  */
-#define GET_UNSIGNED_NUMBER(num)                                       \
-  { if (p != pend)                                                     \
-     {                                                                 \
-       PATFETCH (c);                                                   \
-       while (ISDIGIT (c))                                             \
-         {                                                             \
-           if (num < 0)                                                        \
-              num = 0;                                                 \
-           num = num * 10 + c - '0';                                   \
-           if (p == pend)                                              \
-              break;                                                   \
-           PATFETCH (c);                                               \
-         }                                                             \
-       }                                                               \
-    }          
-
-#define CHAR_CLASS_MAX_LENGTH  6 /* Namely, `xdigit'.  */
-
-#define IS_CHAR_CLASS(string)                                          \
-   (STREQ (string, "alpha") || STREQ (string, "upper")                 \
-    || STREQ (string, "lower") || STREQ (string, "digit")              \
-    || STREQ (string, "alnum") || STREQ (string, "xdigit")             \
-    || STREQ (string, "space") || STREQ (string, "print")              \
-    || STREQ (string, "punct") || STREQ (string, "graph")              \
-    || STREQ (string, "cntrl") || STREQ (string, "blank"))
-\f
-/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX.
-   Returns one of error codes defined in `regex.h', or zero for success.
-
-   Assumes the `allocated' (and perhaps `buffer') and `translate'
-   fields are set in BUFP on entry.
-
-   If it succeeds, results are put in BUFP (if it returns an error, the
-   contents of BUFP are undefined):
-     `buffer' is the compiled pattern;
-     `syntax' is set to SYNTAX;
-     `used' is set to the length of the compiled pattern;
-     `fastmap_accurate' is zero;
-     `re_nsub' is the number of subexpressions in PATTERN;
-     `not_bol' and `not_eol' are zero;
-   
-   The `fastmap' and `newline_anchor' fields are neither
-   examined nor set.  */
-
-static reg_errcode_t
-regex_compile (pattern, size, syntax, bufp)
-     const char *pattern;
-     int size;
-     reg_syntax_t syntax;
-     struct re_pattern_buffer *bufp;
-{
-  /* We fetch characters from PATTERN here.  Even though PATTERN is
-     `char *' (i.e., signed), we declare these variables as unsigned, so
-     they can be reliably used as array indices.  */
-  register unsigned char c, c1;
-  
-  /* A random tempory spot in PATTERN.  */
-  const char *p1;
-
-  /* Points to the end of the buffer, where we should append.  */
-  register unsigned char *b;
-  
-  /* Keeps track of unclosed groups.  */
-  compile_stack_type compile_stack;
-
-  /* Points to the current (ending) position in the pattern.  */
-  const char *p = pattern;
-  const char *pend = pattern + size;
-  
-  /* How to translate the characters in the pattern.  */
-  char *translate = bufp->translate;
-
-  /* Address of the count-byte of the most recently inserted `exactn'
-     command.  This makes it possible to tell if a new exact-match
-     character can be added to that command or if the character requires
-     a new `exactn' command.  */
-  unsigned char *pending_exact = 0;
-
-  /* Address of start of the most recently finished expression.
-     This tells, e.g., postfix * where to find the start of its
-     operand.  Reset at the beginning of groups and alternatives.  */
-  unsigned char *laststart = 0;
-
-  /* Address of beginning of regexp, or inside of last group.  */
-  unsigned char *begalt;
-
-  /* Place in the uncompiled pattern (i.e., the {) to
-     which to go back if the interval is invalid.  */
-  const char *beg_interval;
-                
-  /* Address of the place where a forward jump should go to the end of
-     the containing expression.  Each alternative of an `or' -- except the
-     last -- ends with a forward jump of this sort.  */
-  unsigned char *fixup_alt_jump = 0;
-
-  /* Counts open-groups as they are encountered.  Remembered for the
-     matching close-group on the compile stack, so the same register
-     number is put in the stop_memory as the start_memory.  */
-  regnum_t regnum = 0;
-
-#ifdef DEBUG
-  DEBUG_PRINT1 ("\nCompiling pattern: ");
-  if (debug)
-    {
-      unsigned debug_count;
-      
-      for (debug_count = 0; debug_count < size; debug_count++)
-        printchar (pattern[debug_count]);
-      putchar ('\n');
-    }
-#endif /* DEBUG */
-
-  /* Initialize the compile stack.  */
-  compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t);
-  if (compile_stack.stack == NULL)
-    return REG_ESPACE;
-
-  compile_stack.size = INIT_COMPILE_STACK_SIZE;
-  compile_stack.avail = 0;
-
-  /* Initialize the pattern buffer.  */
-  bufp->syntax = syntax;
-  bufp->fastmap_accurate = 0;
-  bufp->not_bol = bufp->not_eol = 0;
-
-  /* Set `used' to zero, so that if we return an error, the pattern
-     printer (for debugging) will think there's no pattern.  We reset it
-     at the end.  */
-  bufp->used = 0;
-  
-  /* Always count groups, whether or not bufp->no_sub is set.  */
-  bufp->re_nsub = 0;                           
-
-#if !defined (emacs) && !defined (SYNTAX_TABLE)
-  /* Initialize the syntax table.  */
-   init_syntax_once ();
-#endif
-
-  if (bufp->allocated == 0)
-    {
-      if (bufp->buffer)
-       { /* If zero allocated, but buffer is non-null, try to realloc
-             enough space.  This loses if buffer's address is bogus, but
-             that is the user's responsibility.  */
-          RETALLOC (bufp->buffer, INIT_BUF_SIZE, unsigned char);
-        }
-      else
-        { /* Caller did not allocate a buffer.  Do it for them.  */
-          bufp->buffer = TALLOC (INIT_BUF_SIZE, unsigned char);
-        }
-      if (!bufp->buffer) return REG_ESPACE;
-
-      bufp->allocated = INIT_BUF_SIZE;
-    }
-
-  begalt = b = bufp->buffer;
-
-  /* Loop through the uncompiled pattern until we're at the end.  */
-  while (p != pend)
-    {
-      PATFETCH (c);
-
-      switch (c)
-        {
-        case '^':
-          {
-            if (   /* If at start of pattern, it's an operator.  */
-                   p == pattern + 1
-                   /* If context independent, it's an operator.  */
-                || syntax & RE_CONTEXT_INDEP_ANCHORS
-                   /* Otherwise, depends on what's come before.  */
-                || at_begline_loc_p (pattern, p, syntax))
-              BUF_PUSH (begline);
-            else
-              goto normal_char;
-          }
-          break;
-
-
-        case '$':
-          {
-            if (   /* If at end of pattern, it's an operator.  */
-                   p == pend 
-                   /* If context independent, it's an operator.  */
-                || syntax & RE_CONTEXT_INDEP_ANCHORS
-                   /* Otherwise, depends on what's next.  */
-                || at_endline_loc_p (p, pend, syntax))
-               BUF_PUSH (endline);
-             else
-               goto normal_char;
-           }
-           break;
-
-
-       case '+':
-        case '?':
-          if ((syntax & RE_BK_PLUS_QM)
-              || (syntax & RE_LIMITED_OPS))
-            goto normal_char;
-        handle_plus:
-        case '*':
-          /* If there is no previous pattern... */
-          if (!laststart)
-            {
-              if (syntax & RE_CONTEXT_INVALID_OPS)
-                return REG_BADRPT;
-              else if (!(syntax & RE_CONTEXT_INDEP_OPS))
-                goto normal_char;
-            }
-
-          {
-            /* Are we optimizing this jump?  */
-            boolean keep_string_p = false;
-            
-            /* 1 means zero (many) matches is allowed.  */
-            char zero_times_ok = 0, many_times_ok = 0;
-
-            /* If there is a sequence of repetition chars, collapse it
-               down to just one (the right one).  We can't combine
-               interval operators with these because of, e.g., `a{2}*',
-               which should only match an even number of `a's.  */
-
-            for (;;)
-              {
-                zero_times_ok |= c != '+';
-                many_times_ok |= c != '?';
-
-                if (p == pend)
-                  break;
-
-                PATFETCH (c);
-
-                if (c == '*'
-                    || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?')))
-                  ;
-
-                else if (syntax & RE_BK_PLUS_QM  &&  c == '\\')
-                  {
-                    if (p == pend) return REG_EESCAPE;
-
-                    PATFETCH (c1);
-                    if (!(c1 == '+' || c1 == '?'))
-                      {
-                        PATUNFETCH;
-                        PATUNFETCH;
-                        break;
-                      }
-
-                    c = c1;
-                  }
-                else
-                  {
-                    PATUNFETCH;
-                    break;
-                  }
-
-                /* If we get here, we found another repeat character.  */
-               }
-
-            /* Star, etc. applied to an empty pattern is equivalent
-               to an empty pattern.  */
-            if (!laststart)  
-              break;
-
-            /* Now we know whether or not zero matches is allowed
-               and also whether or not two or more matches is allowed.  */
-            if (many_times_ok)
-              { /* More than one repetition is allowed, so put in at the
-                   end a backward relative jump from `b' to before the next
-                   jump we're going to put in below (which jumps from
-                   laststart to after this jump).  
-
-                   But if we are at the `*' in the exact sequence `.*\n',
-                   insert an unconditional jump backwards to the .,
-                   instead of the beginning of the loop.  This way we only
-                   push a failure point once, instead of every time
-                   through the loop.  */
-                assert (p - 1 > pattern);
-
-                /* Allocate the space for the jump.  */
-                GET_BUFFER_SPACE (3);
-
-                /* We know we are not at the first character of the pattern,
-                   because laststart was nonzero.  And we've already
-                   incremented `p', by the way, to be the character after
-                   the `*'.  Do we have to do something analogous here
-                   for null bytes, because of RE_DOT_NOT_NULL?  */
-                if (TRANSLATE (*(p - 2)) == TRANSLATE ('.')
-                   && zero_times_ok
-                    && p < pend && TRANSLATE (*p) == TRANSLATE ('\n')
-                    && !(syntax & RE_DOT_NEWLINE))
-                  { /* We have .*\n.  */
-                    STORE_JUMP (jump, b, laststart);
-                    keep_string_p = true;
-                  }
-                else
-                  /* Anything else.  */
-                  STORE_JUMP (maybe_pop_jump, b, laststart - 3);
-
-                /* We've added more stuff to the buffer.  */
-                b += 3;
-              }
-
-            /* On failure, jump from laststart to b + 3, which will be the
-               end of the buffer after this jump is inserted.  */
-            GET_BUFFER_SPACE (3);
-            INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump
-                                       : on_failure_jump,
-                         laststart, b + 3);
-            pending_exact = 0;
-            b += 3;
-
-            if (!zero_times_ok)
-              {
-                /* At least one repetition is required, so insert a
-                   `dummy_failure_jump' before the initial
-                   `on_failure_jump' instruction of the loop. This
-                   effects a skip over that instruction the first time
-                   we hit that loop.  */
-                GET_BUFFER_SPACE (3);
-                INSERT_JUMP (dummy_failure_jump, laststart, laststart + 6);
-                b += 3;
-              }
-            }
-         break;
-
-
-       case '.':
-          laststart = b;
-          BUF_PUSH (anychar);
-          break;
-
-
-        case '[':
-          {
-            boolean had_char_class = false;
-
-            if (p == pend) return REG_EBRACK;
-
-            /* Ensure that we have enough space to push a charset: the
-               opcode, the length count, and the bitset; 34 bytes in all.  */
-           GET_BUFFER_SPACE (34);
-
-            laststart = b;
-
-            /* We test `*p == '^' twice, instead of using an if
-               statement, so we only need one BUF_PUSH.  */
-            BUF_PUSH (*p == '^' ? charset_not : charset); 
-            if (*p == '^')
-              p++;
-
-            /* Remember the first position in the bracket expression.  */
-            p1 = p;
-
-            /* Push the number of bytes in the bitmap.  */
-            BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH);
-
-            /* Clear the whole map.  */
-            bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH);
-
-            /* charset_not matches newline according to a syntax bit.  */
-            if ((re_opcode_t) b[-2] == charset_not
-                && (syntax & RE_HAT_LISTS_NOT_NEWLINE))
-              SET_LIST_BIT ('\n');
-
-            /* Read in characters and ranges, setting map bits.  */
-            for (;;)
-              {
-                if (p == pend) return REG_EBRACK;
-
-                PATFETCH (c);
-
-                /* \ might escape characters inside [...] and [^...].  */
-                if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\')
-                  {
-                    if (p == pend) return REG_EESCAPE;
-
-                    PATFETCH (c1);
-                    SET_LIST_BIT (c1);
-                    continue;
-                  }
-
-                /* Could be the end of the bracket expression.  If it's
-                   not (i.e., when the bracket expression is `[]' so
-                   far), the ']' character bit gets set way below.  */
-                if (c == ']' && p != p1 + 1)
-                  break;
-
-                /* Look ahead to see if it's a range when the last thing
-                   was a character class.  */
-                if (had_char_class && c == '-' && *p != ']')
-                  return REG_ERANGE;
-
-                /* Look ahead to see if it's a range when the last thing
-                   was a character: if this is a hyphen not at the
-                   beginning or the end of a list, then it's the range
-                   operator.  */
-                if (c == '-' 
-                    && !(p - 2 >= pattern && p[-2] == '[') 
-                    && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^')
-                    && *p != ']')
-                  {
-                    reg_errcode_t ret
-                      = compile_range (&p, pend, translate, syntax, b);
-                    if (ret != REG_NOERROR) return ret;
-                  }
-
-                else if (p[0] == '-' && p[1] != ']')
-                  { /* This handles ranges made up of characters only.  */
-                    reg_errcode_t ret;
-
-                   /* Move past the `-'.  */
-                    PATFETCH (c1);
-                    
-                    ret = compile_range (&p, pend, translate, syntax, b);
-                    if (ret != REG_NOERROR) return ret;
-                  }
-
-                /* See if we're at the beginning of a possible character
-                   class.  */
-
-                else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':')
-                  { /* Leave room for the null.  */
-                    char str[CHAR_CLASS_MAX_LENGTH + 1];
-
-                    PATFETCH (c);
-                    c1 = 0;
-
-                    /* If pattern is `[[:'.  */
-                    if (p == pend) return REG_EBRACK;
-
-                    for (;;)
-                      {
-                        PATFETCH (c);
-                        if (c == ':' || c == ']' || p == pend
-                            || c1 == CHAR_CLASS_MAX_LENGTH)
-                          break;
-                        str[c1++] = c;
-                      }
-                    str[c1] = '\0';
-
-                    /* If isn't a word bracketed by `[:' and:`]':
-                       undo the ending character, the letters, and leave 
-                       the leading `:' and `[' (but set bits for them).  */
-                    if (c == ':' && *p == ']')
-                      {
-                        int ch;
-                        boolean is_alnum = STREQ (str, "alnum");
-                        boolean is_alpha = STREQ (str, "alpha");
-                        boolean is_blank = STREQ (str, "blank");
-                        boolean is_cntrl = STREQ (str, "cntrl");
-                        boolean is_digit = STREQ (str, "digit");
-                        boolean is_graph = STREQ (str, "graph");
-                        boolean is_lower = STREQ (str, "lower");
-                        boolean is_print = STREQ (str, "print");
-                        boolean is_punct = STREQ (str, "punct");
-                        boolean is_space = STREQ (str, "space");
-                        boolean is_upper = STREQ (str, "upper");
-                        boolean is_xdigit = STREQ (str, "xdigit");
-                        
-                        if (!IS_CHAR_CLASS (str)) return REG_ECTYPE;
-
-                        /* Throw away the ] at the end of the character
-                           class.  */
-                        PATFETCH (c);                                  
-
-                        if (p == pend) return REG_EBRACK;
-
-                        for (ch = 0; ch < 1 << BYTEWIDTH; ch++)
-                          {
-                            if (   (is_alnum  && ISALNUM (ch))
-                                || (is_alpha  && ISALPHA (ch))
-                                || (is_blank  && ISBLANK (ch))
-                                || (is_cntrl  && ISCNTRL (ch))
-                                || (is_digit  && ISDIGIT (ch))
-                                || (is_graph  && ISGRAPH (ch))
-                                || (is_lower  && ISLOWER (ch))
-                                || (is_print  && ISPRINT (ch))
-                                || (is_punct  && ISPUNCT (ch))
-                                || (is_space  && ISSPACE (ch))
-                                || (is_upper  && ISUPPER (ch))
-                                || (is_xdigit && ISXDIGIT (ch)))
-                            SET_LIST_BIT (ch);
-                          }
-                        had_char_class = true;
-                      }
-                    else
-                      {
-                        c1++;
-                        while (c1--)    
-                          PATUNFETCH;
-                        SET_LIST_BIT ('[');
-                        SET_LIST_BIT (':');
-                        had_char_class = false;
-                      }
-                  }
-                else
-                  {
-                    had_char_class = false;
-                    SET_LIST_BIT (c);
-                  }
-              }
-
-            /* Discard any (non)matching list bytes that are all 0 at the
-               end of the map.  Decrease the map-length byte too.  */
-            while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) 
-              b[-1]--; 
-            b += b[-1];
-          }
-          break;
-
-
-       case '(':
-          if (syntax & RE_NO_BK_PARENS)
-            goto handle_open;
-          else
-            goto normal_char;
-
-
-        case ')':
-          if (syntax & RE_NO_BK_PARENS)
-            goto handle_close;
-          else
-            goto normal_char;
-
-
-        case '\n':
-          if (syntax & RE_NEWLINE_ALT)
-            goto handle_alt;
-          else
-            goto normal_char;
-
-
-       case '|':
-          if (syntax & RE_NO_BK_VBAR)
-            goto handle_alt;
-          else
-            goto normal_char;
-
-
-        case '{':
-           if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES)
-             goto handle_interval;
-           else
-             goto normal_char;
-
-
-        case '\\':
-          if (p == pend) return REG_EESCAPE;
-
-          /* Do not translate the character after the \, so that we can
-             distinguish, e.g., \B from \b, even if we normally would
-             translate, e.g., B to b.  */
-          PATFETCH_RAW (c);
-
-          switch (c)
-            {
-            case '(':
-              if (syntax & RE_NO_BK_PARENS)
-                goto normal_backslash;
-
-            handle_open:
-              bufp->re_nsub++;
-              regnum++;
-
-              if (COMPILE_STACK_FULL)
-                { 
-                  RETALLOC (compile_stack.stack, compile_stack.size << 1,
-                            compile_stack_elt_t);
-                  if (compile_stack.stack == NULL) return REG_ESPACE;
-
-                  compile_stack.size <<= 1;
-                }
-
-              /* These are the values to restore when we hit end of this
-                 group.  They are all relative offsets, so that if the
-                 whole pattern moves because of realloc, they will still
-                 be valid.  */
-              COMPILE_STACK_TOP.begalt_offset = begalt - bufp->buffer;
-              COMPILE_STACK_TOP.fixup_alt_jump 
-                = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
-              COMPILE_STACK_TOP.laststart_offset = b - bufp->buffer;
-              COMPILE_STACK_TOP.regnum = regnum;
-
-              /* We will eventually replace the 0 with the number of
-                 groups inner to this one.  But do not push a
-                 start_memory for groups beyond the last one we can
-                 represent in the compiled pattern.  */
-              if (regnum <= MAX_REGNUM)
-                {
-                  COMPILE_STACK_TOP.inner_group_offset = b - bufp->buffer + 2;
-                  BUF_PUSH_3 (start_memory, regnum, 0);
-                }
-                
-              compile_stack.avail++;
-
-              fixup_alt_jump = 0;
-              laststart = 0;
-              begalt = b;
-             /* If we've reached MAX_REGNUM groups, then this open
-                won't actually generate any code, so we'll have to
-                clear pending_exact explicitly.  */
-             pending_exact = 0;
-              break;
-
-
-            case ')':
-              if (syntax & RE_NO_BK_PARENS) goto normal_backslash;
-
-              if (COMPILE_STACK_EMPTY) 
-               {
-                 if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
-                   goto normal_backslash;
-                 else
-                   return REG_ERPAREN;
-               }
-
-            handle_close:
-              if (fixup_alt_jump)
-                { /* Push a dummy failure point at the end of the
-                     alternative for a possible future
-                     `pop_failure_jump' to pop.  See comments at
-                     `push_dummy_failure' in `re_match_2'.  */
-                  BUF_PUSH (push_dummy_failure);
-                  
-                  /* We allocated space for this jump when we assigned
-                     to `fixup_alt_jump', in the `handle_alt' case below.  */
-                  STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1);
-                }
-
-              /* See similar code for backslashed left paren above.  */
-              if (COMPILE_STACK_EMPTY)
-               {
-                 if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)
-                   goto normal_char;
-                 else
-                   return REG_ERPAREN;
-               }
-
-              /* Since we just checked for an empty stack above, this
-                 ``can't happen''.  */
-              assert (compile_stack.avail != 0);
-              {
-                /* We don't just want to restore into `regnum', because
-                   later groups should continue to be numbered higher,
-                   as in `(ab)c(de)' -- the second group is #2.  */
-                regnum_t this_group_regnum;
-
-                compile_stack.avail--;         
-                begalt = bufp->buffer + COMPILE_STACK_TOP.begalt_offset;
-                fixup_alt_jump
-                  = COMPILE_STACK_TOP.fixup_alt_jump
-                    ? bufp->buffer + COMPILE_STACK_TOP.fixup_alt_jump - 1 
-                    : 0;
-                laststart = bufp->buffer + COMPILE_STACK_TOP.laststart_offset;
-                this_group_regnum = COMPILE_STACK_TOP.regnum;
-               /* If we've reached MAX_REGNUM groups, then this open
-                  won't actually generate any code, so we'll have to
-                  clear pending_exact explicitly.  */
-               pending_exact = 0;
-
-                /* We're at the end of the group, so now we know how many
-                   groups were inside this one.  */
-                if (this_group_regnum <= MAX_REGNUM)
-                  {
-                    unsigned char *inner_group_loc
-                      = bufp->buffer + COMPILE_STACK_TOP.inner_group_offset;
-                    
-                    *inner_group_loc = regnum - this_group_regnum;
-                    BUF_PUSH_3 (stop_memory, this_group_regnum,
-                                regnum - this_group_regnum);
-                  }
-              }
-              break;
-
-
-            case '|':                                  /* `\|'.  */
-              if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR)
-                goto normal_backslash;
-            handle_alt:
-              if (syntax & RE_LIMITED_OPS)
-                goto normal_char;
-
-              /* Insert before the previous alternative a jump which
-                 jumps to this alternative if the former fails.  */
-              GET_BUFFER_SPACE (3);
-              INSERT_JUMP (on_failure_jump, begalt, b + 6);
-              pending_exact = 0;
-              b += 3;
-
-              /* The alternative before this one has a jump after it
-                 which gets executed if it gets matched.  Adjust that
-                 jump so it will jump to this alternative's analogous
-                 jump (put in below, which in turn will jump to the next
-                 (if any) alternative's such jump, etc.).  The last such
-                 jump jumps to the correct final destination.  A picture:
-                          _____ _____ 
-                          |   | |   |   
-                          |   v |   v 
-                         a | b   | c   
-
-                 If we are at `b', then fixup_alt_jump right now points to a
-                 three-byte space after `a'.  We'll put in the jump, set
-                 fixup_alt_jump to right after `b', and leave behind three
-                 bytes which we'll fill in when we get to after `c'.  */
-
-              if (fixup_alt_jump)
-                STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
-
-              /* Mark and leave space for a jump after this alternative,
-                 to be filled in later either by next alternative or
-                 when know we're at the end of a series of alternatives.  */
-              fixup_alt_jump = b;
-              GET_BUFFER_SPACE (3);
-              b += 3;
-
-              laststart = 0;
-              begalt = b;
-              break;
-
-
-            case '{': 
-              /* If \{ is a literal.  */
-              if (!(syntax & RE_INTERVALS)
-                     /* If we're at `\{' and it's not the open-interval 
-                        operator.  */
-                  || ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
-                  || (p - 2 == pattern  &&  p == pend))
-                goto normal_backslash;
-
-            handle_interval:
-              {
-                /* If got here, then the syntax allows intervals.  */
-
-                /* At least (most) this many matches must be made.  */
-                int lower_bound = -1, upper_bound = -1;
-
-                beg_interval = p - 1;
-
-                if (p == pend)
-                  {
-                    if (syntax & RE_NO_BK_BRACES)
-                      goto unfetch_interval;
-                    else
-                      return REG_EBRACE;
-                  }
-
-                GET_UNSIGNED_NUMBER (lower_bound);
-
-                if (c == ',')
-                  {
-                    GET_UNSIGNED_NUMBER (upper_bound);
-                    if (upper_bound < 0) upper_bound = RE_DUP_MAX;
-                  }
-                else
-                  /* Interval such as `{1}' => match exactly once. */
-                  upper_bound = lower_bound;
-
-                if (lower_bound < 0 || upper_bound > RE_DUP_MAX
-                    || lower_bound > upper_bound)
-                  {
-                    if (syntax & RE_NO_BK_BRACES)
-                      goto unfetch_interval;
-                    else 
-                      return REG_BADBR;
-                  }
-
-                if (!(syntax & RE_NO_BK_BRACES)) 
-                  {
-                    if (c != '\\') return REG_EBRACE;
-
-                    PATFETCH (c);
-                  }
-
-                if (c != '}')
-                  {
-                    if (syntax & RE_NO_BK_BRACES)
-                      goto unfetch_interval;
-                    else 
-                      return REG_BADBR;
-                  }
-
-                /* We just parsed a valid interval.  */
-
-                /* If it's invalid to have no preceding re.  */
-                if (!laststart)
-                  {
-                    if (syntax & RE_CONTEXT_INVALID_OPS)
-                      return REG_BADRPT;
-                    else if (syntax & RE_CONTEXT_INDEP_OPS)
-                      laststart = b;
-                    else
-                      goto unfetch_interval;
-                  }
-
-                /* If the upper bound is zero, don't want to succeed at
-                   all; jump from `laststart' to `b + 3', which will be
-                   the end of the buffer after we insert the jump.  */
-                 if (upper_bound == 0)
-                   {
-                     GET_BUFFER_SPACE (3);
-                     INSERT_JUMP (jump, laststart, b + 3);
-                     b += 3;
-                   }
-
-                 /* Otherwise, we have a nontrivial interval.  When
-                    we're all done, the pattern will look like:
-                      set_number_at <jump count> <upper bound>
-                      set_number_at <succeed_n count> <lower bound>
-                      succeed_n <after jump addr> <succed_n count>
-                      <body of loop>
-                      jump_n <succeed_n addr> <jump count>
-                    (The upper bound and `jump_n' are omitted if
-                    `upper_bound' is 1, though.)  */
-                 else 
-                   { /* If the upper bound is > 1, we need to insert
-                        more at the end of the loop.  */
-                     unsigned nbytes = 10 + (upper_bound > 1) * 10;
-
-                     GET_BUFFER_SPACE (nbytes);
-
-                     /* Initialize lower bound of the `succeed_n', even
-                        though it will be set during matching by its
-                        attendant `set_number_at' (inserted next),
-                        because `re_compile_fastmap' needs to know.
-                        Jump to the `jump_n' we might insert below.  */
-                     INSERT_JUMP2 (succeed_n, laststart,
-                                   b + 5 + (upper_bound > 1) * 5,
-                                   lower_bound);
-                     b += 5;
-
-                     /* Code to initialize the lower bound.  Insert 
-                        before the `succeed_n'.  The `5' is the last two
-                        bytes of this `set_number_at', plus 3 bytes of
-                        the following `succeed_n'.  */
-                     insert_op2 (set_number_at, laststart, 5, lower_bound, b);
-                     b += 5;
-
-                     if (upper_bound > 1)
-                       { /* More than one repetition is allowed, so
-                            append a backward jump to the `succeed_n'
-                            that starts this interval.
-                            
-                            When we've reached this during matching,
-                            we'll have matched the interval once, so
-                            jump back only `upper_bound - 1' times.  */
-                         STORE_JUMP2 (jump_n, b, laststart + 5,
-                                      upper_bound - 1);
-                         b += 5;
-
-                         /* The location we want to set is the second
-                            parameter of the `jump_n'; that is `b-2' as
-                            an absolute address.  `laststart' will be
-                            the `set_number_at' we're about to insert;
-                            `laststart+3' the number to set, the source
-                            for the relative address.  But we are
-                            inserting into the middle of the pattern --
-                            so everything is getting moved up by 5.
-                            Conclusion: (b - 2) - (laststart + 3) + 5,
-                            i.e., b - laststart.
-                            
-                            We insert this at the beginning of the loop
-                            so that if we fail during matching, we'll
-                            reinitialize the bounds.  */
-                         insert_op2 (set_number_at, laststart, b - laststart,
-                                     upper_bound - 1, b);
-                         b += 5;
-                       }
-                   }
-                pending_exact = 0;
-                beg_interval = NULL;
-              }
-              break;
-
-            unfetch_interval:
-              /* If an invalid interval, match the characters as literals.  */
-               assert (beg_interval);
-               p = beg_interval;
-               beg_interval = NULL;
-
-               /* normal_char and normal_backslash need `c'.  */
-               PATFETCH (c);   
-
-               if (!(syntax & RE_NO_BK_BRACES))
-                 {
-                   if (p > pattern  &&  p[-1] == '\\')
-                     goto normal_backslash;
-                 }
-               goto normal_char;
-
-#ifdef emacs
-            /* There is no way to specify the before_dot and after_dot
-               operators.  rms says this is ok.  --karl  */
-            case '=':
-              BUF_PUSH (at_dot);
-              break;
-
-            case 's':  
-              laststart = b;
-              PATFETCH (c);
-              BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]);
-              break;
-
-            case 'S':
-              laststart = b;
-              PATFETCH (c);
-              BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]);
-              break;
-#endif /* emacs */
-
-
-            case 'w':
-              laststart = b;
-              BUF_PUSH (wordchar);
-              break;
-
-
-            case 'W':
-              laststart = b;
-              BUF_PUSH (notwordchar);
-              break;
-
-
-            case '<':
-              BUF_PUSH (wordbeg);
-              break;
-
-            case '>':
-              BUF_PUSH (wordend);
-              break;
-
-            case 'b':
-              BUF_PUSH (wordbound);
-              break;
-
-            case 'B':
-              BUF_PUSH (notwordbound);
-              break;
-
-            case '`':
-              BUF_PUSH (begbuf);
-              break;
-
-            case '\'':
-              BUF_PUSH (endbuf);
-              break;
-
-            case '1': case '2': case '3': case '4': case '5':
-            case '6': case '7': case '8': case '9':
-              if (syntax & RE_NO_BK_REFS)
-                goto normal_char;
-
-              c1 = c - '0';
-
-              if (c1 > regnum)
-                return REG_ESUBREG;
-
-              /* Can't back reference to a subexpression if inside of it.  */
-              if (group_in_compile_stack (compile_stack, c1))
-                goto normal_char;
-
-              laststart = b;
-              BUF_PUSH_2 (duplicate, c1);
-              break;
-
-
-            case '+':
-            case '?':
-              if (syntax & RE_BK_PLUS_QM)
-                goto handle_plus;
-              else
-                goto normal_backslash;
-
-            default:
-            normal_backslash:
-              /* You might think it would be useful for \ to mean
-                 not to translate; but if we don't translate it
-                 it will never match anything.  */
-              c = TRANSLATE (c);
-              goto normal_char;
-            }
-          break;
-
-
-       default:
-        /* Expects the character in `c'.  */
-       normal_char:
-             /* If no exactn currently being built.  */
-          if (!pending_exact 
-
-              /* If last exactn not at current position.  */
-              || pending_exact + *pending_exact + 1 != b
-              
-              /* We have only one byte following the exactn for the count.  */
-             || *pending_exact == (1 << BYTEWIDTH) - 1
-
-              /* If followed by a repetition operator.  */
-              || *p == '*' || *p == '^'
-             || ((syntax & RE_BK_PLUS_QM)
-                 ? *p == '\\' && (p[1] == '+' || p[1] == '?')
-                 : (*p == '+' || *p == '?'))
-             || ((syntax & RE_INTERVALS)
-                  && ((syntax & RE_NO_BK_BRACES)
-                     ? *p == '{'
-                      : (p[0] == '\\' && p[1] == '{'))))
-           {
-             /* Start building a new exactn.  */
-              
-              laststart = b;
-
-             BUF_PUSH_2 (exactn, 0);
-             pending_exact = b - 1;
-            }
-            
-         BUF_PUSH (c);
-          (*pending_exact)++;
-         break;
-        } /* switch (c) */
-    } /* while p != pend */
-
-  
-  /* Through the pattern now.  */
-  
-  if (fixup_alt_jump)
-    STORE_JUMP (jump_past_alt, fixup_alt_jump, b);
-
-  if (!COMPILE_STACK_EMPTY) 
-    return REG_EPAREN;
-
-  free (compile_stack.stack);
-
-  /* We have succeeded; set the length of the buffer.  */
-  bufp->used = b - bufp->buffer;
-
-#ifdef DEBUG
-  if (debug)
-    {
-      DEBUG_PRINT1 ("\nCompiled pattern: ");
-      print_compiled_pattern (bufp);
-    }
-#endif /* DEBUG */
-
-  return REG_NOERROR;
-} /* regex_compile */
-\f
-/* Subroutines for `regex_compile'.  */
-
-/* Store OP at LOC followed by two-byte integer parameter ARG.  */
-
-static void
-store_op1 (op, loc, arg)
-    re_opcode_t op;
-    unsigned char *loc;
-    int arg;
-{
-  *loc = (unsigned char) op;
-  STORE_NUMBER (loc + 1, arg);
-}
-
-
-/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2.  */
-
-static void
-store_op2 (op, loc, arg1, arg2)
-    re_opcode_t op;
-    unsigned char *loc;
-    int arg1, arg2;
-{
-  *loc = (unsigned char) op;
-  STORE_NUMBER (loc + 1, arg1);
-  STORE_NUMBER (loc + 3, arg2);
-}
-
-
-/* Copy the bytes from LOC to END to open up three bytes of space at LOC
-   for OP followed by two-byte integer parameter ARG.  */
-
-static void
-insert_op1 (op, loc, arg, end)
-    re_opcode_t op;
-    unsigned char *loc;
-    int arg;
-    unsigned char *end;    
-{
-  register unsigned char *pfrom = end;
-  register unsigned char *pto = end + 3;
-
-  while (pfrom != loc)
-    *--pto = *--pfrom;
-    
-  store_op1 (op, loc, arg);
-}
-
-
-/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2.  */
-
-static void
-insert_op2 (op, loc, arg1, arg2, end)
-    re_opcode_t op;
-    unsigned char *loc;
-    int arg1, arg2;
-    unsigned char *end;    
-{
-  register unsigned char *pfrom = end;
-  register unsigned char *pto = end + 5;
-
-  while (pfrom != loc)
-    *--pto = *--pfrom;
-    
-  store_op2 (op, loc, arg1, arg2);
-}
-
-
-/* P points to just after a ^ in PATTERN.  Return true if that ^ comes
-   after an alternative or a begin-subexpression.  We assume there is at
-   least one character before the ^.  */
-
-static boolean
-at_begline_loc_p (pattern, p, syntax)
-    const char *pattern, *p;
-    reg_syntax_t syntax;
-{
-  const char *prev = p - 2;
-  boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\';
-  
-  return
-       /* After a subexpression?  */
-       (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash))
-       /* After an alternative?  */
-    || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash));
-}
-
-
-/* The dual of at_begline_loc_p.  This one is for $.  We assume there is
-   at least one character after the $, i.e., `P < PEND'.  */
-
-static boolean
-at_endline_loc_p (p, pend, syntax)
-    const char *p, *pend;
-    int syntax;
-{
-  const char *next = p;
-  boolean next_backslash = *next == '\\';
-  const char *next_next = p + 1 < pend ? p + 1 : NULL;
-  
-  return
-       /* Before a subexpression?  */
-       (syntax & RE_NO_BK_PARENS ? *next == ')'
-        : next_backslash && next_next && *next_next == ')')
-       /* Before an alternative?  */
-    || (syntax & RE_NO_BK_VBAR ? *next == '|'
-        : next_backslash && next_next && *next_next == '|');
-}
-
-
-/* Returns true if REGNUM is in one of COMPILE_STACK's elements and 
-   false if it's not.  */
-
-static boolean
-group_in_compile_stack (compile_stack, regnum)
-    compile_stack_type compile_stack;
-    regnum_t regnum;
-{
-  int this_element;
-
-  for (this_element = compile_stack.avail - 1;  
-       this_element >= 0; 
-       this_element--)
-    if (compile_stack.stack[this_element].regnum == regnum)
-      return true;
-
-  return false;
-}
-
-
-/* Read the ending character of a range (in a bracket expression) from the
-   uncompiled pattern *P_PTR (which ends at PEND).  We assume the
-   starting character is in `P[-2]'.  (`P[-1]' is the character `-'.)
-   Then we set the translation of all bits between the starting and
-   ending characters (inclusive) in the compiled pattern B.
-   
-   Return an error code.
-   
-   We use these short variable names so we can use the same macros as
-   `regex_compile' itself.  */
-
-static reg_errcode_t
-compile_range (p_ptr, pend, translate, syntax, b)
-    const char **p_ptr, *pend;
-    char *translate;
-    reg_syntax_t syntax;
-    unsigned char *b;
-{
-  unsigned this_char;
-
-  const char *p = *p_ptr;
-  int range_start, range_end;
-  
-  if (p == pend)
-    return REG_ERANGE;
-
-  /* Even though the pattern is a signed `char *', we need to fetch
-     with unsigned char *'s; if the high bit of the pattern character
-     is set, the range endpoints will be negative if we fetch using a
-     signed char *.
-
-     We also want to fetch the endpoints without translating them; the 
-     appropriate translation is done in the bit-setting loop below.  */
-  range_start = ((unsigned char *) p)[-2];
-  range_end   = ((unsigned char *) p)[0];
-
-  /* Have to increment the pointer into the pattern string, so the
-     caller isn't still at the ending character.  */
-  (*p_ptr)++;
-
-  /* If the start is after the end, the range is empty.  */
-  if (range_start > range_end)
-    return syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR;
-
-  /* Here we see why `this_char' has to be larger than an `unsigned
-     char' -- the range is inclusive, so if `range_end' == 0xff
-     (assuming 8-bit characters), we would otherwise go into an infinite
-     loop, since all characters <= 0xff.  */
-  for (this_char = range_start; this_char <= range_end; this_char++)
-    {
-      SET_LIST_BIT (TRANSLATE (this_char));
-    }
-  
-  return REG_NOERROR;
-}
-\f
-/* Failure stack declarations and macros; both re_compile_fastmap and
-   re_match_2 use a failure stack.  These have to be macros because of
-   REGEX_ALLOCATE.  */
-   
-
-/* Number of failure points for which to initially allocate space
-   when matching.  If this number is exceeded, we allocate more
-   space, so it is not a hard limit.  */
-#ifndef INIT_FAILURE_ALLOC
-#define INIT_FAILURE_ALLOC 5
-#endif
-
-/* Roughly the maximum number of failure points on the stack.  Would be
-   exactly that if always used MAX_FAILURE_SPACE each time we failed.
-   This is a variable only so users of regex can assign to it; we never
-   change it ourselves.  */
-int re_max_failures = 2000;
-
-typedef const unsigned char *fail_stack_elt_t;
-
-typedef struct
-{
-  fail_stack_elt_t *stack;
-  unsigned size;
-  unsigned avail;                      /* Offset of next open position.  */
-} fail_stack_type;
-
-#define FAIL_STACK_EMPTY()     (fail_stack.avail == 0)
-#define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0)
-#define FAIL_STACK_FULL()      (fail_stack.avail == fail_stack.size)
-#define FAIL_STACK_TOP()       (fail_stack.stack[fail_stack.avail])
-
-
-/* Initialize `fail_stack'.  Do `return -2' if the alloc fails.  */
-
-#define INIT_FAIL_STACK()                                              \
-  do {                                                                 \
-    fail_stack.stack = (fail_stack_elt_t *)                            \
-      REGEX_ALLOCATE (INIT_FAILURE_ALLOC * sizeof (fail_stack_elt_t)); \
-                                                                       \
-    if (fail_stack.stack == NULL)                                      \
-      return -2;                                                       \
-                                                                       \
-    fail_stack.size = INIT_FAILURE_ALLOC;                              \
-    fail_stack.avail = 0;                                              \
-  } while (0)
-
-
-/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items.
-
-   Return 1 if succeeds, and 0 if either ran out of memory
-   allocating space for it or it was already too large.  
-   
-   REGEX_REALLOCATE requires `destination' be declared.   */
-
-#define DOUBLE_FAIL_STACK(fail_stack)                                  \
-  ((fail_stack).size > re_max_failures * MAX_FAILURE_ITEMS             \
-   ? 0                                                                 \
-   : ((fail_stack).stack = (fail_stack_elt_t *)                                \
-        REGEX_REALLOCATE ((fail_stack).stack,                          \
-          (fail_stack).size * sizeof (fail_stack_elt_t),               \
-          ((fail_stack).size << 1) * sizeof (fail_stack_elt_t)),       \
-                                                                       \
-      (fail_stack).stack == NULL                                       \
-      ? 0                                                              \
-      : ((fail_stack).size <<= 1,                                      \
-         1)))
-
-
-/* Push PATTERN_OP on FAIL_STACK. 
-
-   Return 1 if was able to do so and 0 if ran out of memory allocating
-   space to do so.  */
-#define PUSH_PATTERN_OP(pattern_op, fail_stack)                                \
-  ((FAIL_STACK_FULL ()                                                 \
-    && !DOUBLE_FAIL_STACK (fail_stack))                                        \
-    ? 0                                                                        \
-    : ((fail_stack).stack[(fail_stack).avail++] = pattern_op,          \
-       1))
-
-/* This pushes an item onto the failure stack.  Must be a four-byte
-   value.  Assumes the variable `fail_stack'.  Probably should only
-   be called from within `PUSH_FAILURE_POINT'.  */
-#define PUSH_FAILURE_ITEM(item)                                                \
-  fail_stack.stack[fail_stack.avail++] = (fail_stack_elt_t) item
-
-/* The complement operation.  Assumes `fail_stack' is nonempty.  */
-#define POP_FAILURE_ITEM() fail_stack.stack[--fail_stack.avail]
-
-/* Used to omit pushing failure point id's when we're not debugging.  */
-#ifdef DEBUG
-#define DEBUG_PUSH PUSH_FAILURE_ITEM
-#define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_ITEM ()
-#else
-#define DEBUG_PUSH(item)
-#define DEBUG_POP(item_addr)
-#endif
-
-
-/* Push the information about the state we will need
-   if we ever fail back to it.  
-   
-   Requires variables fail_stack, regstart, regend, reg_info, and
-   num_regs be declared.  DOUBLE_FAIL_STACK requires `destination' be
-   declared.
-   
-   Does `return FAILURE_CODE' if runs out of memory.  */
-
-#define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code)  \
-  do {                                                                 \
-    char *destination;                                                 \
-    /* Must be int, so when we don't save any registers, the arithmetic        \
-       of 0 + -1 isn't done as unsigned.  */                           \
-    int this_reg;                                                      \
-                                                                       \
-    DEBUG_STATEMENT (failure_id++);                                    \
-    DEBUG_STATEMENT (nfailure_points_pushed++);                                \
-    DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id);          \
-    DEBUG_PRINT2 ("  Before push, next avail: %d\n", (fail_stack).avail);\
-    DEBUG_PRINT2 ("                     size: %d\n", (fail_stack).size);\
-                                                                       \
-    DEBUG_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);          \
-    DEBUG_PRINT2 ("     available: %d\n", REMAINING_AVAIL_SLOTS);      \
-                                                                       \
-    /* Ensure we have enough space allocated for what we will push.  */        \
-    while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS)                  \
-      {                                                                        \
-        if (!DOUBLE_FAIL_STACK (fail_stack))                   \
-          return failure_code;                                         \
-                                                                       \
-        DEBUG_PRINT2 ("\n  Doubled stack; size now: %d\n",             \
-                      (fail_stack).size);                              \
-        DEBUG_PRINT2 ("  slots available: %d\n", REMAINING_AVAIL_SLOTS);\
-      }                                                                        \
-                                                                       \
-    /* Push the info, starting with the registers.  */                 \
-    DEBUG_PRINT1 ("\n");                                               \
-                                                                       \
-    for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \
-         this_reg++)                                                   \
-      {                                                                        \
-       DEBUG_PRINT2 ("  Pushing reg: %d\n", this_reg);                 \
-        DEBUG_STATEMENT (num_regs_pushed++);                           \
-                                                                       \
-       DEBUG_PRINT2 ("    start: 0x%x\n", regstart[this_reg]);         \
-        PUSH_FAILURE_ITEM (regstart[this_reg]);                                \
-                                                                        \
-       DEBUG_PRINT2 ("    end: 0x%x\n", regend[this_reg]);             \
-        PUSH_FAILURE_ITEM (regend[this_reg]);                          \
-                                                                       \
-       DEBUG_PRINT2 ("    info: 0x%x\n      ", reg_info[this_reg]);    \
-        DEBUG_PRINT2 (" match_null=%d",                                        \
-                      REG_MATCH_NULL_STRING_P (reg_info[this_reg]));   \
-        DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));   \
-        DEBUG_PRINT2 (" matched_something=%d",                         \
-                      MATCHED_SOMETHING (reg_info[this_reg]));         \
-        DEBUG_PRINT2 (" ever_matched=%d",                              \
-                      EVER_MATCHED_SOMETHING (reg_info[this_reg]));    \
-       DEBUG_PRINT1 ("\n");                                            \
-        PUSH_FAILURE_ITEM (reg_info[this_reg].word);                   \
-      }                                                                        \
-                                                                       \
-    DEBUG_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg);\
-    PUSH_FAILURE_ITEM (lowest_active_reg);                             \
-                                                                       \
-    DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);\
-    PUSH_FAILURE_ITEM (highest_active_reg);                            \
-                                                                       \
-    DEBUG_PRINT2 ("  Pushing pattern 0x%x: ", pattern_place);          \
-    DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);          \
-    PUSH_FAILURE_ITEM (pattern_place);                                 \
-                                                                       \
-    DEBUG_PRINT2 ("  Pushing string 0x%x: `", string_place);           \
-    DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,   \
-                                size2);                                \
-    DEBUG_PRINT1 ("'\n");                                              \
-    PUSH_FAILURE_ITEM (string_place);                                  \
-                                                                       \
-    DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);           \
-    DEBUG_PUSH (failure_id);                                           \
-  } while (0)
-
-/* This is the number of items that are pushed and popped on the stack
-   for each register.  */
-#define NUM_REG_ITEMS  3
-
-/* Individual items aside from the registers.  */
-#ifdef DEBUG
-#define NUM_NONREG_ITEMS 5 /* Includes failure point id.  */
-#else
-#define NUM_NONREG_ITEMS 4
-#endif
-
-/* We push at most this many items on the stack.  */
-#define MAX_FAILURE_ITEMS ((num_regs - 1) * NUM_REG_ITEMS + NUM_NONREG_ITEMS)
-
-/* We actually push this many items.  */
-#define NUM_FAILURE_ITEMS                                              \
-  ((highest_active_reg - lowest_active_reg + 1) * NUM_REG_ITEMS        \
-    + NUM_NONREG_ITEMS)
-
-/* How many items can still be added to the stack without overflowing it.  */
-#define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail)
-
-
-/* Pops what PUSH_FAIL_STACK pushes.
-
-   We restore into the parameters, all of which should be lvalues:
-     STR -- the saved data position.
-     PAT -- the saved pattern position.
-     LOW_REG, HIGH_REG -- the highest and lowest active registers.
-     REGSTART, REGEND -- arrays of string positions.
-     REG_INFO -- array of information about each subexpression.
-   
-   Also assumes the variables `fail_stack' and (if debugging), `bufp',
-   `pend', `string1', `size1', `string2', and `size2'.  */
-
-#define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\
-{                                                                      \
-  DEBUG_STATEMENT (fail_stack_elt_t failure_id;)                       \
-  int this_reg;                                                                \
-  const unsigned char *string_temp;                                    \
-                                                                       \
-  assert (!FAIL_STACK_EMPTY ());                                       \
-                                                                       \
-  /* Remove failure points and point to how many regs pushed.  */      \
-  DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");                               \
-  DEBUG_PRINT2 ("  Before pop, next avail: %d\n", fail_stack.avail);   \
-  DEBUG_PRINT2 ("                    size: %d\n", fail_stack.size);    \
-                                                                       \
-  assert (fail_stack.avail >= NUM_NONREG_ITEMS);                       \
-                                                                       \
-  DEBUG_POP (&failure_id);                                             \
-  DEBUG_PRINT2 ("  Popping failure id: %u\n", failure_id);             \
-                                                                       \
-  /* If the saved string location is NULL, it came from an             \
-     on_failure_keep_string_jump opcode, and we want to throw away the \
-     saved NULL, thus retaining our current position in the string.  */        \
-  string_temp = POP_FAILURE_ITEM ();                                   \
-  if (string_temp != NULL)                                             \
-    str = (const char *) string_temp;                                  \
-                                                                       \
-  DEBUG_PRINT2 ("  Popping string 0x%x: `", str);                      \
-  DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);     \
-  DEBUG_PRINT1 ("'\n");                                                        \
-                                                                       \
-  pat = (unsigned char *) POP_FAILURE_ITEM ();                         \
-  DEBUG_PRINT2 ("  Popping pattern 0x%x: ", pat);                      \
-  DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);                      \
-                                                                       \
-  /* Restore register info.  */                                                \
-  high_reg = (unsigned) POP_FAILURE_ITEM ();                           \
-  DEBUG_PRINT2 ("  Popping high active reg: %d\n", high_reg);          \
-                                                                       \
-  low_reg = (unsigned) POP_FAILURE_ITEM ();                            \
-  DEBUG_PRINT2 ("  Popping  low active reg: %d\n", low_reg);           \
-                                                                       \
-  for (this_reg = high_reg; this_reg >= low_reg; this_reg--)           \
-    {                                                                  \
-      DEBUG_PRINT2 ("    Popping reg: %d\n", this_reg);                        \
-                                                                       \
-      reg_info[this_reg].word = POP_FAILURE_ITEM ();                   \
-      DEBUG_PRINT2 ("      info: 0x%x\n", reg_info[this_reg]);         \
-                                                                       \
-      regend[this_reg] = (const char *) POP_FAILURE_ITEM ();           \
-      DEBUG_PRINT2 ("      end: 0x%x\n", regend[this_reg]);            \
-                                                                       \
-      regstart[this_reg] = (const char *) POP_FAILURE_ITEM ();         \
-      DEBUG_PRINT2 ("      start: 0x%x\n", regstart[this_reg]);                \
-    }                                                                  \
-                                                                       \
-  DEBUG_STATEMENT (nfailure_points_popped++);                          \
-} /* POP_FAILURE_POINT */
-\f
-/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in
-   BUFP.  A fastmap records which of the (1 << BYTEWIDTH) possible
-   characters can start a string that matches the pattern.  This fastmap
-   is used by re_search to skip quickly over impossible starting points.
-
-   The caller must supply the address of a (1 << BYTEWIDTH)-byte data
-   area as BUFP->fastmap.
-   
-   We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in
-   the pattern buffer.
-
-   Returns 0 if we succeed, -2 if an internal error.   */
-
-int
-re_compile_fastmap (bufp)
-     struct re_pattern_buffer *bufp;
-{
-  int j, k;
-  fail_stack_type fail_stack;
-#ifndef REGEX_MALLOC
-  char *destination;
-#endif
-  /* We don't push any register information onto the failure stack.  */
-  unsigned num_regs = 0;
-  
-  register char *fastmap = bufp->fastmap;
-  unsigned char *pattern = bufp->buffer;
-  unsigned long size = bufp->used;
-  const unsigned char *p = pattern;
-  register unsigned char *pend = pattern + size;
-
-  /* Assume that each path through the pattern can be null until
-     proven otherwise.  We set this false at the bottom of switch
-     statement, to which we get only if a particular path doesn't
-     match the empty string.  */
-  boolean path_can_be_null = true;
-
-  /* We aren't doing a `succeed_n' to begin with.  */
-  boolean succeed_n_p = false;
-
-  assert (fastmap != NULL && p != NULL);
-  
-  INIT_FAIL_STACK ();
-  bzero (fastmap, 1 << BYTEWIDTH);  /* Assume nothing's valid.  */
-  bufp->fastmap_accurate = 1;      /* It will be when we're done.  */
-  bufp->can_be_null = 0;
-      
-  while (p != pend || !FAIL_STACK_EMPTY ())
-    {
-      if (p == pend)
-        {
-          bufp->can_be_null |= path_can_be_null;
-          
-          /* Reset for next path.  */
-          path_can_be_null = true;
-          
-          p = fail_stack.stack[--fail_stack.avail];
-       }
-
-      /* We should never be about to go beyond the end of the pattern.  */
-      assert (p < pend);
-      
-#ifdef SWITCH_ENUM_BUG
-      switch ((int) ((re_opcode_t) *p++))
-#else
-      switch ((re_opcode_t) *p++)
-#endif
-       {
-
-        /* I guess the idea here is to simply not bother with a fastmap
-           if a backreference is used, since it's too hard to figure out
-           the fastmap for the corresponding group.  Setting
-           `can_be_null' stops `re_search_2' from using the fastmap, so
-           that is all we do.  */
-       case duplicate:
-         bufp->can_be_null = 1;
-          return 0;
-
-
-      /* Following are the cases which match a character.  These end
-         with `break'.  */
-
-       case exactn:
-          fastmap[p[1]] = 1;
-         break;
-
-
-        case charset:
-          for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
-           if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
-              fastmap[j] = 1;
-         break;
-
-
-       case charset_not:
-         /* Chars beyond end of map must be allowed.  */
-         for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
-            fastmap[j] = 1;
-
-         for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
-           if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
-              fastmap[j] = 1;
-          break;
-
-
-       case wordchar:
-         for (j = 0; j < (1 << BYTEWIDTH); j++)
-           if (SYNTAX (j) == Sword)
-             fastmap[j] = 1;
-         break;
-
-
-       case notwordchar:
-         for (j = 0; j < (1 << BYTEWIDTH); j++)
-           if (SYNTAX (j) != Sword)
-             fastmap[j] = 1;
-         break;
-
-
-        case anychar:
-          /* `.' matches anything ...  */
-         for (j = 0; j < (1 << BYTEWIDTH); j++)
-            fastmap[j] = 1;
-
-          /* ... except perhaps newline.  */
-          if (!(bufp->syntax & RE_DOT_NEWLINE))
-            fastmap['\n'] = 0;
-
-          /* Return if we have already set `can_be_null'; if we have,
-             then the fastmap is irrelevant.  Something's wrong here.  */
-         else if (bufp->can_be_null)
-           return 0;
-
-          /* Otherwise, have to check alternative paths.  */
-         break;
-
-
-#ifdef emacs
-        case syntaxspec:
-         k = *p++;
-         for (j = 0; j < (1 << BYTEWIDTH); j++)
-           if (SYNTAX (j) == (enum syntaxcode) k)
-             fastmap[j] = 1;
-         break;
-
-
-       case notsyntaxspec:
-         k = *p++;
-         for (j = 0; j < (1 << BYTEWIDTH); j++)
-           if (SYNTAX (j) != (enum syntaxcode) k)
-             fastmap[j] = 1;
-         break;
-
-
-      /* All cases after this match the empty string.  These end with
-         `continue'.  */
-
-
-       case before_dot:
-       case at_dot:
-       case after_dot:
-          continue;
-#endif /* not emacs */
-
-
-        case no_op:
-        case begline:
-        case endline:
-       case begbuf:
-       case endbuf:
-       case wordbound:
-       case notwordbound:
-       case wordbeg:
-       case wordend:
-        case push_dummy_failure:
-          continue;
-
-
-       case jump_n:
-        case pop_failure_jump:
-       case maybe_pop_jump:
-       case jump:
-        case jump_past_alt:
-       case dummy_failure_jump:
-          EXTRACT_NUMBER_AND_INCR (j, p);
-         p += j;       
-         if (j > 0)
-           continue;
-            
-          /* Jump backward implies we just went through the body of a
-             loop and matched nothing.  Opcode jumped to should be
-             `on_failure_jump' or `succeed_n'.  Just treat it like an
-             ordinary jump.  For a * loop, it has pushed its failure
-             point already; if so, discard that as redundant.  */
-          if ((re_opcode_t) *p != on_failure_jump
-             && (re_opcode_t) *p != succeed_n)
-           continue;
-
-          p++;
-          EXTRACT_NUMBER_AND_INCR (j, p);
-          p += j;              
-         
-          /* If what's on the stack is where we are now, pop it.  */
-          if (!FAIL_STACK_EMPTY () 
-             && fail_stack.stack[fail_stack.avail - 1] == p)
-            fail_stack.avail--;
-
-          continue;
-
-
-        case on_failure_jump:
-        case on_failure_keep_string_jump:
-       handle_on_failure_jump:
-          EXTRACT_NUMBER_AND_INCR (j, p);
-
-          /* For some patterns, e.g., `(a?)?', `p+j' here points to the
-             end of the pattern.  We don't want to push such a point,
-             since when we restore it above, entering the switch will
-             increment `p' past the end of the pattern.  We don't need
-             to push such a point since we obviously won't find any more
-             fastmap entries beyond `pend'.  Such a pattern can match
-             the null string, though.  */
-          if (p + j < pend)
-            {
-              if (!PUSH_PATTERN_OP (p + j, fail_stack))
-                return -2;
-            }
-          else
-            bufp->can_be_null = 1;
-
-          if (succeed_n_p)
-            {
-              EXTRACT_NUMBER_AND_INCR (k, p);  /* Skip the n.  */
-              succeed_n_p = false;
-           }
-
-          continue;
-
-
-       case succeed_n:
-          /* Get to the number of times to succeed.  */
-          p += 2;              
-
-          /* Increment p past the n for when k != 0.  */
-          EXTRACT_NUMBER_AND_INCR (k, p);
-          if (k == 0)
-           {
-              p -= 4;
-             succeed_n_p = true;  /* Spaghetti code alert.  */
-              goto handle_on_failure_jump;
-            }
-          continue;
-
-
-       case set_number_at:
-          p += 4;
-          continue;
-
-
-       case start_memory:
-        case stop_memory:
-         p += 2;
-         continue;
-
-
-       default:
-          abort (); /* We have listed all the cases.  */
-        } /* switch *p++ */
-
-      /* Getting here means we have found the possible starting
-         characters for one path of the pattern -- and that the empty
-         string does not match.  We need not follow this path further.
-         Instead, look at the next alternative (remembered on the
-         stack), or quit if no more.  The test at the top of the loop
-         does these things.  */
-      path_can_be_null = false;
-      p = pend;
-    } /* while p */
-
-  /* Set `can_be_null' for the last path (also the first path, if the
-     pattern is empty).  */
-  bufp->can_be_null |= path_can_be_null;
-  return 0;
-} /* re_compile_fastmap */
-\f
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
-   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
-   this memory for recording register information.  STARTS and ENDS
-   must be allocated using the malloc library routine, and must each
-   be at least NUM_REGS * sizeof (regoff_t) bytes long.
-
-   If NUM_REGS == 0, then subsequent matches should allocate their own
-   register data.
-
-   Unless this function is called, the first search or match using
-   PATTERN_BUFFER will allocate its own register data, without
-   freeing the old data.  */
-
-void
-re_set_registers (bufp, regs, num_regs, starts, ends)
-    struct re_pattern_buffer *bufp;
-    struct re_registers *regs;
-    unsigned num_regs;
-    regoff_t *starts, *ends;
-{
-  if (num_regs)
-    {
-      bufp->regs_allocated = REGS_REALLOCATE;
-      regs->num_regs = num_regs;
-      regs->start = starts;
-      regs->end = ends;
-    }
-  else
-    {
-      bufp->regs_allocated = REGS_UNALLOCATED;
-      regs->num_regs = 0;
-      regs->start = regs->end = (regoff_t) 0;
-    }
-}
-\f
-/* Searching routines.  */
-
-/* Like re_search_2, below, but only one string is specified, and
-   doesn't let you say where to stop matching. */
-
-int
-re_search (bufp, string, size, startpos, range, regs)
-     struct re_pattern_buffer *bufp;
-     const char *string;
-     int size, startpos, range;
-     struct re_registers *regs;
-{
-  return re_search_2 (bufp, NULL, 0, string, size, startpos, range, 
-                     regs, size);
-}
-
-
-/* Using the compiled pattern in BUFP->buffer, first tries to match the
-   virtual concatenation of STRING1 and STRING2, starting first at index
-   STARTPOS, then at STARTPOS + 1, and so on.
-   
-   STRING1 and STRING2 have length SIZE1 and SIZE2, respectively.
-   
-   RANGE is how far to scan while trying to match.  RANGE = 0 means try
-   only at STARTPOS; in general, the last start tried is STARTPOS +
-   RANGE.
-   
-   In REGS, return the indices of the virtual concatenation of STRING1
-   and STRING2 that matched the entire BUFP->buffer and its contained
-   subexpressions.
-   
-   Do not consider matching one past the index STOP in the virtual
-   concatenation of STRING1 and STRING2.
-
-   We return either the position in the strings at which the match was
-   found, -1 if no match, or -2 if error (such as failure
-   stack overflow).  */
-
-int
-re_search_2 (bufp, string1, size1, string2, size2, startpos, range, regs, stop)
-     struct re_pattern_buffer *bufp;
-     const char *string1, *string2;
-     int size1, size2;
-     int startpos;
-     int range;
-     struct re_registers *regs;
-     int stop;
-{
-  int val;
-  register char *fastmap = bufp->fastmap;
-  register char *translate = bufp->translate;
-  int total_size = size1 + size2;
-  int endpos = startpos + range;
-
-  /* Check for out-of-range STARTPOS.  */
-  if (startpos < 0 || startpos > total_size)
-    return -1;
-    
-  /* Fix up RANGE if it might eventually take us outside
-     the virtual concatenation of STRING1 and STRING2.  */
-  if (endpos < -1)
-    range = -1 - startpos;
-  else if (endpos > total_size)
-    range = total_size - startpos;
-
-  /* If the search isn't to be a backwards one, don't waste time in a
-     search for a pattern that must be anchored.  */
-  if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == begbuf && range > 0)
-    {
-      if (startpos > 0)
-       return -1;
-      else
-       range = 1;
-    }
-
-  /* Update the fastmap now if not correct already.  */
-  if (fastmap && !bufp->fastmap_accurate)
-    if (re_compile_fastmap (bufp) == -2)
-      return -2;
-  
-  /* Loop through the string, looking for a place to start matching.  */
-  for (;;)
-    { 
-      /* If a fastmap is supplied, skip quickly over characters that
-         cannot be the start of a match.  If the pattern can match the
-         null string, however, we don't need to skip characters; we want
-         the first null string.  */
-      if (fastmap && startpos < total_size && !bufp->can_be_null)
-       {
-         if (range > 0)        /* Searching forwards.  */
-           {
-             register const char *d;
-             register int lim = 0;
-             int irange = range;
-
-              if (startpos < size1 && startpos + range >= size1)
-                lim = range - (size1 - startpos);
-
-             d = (startpos >= size1 ? string2 - size1 : string1) + startpos;
-   
-              /* Written out as an if-else to avoid testing `translate'
-                 inside the loop.  */
-             if (translate)
-                while (range > lim
-                       && !fastmap[(unsigned char)
-                                  translate[(unsigned char) *d++]])
-                  range--;
-             else
-                while (range > lim && !fastmap[(unsigned char) *d++])
-                  range--;
-
-             startpos += irange - range;
-           }
-         else                          /* Searching backwards.  */
-           {
-             register char c = (size1 == 0 || startpos >= size1
-                                 ? string2[startpos - size1] 
-                                 : string1[startpos]);
-
-             if (!fastmap[(unsigned char) TRANSLATE (c)])
-               goto advance;
-           }
-       }
-
-      /* If can't match the null string, and that's all we have left, fail.  */
-      if (range >= 0 && startpos == total_size && fastmap
-          && !bufp->can_be_null)
-       return -1;
-
-      val = re_match_2 (bufp, string1, size1, string2, size2,
-                       startpos, regs, stop);
-      if (val >= 0)
-       return startpos;
-        
-      if (val == -2)
-       return -2;
-
-    advance:
-      if (!range) 
-        break;
-      else if (range > 0) 
-        {
-          range--; 
-          startpos++;
-        }
-      else
-        {
-          range++; 
-          startpos--;
-        }
-    }
-  return -1;
-} /* re_search_2 */
-\f
-/* Declarations and macros for re_match_2.  */
-
-static int bcmp_translate ();
-static boolean alt_match_null_string_p (),
-               common_op_match_null_string_p (),
-               group_match_null_string_p ();
-
-/* Structure for per-register (a.k.a. per-group) information.
-   This must not be longer than one word, because we push this value
-   onto the failure stack.  Other register information, such as the
-   starting and ending positions (which are addresses), and the list of
-   inner groups (which is a bits list) are maintained in separate
-   variables.  
-   
-   We are making a (strictly speaking) nonportable assumption here: that
-   the compiler will pack our bit fields into something that fits into
-   the type of `word', i.e., is something that fits into one item on the
-   failure stack.  */
-typedef union
-{
-  fail_stack_elt_t word;
-  struct
-  {
-      /* This field is one if this group can match the empty string,
-         zero if not.  If not yet determined,  `MATCH_NULL_UNSET_VALUE'.  */
-#define MATCH_NULL_UNSET_VALUE 3
-    unsigned match_null_string_p : 2;
-    unsigned is_active : 1;
-    unsigned matched_something : 1;
-    unsigned ever_matched_something : 1;
-  } bits;
-} register_info_type;
-
-#define REG_MATCH_NULL_STRING_P(R)  ((R).bits.match_null_string_p)
-#define IS_ACTIVE(R)  ((R).bits.is_active)
-#define MATCHED_SOMETHING(R)  ((R).bits.matched_something)
-#define EVER_MATCHED_SOMETHING(R)  ((R).bits.ever_matched_something)
-
-
-/* Call this when have matched a real character; it sets `matched' flags
-   for the subexpressions which we are currently inside.  Also records
-   that those subexprs have matched.  */
-#define SET_REGS_MATCHED()                                             \
-  do                                                                   \
-    {                                                                  \
-      unsigned r;                                                      \
-      for (r = lowest_active_reg; r <= highest_active_reg; r++)                \
-        {                                                              \
-          MATCHED_SOMETHING (reg_info[r])                              \
-            = EVER_MATCHED_SOMETHING (reg_info[r])                     \
-            = 1;                                                       \
-        }                                                              \
-    }                                                                  \
-  while (0)
-
-
-/* This converts PTR, a pointer into one of the search strings `string1'
-   and `string2' into an offset from the beginning of that string.  */
-#define POINTER_TO_OFFSET(ptr)                                         \
-  (FIRST_STRING_P (ptr) ? (ptr) - string1 : (ptr) - string2 + size1)
-
-/* Registers are set to a sentinel when they haven't yet matched.  */
-#define REG_UNSET_VALUE ((char *) -1)
-#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
-
-
-/* Macros for dealing with the split strings in re_match_2.  */
-
-#define MATCHING_IN_FIRST_STRING  (dend == end_match_1)
-
-/* Call before fetching a character with *d.  This switches over to
-   string2 if necessary.  */
-#define PREFETCH()                                                     \
-  while (d == dend)                                                    \
-    {                                                                  \
-      /* End of string2 => fail.  */                                   \
-      if (dend == end_match_2)                                                 \
-        goto fail;                                                     \
-      /* End of string1 => advance to string2.  */                     \
-      d = string2;                                                     \
-      dend = end_match_2;                                              \
-    }
-
-
-/* Test if at very beginning or at very end of the virtual concatenation
-   of `string1' and `string2'.  If only one string, it's `string2'.  */
-#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2)
-#define AT_STRINGS_END(d) ((d) == end2)        
-
-
-/* Test if D points to a character which is word-constituent.  We have
-   two special cases to check for: if past the end of string1, look at
-   the first character in string2; and if before the beginning of
-   string2, look at the last character in string1.  */
-#define WORDCHAR_P(d)                                                  \
-  (SYNTAX ((d) == end1 ? *string2                                      \
-           : (d) == string2 - 1 ? *(end1 - 1) : *(d))                  \
-   == Sword)
-
-/* Test if the character before D and the one at D differ with respect
-   to being word-constituent.  */
-#define AT_WORD_BOUNDARY(d)                                            \
-  (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)                            \
-   || WORDCHAR_P (d - 1) != WORDCHAR_P (d))
-
-
-/* Free everything we malloc.  */
-#ifdef REGEX_MALLOC
-#define FREE_VAR(var) if (var) free (var); var = NULL
-#define FREE_VARIABLES()                                               \
-  do {                                                                 \
-    FREE_VAR (fail_stack.stack);                                       \
-    FREE_VAR (regstart);                                               \
-    FREE_VAR (regend);                                                 \
-    FREE_VAR (old_regstart);                                           \
-    FREE_VAR (old_regend);                                             \
-    FREE_VAR (best_regstart);                                          \
-    FREE_VAR (best_regend);                                            \
-    FREE_VAR (reg_info);                                               \
-    FREE_VAR (reg_dummy);                                              \
-    FREE_VAR (reg_info_dummy);                                         \
-  } while (0)
-#else /* not REGEX_MALLOC */
-/* Some MIPS systems (at least) want this to free alloca'd storage.  */
-#define FREE_VARIABLES() alloca (0)
-#endif /* not REGEX_MALLOC */
-
-
-/* These values must meet several constraints.  They must not be valid
-   register values; since we have a limit of 255 registers (because
-   we use only one byte in the pattern for the register number), we can
-   use numbers larger than 255.  They must differ by 1, because of
-   NUM_FAILURE_ITEMS above.  And the value for the lowest register must
-   be larger than the value for the highest register, so we do not try
-   to actually save any registers when none are active.  */
-#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH)
-#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1)
-\f
-/* Matching routines.  */
-
-#ifndef emacs   /* Emacs never uses this.  */
-/* re_match is like re_match_2 except it takes only a single string.  */
-
-int
-re_match (bufp, string, size, pos, regs)
-     struct re_pattern_buffer *bufp;
-     const char *string;
-     int size, pos;
-     struct re_registers *regs;
- {
-  return re_match_2 (bufp, NULL, 0, string, size, pos, regs, size); 
-}
-#endif /* not emacs */
-
-
-/* re_match_2 matches the compiled pattern in BUFP against the
-   the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1
-   and SIZE2, respectively).  We start matching at POS, and stop
-   matching at STOP.
-   
-   If REGS is non-null and the `no_sub' field of BUFP is nonzero, we
-   store offsets for the substring each group matched in REGS.  See the
-   documentation for exactly how many groups we fill.
-
-   We return -1 if no match, -2 if an internal error (such as the
-   failure stack overflowing).  Otherwise, we return the length of the
-   matched substring.  */
-
-int
-re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)
-     struct re_pattern_buffer *bufp;
-     const char *string1, *string2;
-     int size1, size2;
-     int pos;
-     struct re_registers *regs;
-     int stop;
-{
-  /* General temporaries.  */
-  int mcnt;
-  unsigned char *p1;
-
-  /* Just past the end of the corresponding string.  */
-  const char *end1, *end2;
-
-  /* Pointers into string1 and string2, just past the last characters in
-     each to consider matching.  */
-  const char *end_match_1, *end_match_2;
-
-  /* Where we are in the data, and the end of the current string.  */
-  const char *d, *dend;
-  
-  /* Where we are in the pattern, and the end of the pattern.  */
-  unsigned char *p = bufp->buffer;
-  register unsigned char *pend = p + bufp->used;
-
-  /* We use this to map every character in the string.  */
-  char *translate = bufp->translate;
-
-  /* Failure point stack.  Each place that can handle a failure further
-     down the line pushes a failure point on this stack.  It consists of
-     restart, regend, and reg_info for all registers corresponding to
-     the subexpressions we're currently inside, plus the number of such
-     registers, and, finally, two char *'s.  The first char * is where
-     to resume scanning the pattern; the second one is where to resume
-     scanning the strings.  If the latter is zero, the failure point is
-     a ``dummy''; if a failure happens and the failure point is a dummy,
-     it gets discarded and the next next one is tried.  */
-  fail_stack_type fail_stack;
-#ifdef DEBUG
-  static unsigned failure_id = 0;
-  unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0;
-#endif
-
-  /* We fill all the registers internally, independent of what we
-     return, for use in backreferences.  The number here includes
-     an element for register zero.  */
-  unsigned num_regs = bufp->re_nsub + 1;
-  
-  /* The currently active registers.  */
-  unsigned lowest_active_reg = NO_LOWEST_ACTIVE_REG;
-  unsigned highest_active_reg = NO_HIGHEST_ACTIVE_REG;
-
-  /* Information on the contents of registers. These are pointers into
-     the input strings; they record just what was matched (on this
-     attempt) by a subexpression part of the pattern, that is, the
-     regnum-th regstart pointer points to where in the pattern we began
-     matching and the regnum-th regend points to right after where we
-     stopped matching the regnum-th subexpression.  (The zeroth register
-     keeps track of what the whole pattern matches.)  */
-  const char **regstart = NULL, **regend = NULL;
-
-  /* If a group that's operated upon by a repetition operator fails to
-     match anything, then the register for its start will need to be
-     restored because it will have been set to wherever in the string we
-     are when we last see its open-group operator.  Similarly for a
-     register's end.  */
-  const char **old_regstart = NULL, **old_regend = NULL;
-
-  /* The is_active field of reg_info helps us keep track of which (possibly
-     nested) subexpressions we are currently in. The matched_something
-     field of reg_info[reg_num] helps us tell whether or not we have
-     matched any of the pattern so far this time through the reg_num-th
-     subexpression.  These two fields get reset each time through any
-     loop their register is in.  */
-  register_info_type *reg_info = NULL;
-
-  /* The following record the register info as found in the above
-     variables when we find a match better than any we've seen before. 
-     This happens as we backtrack through the failure points, which in
-     turn happens only if we have not yet matched the entire string. */
-  unsigned best_regs_set = false;
-  const char **best_regstart = NULL, **best_regend = NULL;
-  /* Logically, this is `best_regend[0]'.  But we don't want to have to
-     allocate space for that if we're not allocating space for anything
-     else (see below).  Also, we never need info about register 0 for
-     any of the other register vectors, and it seems rather a kludge to
-     treat `best_regend' differently than the rest.  So we keep track of
-     the end of the best match so far in a separate variable.  We
-     initialize this to NULL so that when we backtrack the first time
-     and need to test it, it's not garbage.  */
-  const char *match_end = NULL;
-
-  /* Used when we pop values we don't care about.  */
-  const char **reg_dummy = NULL;
-  register_info_type *reg_info_dummy = NULL;
-
-#ifdef DEBUG
-  /* Counts the total number of registers pushed.  */
-  unsigned num_regs_pushed = 0;        
-#endif
-
-  DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
-  
-  INIT_FAIL_STACK ();
-  
-  /* Do not bother to initialize all the register variables if there are
-     no groups in the pattern, as it takes a fair amount of time.  If
-     there are groups, we include space for register 0 (the whole
-     pattern), even though we never use it, since it simplifies the
-     array indexing.  We should fix this.  */
-  if (bufp->re_nsub)
-    {
-      regstart = REGEX_TALLOC (num_regs, const char *);
-      regend = REGEX_TALLOC (num_regs, const char *);
-      old_regstart = REGEX_TALLOC (num_regs, const char *);
-      old_regend = REGEX_TALLOC (num_regs, const char *);
-      best_regstart = REGEX_TALLOC (num_regs, const char *);
-      best_regend = REGEX_TALLOC (num_regs, const char *);
-      reg_info = REGEX_TALLOC (num_regs, register_info_type);
-      reg_dummy = REGEX_TALLOC (num_regs, const char *);
-      reg_info_dummy = REGEX_TALLOC (num_regs, register_info_type);
-
-      if (!(regstart && regend && old_regstart && old_regend && reg_info 
-            && best_regstart && best_regend && reg_dummy && reg_info_dummy)) 
-        {
-          FREE_VARIABLES ();
-          return -2;
-        }
-    }
-#ifdef REGEX_MALLOC
-  else
-    {
-      /* We must initialize all our variables to NULL, so that
-         `FREE_VARIABLES' doesn't try to free them.  */
-      regstart = regend = old_regstart = old_regend = best_regstart
-        = best_regend = reg_dummy = NULL;
-      reg_info = reg_info_dummy = (register_info_type *) NULL;
-    }
-#endif /* REGEX_MALLOC */
-
-  /* The starting position is bogus.  */
-  if (pos < 0 || pos > size1 + size2)
-    {
-      FREE_VARIABLES ();
-      return -1;
-    }
-    
-  /* Initialize subexpression text positions to -1 to mark ones that no
-     start_memory/stop_memory has been seen for. Also initialize the
-     register information struct.  */
-  for (mcnt = 1; mcnt < num_regs; mcnt++)
-    {
-      regstart[mcnt] = regend[mcnt] 
-        = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE;
-        
-      REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
-      IS_ACTIVE (reg_info[mcnt]) = 0;
-      MATCHED_SOMETHING (reg_info[mcnt]) = 0;
-      EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
-    }
-  
-  /* We move `string1' into `string2' if the latter's empty -- but not if
-     `string1' is null.  */
-  if (size2 == 0 && string1 != NULL)
-    {
-      string2 = string1;
-      size2 = size1;
-      string1 = 0;
-      size1 = 0;
-    }
-  end1 = string1 + size1;
-  end2 = string2 + size2;
-
-  /* Compute where to stop matching, within the two strings.  */
-  if (stop <= size1)
-    {
-      end_match_1 = string1 + stop;
-      end_match_2 = string2;
-    }
-  else
-    {
-      end_match_1 = end1;
-      end_match_2 = string2 + stop - size1;
-    }
-
-  /* `p' scans through the pattern as `d' scans through the data. 
-     `dend' is the end of the input string that `d' points within.  `d'
-     is advanced into the following input string whenever necessary, but
-     this happens before fetching; therefore, at the beginning of the
-     loop, `d' can be pointing at the end of a string, but it cannot
-     equal `string2'.  */
-  if (size1 > 0 && pos <= size1)
-    {
-      d = string1 + pos;
-      dend = end_match_1;
-    }
-  else
-    {
-      d = string2 + pos - size1;
-      dend = end_match_2;
-    }
-
-  DEBUG_PRINT1 ("The compiled pattern is: ");
-  DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
-  DEBUG_PRINT1 ("The string to match is: `");
-  DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
-  DEBUG_PRINT1 ("'\n");
-  
-  /* This loops over pattern commands.  It exits by returning from the
-     function if the match is complete, or it drops through if the match
-     fails at this starting point in the input data.  */
-  for (;;)
-    {
-      DEBUG_PRINT2 ("\n0x%x: ", p);
-
-      if (p == pend)
-       { /* End of pattern means we might have succeeded.  */
-          DEBUG_PRINT1 ("end of pattern ... ");
-          
-         /* If we haven't matched the entire string, and we want the
-             longest match, try backtracking.  */
-          if (d != end_match_2)
-           {
-              DEBUG_PRINT1 ("backtracking.\n");
-              
-              if (!FAIL_STACK_EMPTY ())
-                { /* More failure points to try.  */
-                  boolean same_str_p = (FIRST_STRING_P (match_end) 
-                                       == MATCHING_IN_FIRST_STRING);
-
-                  /* If exceeds best match so far, save it.  */
-                  if (!best_regs_set
-                      || (same_str_p && d > match_end)
-                      || (!same_str_p && !MATCHING_IN_FIRST_STRING))
-                    {
-                      best_regs_set = true;
-                      match_end = d;
-                      
-                      DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
-                      
-                      for (mcnt = 1; mcnt < num_regs; mcnt++)
-                        {
-                          best_regstart[mcnt] = regstart[mcnt];
-                          best_regend[mcnt] = regend[mcnt];
-                        }
-                    }
-                  goto fail;          
-                }
-
-              /* If no failure points, don't restore garbage.  */
-              else if (best_regs_set)   
-                {
-               restore_best_regs:
-                  /* Restore best match.  It may happen that `dend ==
-                     end_match_1' while the restored d is in string2.
-                     For example, the pattern `x.*y.*z' against the
-                     strings `x-' and `y-z-', if the two strings are
-                     not consecutive in memory.  */
-                  DEBUG_PRINT1 ("Restoring best registers.\n");
-                  
-                  d = match_end;
-                  dend = ((d >= string1 && d <= end1)
-                          ? end_match_1 : end_match_2);
-
-                 for (mcnt = 1; mcnt < num_regs; mcnt++)
-                   {
-                     regstart[mcnt] = best_regstart[mcnt];
-                     regend[mcnt] = best_regend[mcnt];
-                   }
-                }
-            } /* d != end_match_2 */
-
-          DEBUG_PRINT1 ("Accepting match.\n");
-
-          /* If caller wants register contents data back, do it.  */
-          if (regs && !bufp->no_sub)
-           {
-              /* Have the register data arrays been allocated?  */
-              if (bufp->regs_allocated == REGS_UNALLOCATED)
-                { /* No.  So allocate them with malloc.  We need one
-                     extra element beyond `num_regs' for the `-1' marker
-                     GNU code uses.  */
-                  regs->num_regs = MAX (RE_NREGS, num_regs + 1);
-                  regs->start = TALLOC (regs->num_regs, regoff_t);
-                  regs->end = TALLOC (regs->num_regs, regoff_t);
-                  if (regs->start == NULL || regs->end == NULL)
-                    return -2;
-                  bufp->regs_allocated = REGS_REALLOCATE;
-                }
-              else if (bufp->regs_allocated == REGS_REALLOCATE)
-                { /* Yes.  If we need more elements than were already
-                     allocated, reallocate them.  If we need fewer, just
-                     leave it alone.  */
-                  if (regs->num_regs < num_regs + 1)
-                    {
-                      regs->num_regs = num_regs + 1;
-                      RETALLOC (regs->start, regs->num_regs, regoff_t);
-                      RETALLOC (regs->end, regs->num_regs, regoff_t);
-                      if (regs->start == NULL || regs->end == NULL)
-                        return -2;
-                    }
-                }
-              else
-                assert (bufp->regs_allocated == REGS_FIXED);
-
-              /* Convert the pointer data in `regstart' and `regend' to
-                 indices.  Register zero has to be set differently,
-                 since we haven't kept track of any info for it.  */
-              if (regs->num_regs > 0)
-                {
-                  regs->start[0] = pos;
-                  regs->end[0] = (MATCHING_IN_FIRST_STRING ? d - string1
-                                 : d - string2 + size1);
-                }
-              
-              /* Go through the first `min (num_regs, regs->num_regs)'
-                 registers, since that is all we initialized.  */
-             for (mcnt = 1; mcnt < MIN (num_regs, regs->num_regs); mcnt++)
-               {
-                  if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt]))
-                    regs->start[mcnt] = regs->end[mcnt] = -1;
-                  else
-                    {
-                     regs->start[mcnt] = POINTER_TO_OFFSET (regstart[mcnt]);
-                      regs->end[mcnt] = POINTER_TO_OFFSET (regend[mcnt]);
-                    }
-               }
-              
-              /* If the regs structure we return has more elements than
-                 were in the pattern, set the extra elements to -1.  If
-                 we (re)allocated the registers, this is the case,
-                 because we always allocate enough to have at least one
-                 -1 at the end.  */
-              for (mcnt = num_regs; mcnt < regs->num_regs; mcnt++)
-                regs->start[mcnt] = regs->end[mcnt] = -1;
-           } /* regs && !bufp->no_sub */
-
-          FREE_VARIABLES ();
-          DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
-                        nfailure_points_pushed, nfailure_points_popped,
-                        nfailure_points_pushed - nfailure_points_popped);
-          DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
-
-          mcnt = d - pos - (MATCHING_IN_FIRST_STRING 
-                           ? string1 
-                           : string2 - size1);
-
-          DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
-
-          return mcnt;
-        }
-
-      /* Otherwise match next pattern command.  */
-#ifdef SWITCH_ENUM_BUG
-      switch ((int) ((re_opcode_t) *p++))
-#else
-      switch ((re_opcode_t) *p++)
-#endif
-       {
-        /* Ignore these.  Used to ignore the n of succeed_n's which
-           currently have n == 0.  */
-        case no_op:
-          DEBUG_PRINT1 ("EXECUTING no_op.\n");
-          break;
-
-
-        /* Match the next n pattern characters exactly.  The following
-           byte in the pattern defines n, and the n bytes after that
-           are the characters to match.  */
-       case exactn:
-         mcnt = *p++;
-          DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
-
-          /* This is written out as an if-else so we don't waste time
-             testing `translate' inside the loop.  */
-          if (translate)
-           {
-             do
-               {
-                 PREFETCH ();
-                 if (translate[(unsigned char) *d++] != (char) *p++)
-                    goto fail;
-               }
-             while (--mcnt);
-           }
-         else
-           {
-             do
-               {
-                 PREFETCH ();
-                 if (*d++ != (char) *p++) goto fail;
-               }
-             while (--mcnt);
-           }
-         SET_REGS_MATCHED ();
-          break;
-
-
-        /* Match any character except possibly a newline or a null.  */
-       case anychar:
-          DEBUG_PRINT1 ("EXECUTING anychar.\n");
-
-          PREFETCH ();
-
-          if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n')
-              || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000'))
-           goto fail;
-
-          SET_REGS_MATCHED ();
-          DEBUG_PRINT2 ("  Matched `%d'.\n", *d);
-          d++;
-         break;
-
-
-       case charset:
-       case charset_not:
-         {
-           register unsigned char c;
-           boolean not = (re_opcode_t) *(p - 1) == charset_not;
-
-            DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : "");
-
-           PREFETCH ();
-           c = TRANSLATE (*d); /* The character to match.  */
-
-            /* Cast to `unsigned' instead of `unsigned char' in case the
-               bit list is a full 32 bytes long.  */
-           if (c < (unsigned) (*p * BYTEWIDTH)
-               && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
-             not = !not;
-
-           p += 1 + *p;
-
-           if (!not) goto fail;
-            
-           SET_REGS_MATCHED ();
-            d++;
-           break;
-         }
-
-
-        /* The beginning of a group is represented by start_memory.
-           The arguments are the register number in the next byte, and the
-           number of groups inner to this one in the next.  The text
-           matched within the group is recorded (in the internal
-           registers data structure) under the register number.  */
-        case start_memory:
-         DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
-
-          /* Find out if this group can match the empty string.  */
-         p1 = p;               /* To send to group_match_null_string_p.  */
-          
-          if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
-            REG_MATCH_NULL_STRING_P (reg_info[*p]) 
-              = group_match_null_string_p (&p1, pend, reg_info);
-
-          /* Save the position in the string where we were the last time
-             we were at this open-group operator in case the group is
-             operated upon by a repetition operator, e.g., with `(a*)*b'
-             against `ab'; then we want to ignore where we are now in
-             the string in case this attempt to match fails.  */
-          old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
-                             ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
-                             : regstart[*p];
-         DEBUG_PRINT2 ("  old_regstart: %d\n", 
-                        POINTER_TO_OFFSET (old_regstart[*p]));
-
-          regstart[*p] = d;
-         DEBUG_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
-
-          IS_ACTIVE (reg_info[*p]) = 1;
-          MATCHED_SOMETHING (reg_info[*p]) = 0;
-          
-          /* This is the new highest active register.  */
-          highest_active_reg = *p;
-          
-          /* If nothing was active before, this is the new lowest active
-             register.  */
-          if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
-            lowest_active_reg = *p;
-
-          /* Move past the register number and inner group count.  */
-          p += 2;
-          break;
-
-
-        /* The stop_memory opcode represents the end of a group.  Its
-           arguments are the same as start_memory's: the register
-           number, and the number of inner groups.  */
-       case stop_memory:
-         DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
-             
-          /* We need to save the string position the last time we were at
-             this close-group operator in case the group is operated
-             upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
-             against `aba'; then we want to ignore where we are now in
-             the string in case this attempt to match fails.  */
-          old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
-                           ? REG_UNSET (regend[*p]) ? d : regend[*p]
-                          : regend[*p];
-         DEBUG_PRINT2 ("      old_regend: %d\n", 
-                        POINTER_TO_OFFSET (old_regend[*p]));
-
-          regend[*p] = d;
-         DEBUG_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
-
-          /* This register isn't active anymore.  */
-          IS_ACTIVE (reg_info[*p]) = 0;
-          
-          /* If this was the only register active, nothing is active
-             anymore.  */
-          if (lowest_active_reg == highest_active_reg)
-            {
-              lowest_active_reg = NO_LOWEST_ACTIVE_REG;
-              highest_active_reg = NO_HIGHEST_ACTIVE_REG;
-            }
-          else
-            { /* We must scan for the new highest active register, since
-                 it isn't necessarily one less than now: consider
-                 (a(b)c(d(e)f)g).  When group 3 ends, after the f), the
-                 new highest active register is 1.  */
-              unsigned char r = *p - 1;
-              while (r > 0 && !IS_ACTIVE (reg_info[r]))
-                r--;
-              
-              /* If we end up at register zero, that means that we saved
-                 the registers as the result of an `on_failure_jump', not
-                 a `start_memory', and we jumped to past the innermost
-                 `stop_memory'.  For example, in ((.)*) we save
-                 registers 1 and 2 as a result of the *, but when we pop
-                 back to the second ), we are at the stop_memory 1.
-                 Thus, nothing is active.  */
-             if (r == 0)
-                {
-                  lowest_active_reg = NO_LOWEST_ACTIVE_REG;
-                  highest_active_reg = NO_HIGHEST_ACTIVE_REG;
-                }
-              else
-                highest_active_reg = r;
-            }
-          
-          /* If just failed to match something this time around with a
-             group that's operated on by a repetition operator, try to
-             force exit from the ``loop'', and restore the register
-             information for this group that we had before trying this
-             last match.  */
-          if ((!MATCHED_SOMETHING (reg_info[*p])
-               || (re_opcode_t) p[-3] == start_memory)
-             && (p + 2) < pend)              
-            {
-              boolean is_a_jump_n = false;
-              
-              p1 = p + 2;
-              mcnt = 0;
-              switch ((re_opcode_t) *p1++)
-                {
-                  case jump_n:
-                   is_a_jump_n = true;
-                  case pop_failure_jump:
-                 case maybe_pop_jump:
-                 case jump:
-                 case dummy_failure_jump:
-                    EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-                   if (is_a_jump_n)
-                     p1 += 2;
-                    break;
-                  
-                  default:
-                    /* do nothing */ ;
-                }
-             p1 += mcnt;
-        
-              /* If the next operation is a jump backwards in the pattern
-                to an on_failure_jump right before the start_memory
-                 corresponding to this stop_memory, exit from the loop
-                 by forcing a failure after pushing on the stack the
-                 on_failure_jump's jump in the pattern, and d.  */
-              if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump
-                  && (re_opcode_t) p1[3] == start_memory && p1[4] == *p)
-               {
-                  /* If this group ever matched anything, then restore
-                     what its registers were before trying this last
-                     failed match, e.g., with `(a*)*b' against `ab' for
-                     regstart[1], and, e.g., with `((a*)*(b*)*)*'
-                     against `aba' for regend[3].
-                     
-                     Also restore the registers for inner groups for,
-                     e.g., `((a*)(b*))*' against `aba' (register 3 would
-                     otherwise get trashed).  */
-                     
-                  if (EVER_MATCHED_SOMETHING (reg_info[*p]))
-                   {
-                     unsigned r; 
-        
-                      EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
-                      
-                     /* Restore this and inner groups' (if any) registers.  */
-                      for (r = *p; r < *p + *(p + 1); r++)
-                        {
-                          regstart[r] = old_regstart[r];
-
-                          /* xx why this test?  */
-                          if ((int) old_regend[r] >= (int) regstart[r])
-                            regend[r] = old_regend[r];
-                        }     
-                    }
-                 p1++;
-                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-                  PUSH_FAILURE_POINT (p1 + mcnt, d, -2);
-
-                  goto fail;
-                }
-            }
-          
-          /* Move past the register number and the inner group count.  */
-          p += 2;
-          break;
-
-
-       /* \<digit> has been turned into a `duplicate' command which is
-           followed by the numeric value of <digit> as the register number.  */
-        case duplicate:
-         {
-           register const char *d2, *dend2;
-           int regno = *p++;   /* Get which register to match against.  */
-           DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
-
-           /* Can't back reference a group which we've never matched.  */
-            if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
-              goto fail;
-              
-            /* Where in input to try to start matching.  */
-            d2 = regstart[regno];
-            
-            /* Where to stop matching; if both the place to start and
-               the place to stop matching are in the same string, then
-               set to the place to stop, otherwise, for now have to use
-               the end of the first string.  */
-
-            dend2 = ((FIRST_STRING_P (regstart[regno]) 
-                     == FIRST_STRING_P (regend[regno]))
-                    ? regend[regno] : end_match_1);
-           for (;;)
-             {
-               /* If necessary, advance to next segment in register
-                   contents.  */
-               while (d2 == dend2)
-                 {
-                   if (dend2 == end_match_2) break;
-                   if (dend2 == regend[regno]) break;
-
-                    /* End of string1 => advance to string2. */
-                    d2 = string2;
-                    dend2 = regend[regno];
-                 }
-               /* At end of register contents => success */
-               if (d2 == dend2) break;
-
-               /* If necessary, advance to next segment in data.  */
-               PREFETCH ();
-
-               /* How many characters left in this segment to match.  */
-               mcnt = dend - d;
-                
-               /* Want how many consecutive characters we can match in
-                   one shot, so, if necessary, adjust the count.  */
-                if (mcnt > dend2 - d2)
-                 mcnt = dend2 - d2;
-                  
-               /* Compare that many; failure if mismatch, else move
-                   past them.  */
-               if (translate 
-                    ? bcmp_translate (d, d2, mcnt, translate) 
-                    : bcmp (d, d2, mcnt))
-                 goto fail;
-               d += mcnt, d2 += mcnt;
-             }
-         }
-         break;
-
-
-        /* begline matches the empty string at the beginning of the string
-           (unless `not_bol' is set in `bufp'), and, if
-           `newline_anchor' is set, after newlines.  */
-       case begline:
-          DEBUG_PRINT1 ("EXECUTING begline.\n");
-          
-          if (AT_STRINGS_BEG (d))
-            {
-              if (!bufp->not_bol) break;
-            }
-          else if (d[-1] == '\n' && bufp->newline_anchor)
-            {
-              break;
-            }
-          /* In all other cases, we fail.  */
-          goto fail;
-
-
-        /* endline is the dual of begline.  */
-       case endline:
-          DEBUG_PRINT1 ("EXECUTING endline.\n");
-
-          if (AT_STRINGS_END (d))
-            {
-              if (!bufp->not_eol) break;
-            }
-          
-          /* We have to ``prefetch'' the next character.  */
-          else if ((d == end1 ? *string2 : *d) == '\n'
-                   && bufp->newline_anchor)
-            {
-              break;
-            }
-          goto fail;
-
-
-       /* Match at the very beginning of the data.  */
-        case begbuf:
-          DEBUG_PRINT1 ("EXECUTING begbuf.\n");
-          if (AT_STRINGS_BEG (d))
-            break;
-          goto fail;
-
-
-       /* Match at the very end of the data.  */
-        case endbuf:
-          DEBUG_PRINT1 ("EXECUTING endbuf.\n");
-         if (AT_STRINGS_END (d))
-           break;
-          goto fail;
-
-
-        /* on_failure_keep_string_jump is used to optimize `.*\n'.  It
-           pushes NULL as the value for the string on the stack.  Then
-           `pop_failure_point' will keep the current value for the
-           string, instead of restoring it.  To see why, consider
-           matching `foo\nbar' against `.*\n'.  The .* matches the foo;
-           then the . fails against the \n.  But the next thing we want
-           to do is match the \n against the \n; if we restored the
-           string value, we would be back at the foo.
-           
-           Because this is used only in specific cases, we don't need to
-           check all the things that `on_failure_jump' does, to make
-           sure the right things get saved on the stack.  Hence we don't
-           share its code.  The only reason to push anything on the
-           stack at all is that otherwise we would have to change
-           `anychar's code to do something besides goto fail in this
-           case; that seems worse than this.  */
-        case on_failure_keep_string_jump:
-          DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
-          
-          EXTRACT_NUMBER_AND_INCR (mcnt, p);
-          DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt);
-
-          PUSH_FAILURE_POINT (p + mcnt, NULL, -2);
-          break;
-
-
-       /* Uses of on_failure_jump:
-        
-           Each alternative starts with an on_failure_jump that points
-           to the beginning of the next alternative.  Each alternative
-           except the last ends with a jump that in effect jumps past
-           the rest of the alternatives.  (They really jump to the
-           ending jump of the following alternative, because tensioning
-           these jumps is a hassle.)
-
-           Repeats start with an on_failure_jump that points past both
-           the repetition text and either the following jump or
-           pop_failure_jump back to this on_failure_jump.  */
-       case on_failure_jump:
-        on_failure:
-          DEBUG_PRINT1 ("EXECUTING on_failure_jump");
-
-          EXTRACT_NUMBER_AND_INCR (mcnt, p);
-          DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt);
-
-          /* If this on_failure_jump comes right before a group (i.e.,
-             the original * applied to a group), save the information
-             for that group and all inner ones, so that if we fail back
-             to this point, the group's information will be correct.
-             For example, in \(a*\)*\1, we need the preceding group,
-             and in \(\(a*\)b*\)\2, we need the inner group.  */
-
-          /* We can't use `p' to check ahead because we push
-             a failure point to `p + mcnt' after we do this.  */
-          p1 = p;
-
-          /* We need to skip no_op's before we look for the
-             start_memory in case this on_failure_jump is happening as
-             the result of a completed succeed_n, as in \(a\)\{1,3\}b\1
-             against aba.  */
-          while (p1 < pend && (re_opcode_t) *p1 == no_op)
-            p1++;
-
-          if (p1 < pend && (re_opcode_t) *p1 == start_memory)
-            {
-              /* We have a new highest active register now.  This will
-                 get reset at the start_memory we are about to get to,
-                 but we will have saved all the registers relevant to
-                 this repetition op, as described above.  */
-              highest_active_reg = *(p1 + 1) + *(p1 + 2);
-              if (lowest_active_reg == NO_LOWEST_ACTIVE_REG)
-                lowest_active_reg = *(p1 + 1);
-            }
-
-          DEBUG_PRINT1 (":\n");
-          PUSH_FAILURE_POINT (p + mcnt, d, -2);
-          break;
-
-
-        /* A smart repeat ends with `maybe_pop_jump'.
-          We change it to either `pop_failure_jump' or `jump'.  */
-        case maybe_pop_jump:
-          EXTRACT_NUMBER_AND_INCR (mcnt, p);
-          DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
-          {
-           register unsigned char *p2 = p;
-
-            /* Compare the beginning of the repeat with what in the
-               pattern follows its end. If we can establish that there
-               is nothing that they would both match, i.e., that we
-               would have to backtrack because of (as in, e.g., `a*a')
-               then we can change to pop_failure_jump, because we'll
-               never have to backtrack.
-               
-               This is not true in the case of alternatives: in
-               `(a|ab)*' we do need to backtrack to the `ab' alternative
-               (e.g., if the string was `ab').  But instead of trying to
-               detect that here, the alternative has put on a dummy
-               failure point which is what we will end up popping.  */
-
-           /* Skip over open/close-group commands.  */
-           while (p2 + 2 < pend
-                  && ((re_opcode_t) *p2 == stop_memory
-                      || (re_opcode_t) *p2 == start_memory))
-             p2 += 3;                  /* Skip over args, too.  */
-
-            /* If we're at the end of the pattern, we can change.  */
-            if (p2 == pend)
-             {
-               /* Consider what happens when matching ":\(.*\)"
-                  against ":/".  I don't really understand this code
-                  yet.  */
-               p[-3] = (unsigned char) pop_failure_jump;
-                DEBUG_PRINT1
-                  ("  End of pattern: change to `pop_failure_jump'.\n");
-              }
-
-            else if ((re_opcode_t) *p2 == exactn
-                    || (bufp->newline_anchor && (re_opcode_t) *p2 == endline))
-             {
-               register unsigned char c
-                  = *p2 == (unsigned char) endline ? '\n' : p2[2];
-               p1 = p + mcnt;
-
-                /* p1[0] ... p1[2] are the `on_failure_jump' corresponding
-                   to the `maybe_finalize_jump' of this case.  Examine what 
-                   follows.  */
-                if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
-                  {
-                   p[-3] = (unsigned char) pop_failure_jump;
-                    DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
-                                  c, p1[5]);
-                  }
-                  
-               else if ((re_opcode_t) p1[3] == charset
-                        || (re_opcode_t) p1[3] == charset_not)
-                 {
-                   int not = (re_opcode_t) p1[3] == charset_not;
-                    
-                   if (c < (unsigned char) (p1[4] * BYTEWIDTH)
-                       && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH)))
-                     not = !not;
-
-                    /* `not' is equal to 1 if c would match, which means
-                        that we can't change to pop_failure_jump.  */
-                   if (!not)
-                      {
-                       p[-3] = (unsigned char) pop_failure_jump;
-                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
-                      }
-                 }
-             }
-         }
-         p -= 2;               /* Point at relative address again.  */
-         if ((re_opcode_t) p[-1] != pop_failure_jump)
-           {
-             p[-1] = (unsigned char) jump;
-              DEBUG_PRINT1 ("  Match => jump.\n");
-             goto unconditional_jump;
-           }
-        /* Note fall through.  */
-
-
-       /* The end of a simple repeat has a pop_failure_jump back to
-           its matching on_failure_jump, where the latter will push a
-           failure point.  The pop_failure_jump takes off failure
-           points put on by this pop_failure_jump's matching
-           on_failure_jump; we got through the pattern to here from the
-           matching on_failure_jump, so didn't fail.  */
-        case pop_failure_jump:
-          {
-            /* We need to pass separate storage for the lowest and
-               highest registers, even though we don't care about the
-               actual values.  Otherwise, we will restore only one
-               register from the stack, since lowest will == highest in
-               `pop_failure_point'.  */
-            unsigned dummy_low_reg, dummy_high_reg;
-            unsigned char *pdummy;
-            const char *sdummy;
-
-            DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
-            POP_FAILURE_POINT (sdummy, pdummy,
-                               dummy_low_reg, dummy_high_reg,
-                               reg_dummy, reg_dummy, reg_info_dummy);
-          }
-          /* Note fall through.  */
-
-          
-        /* Unconditionally jump (without popping any failure points).  */
-        case jump:
-       unconditional_jump:
-         EXTRACT_NUMBER_AND_INCR (mcnt, p);    /* Get the amount to jump.  */
-          DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
-         p += mcnt;                            /* Do the jump.  */
-          DEBUG_PRINT2 ("(to 0x%x).\n", p);
-         break;
-
-       
-        /* We need this opcode so we can detect where alternatives end
-           in `group_match_null_string_p' et al.  */
-        case jump_past_alt:
-          DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
-          goto unconditional_jump;
-
-
-        /* Normally, the on_failure_jump pushes a failure point, which
-           then gets popped at pop_failure_jump.  We will end up at
-           pop_failure_jump, also, and with a pattern of, say, `a+', we
-           are skipping over the on_failure_jump, so we have to push
-           something meaningless for pop_failure_jump to pop.  */
-        case dummy_failure_jump:
-          DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
-          /* It doesn't matter what we push for the string here.  What
-             the code at `fail' tests is the value for the pattern.  */
-          PUSH_FAILURE_POINT (0, 0, -2);
-          goto unconditional_jump;
-
-
-        /* At the end of an alternative, we need to push a dummy failure
-           point in case we are followed by a `pop_failure_jump', because
-           we don't want the failure point for the alternative to be
-           popped.  For example, matching `(a|ab)*' against `aab'
-           requires that we match the `ab' alternative.  */
-        case push_dummy_failure:
-          DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
-          /* See comments just above at `dummy_failure_jump' about the
-             two zeroes.  */
-          PUSH_FAILURE_POINT (0, 0, -2);
-          break;
-
-        /* Have to succeed matching what follows at least n times.
-           After that, handle like `on_failure_jump'.  */
-        case succeed_n: 
-          EXTRACT_NUMBER (mcnt, p + 2);
-          DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
-
-          assert (mcnt >= 0);
-          /* Originally, this is how many times we HAVE to succeed.  */
-          if (mcnt > 0)
-            {
-               mcnt--;
-              p += 2;
-               STORE_NUMBER_AND_INCR (p, mcnt);
-               DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p, mcnt);
-            }
-         else if (mcnt == 0)
-            {
-              DEBUG_PRINT2 ("  Setting two bytes from 0x%x to no_op.\n", p+2);
-             p[2] = (unsigned char) no_op;
-              p[3] = (unsigned char) no_op;
-              goto on_failure;
-            }
-          break;
-        
-        case jump_n: 
-          EXTRACT_NUMBER (mcnt, p + 2);
-          DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
-
-          /* Originally, this is how many times we CAN jump.  */
-          if (mcnt)
-            {
-               mcnt--;
-               STORE_NUMBER (p + 2, mcnt);
-              goto unconditional_jump;      
-            }
-          /* If don't have to jump any more, skip over the rest of command.  */
-         else      
-           p += 4;                  
-          break;
-        
-       case set_number_at:
-         {
-            DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
-
-            EXTRACT_NUMBER_AND_INCR (mcnt, p);
-            p1 = p + mcnt;
-            EXTRACT_NUMBER_AND_INCR (mcnt, p);
-            DEBUG_PRINT3 ("  Setting 0x%x to %d.\n", p1, mcnt);
-           STORE_NUMBER (p1, mcnt);
-            break;
-          }
-
-        case wordbound:
-          DEBUG_PRINT1 ("EXECUTING wordbound.\n");
-          if (AT_WORD_BOUNDARY (d))
-           break;
-          goto fail;
-
-       case notwordbound:
-          DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
-         if (AT_WORD_BOUNDARY (d))
-           goto fail;
-          break;
-
-       case wordbeg:
-          DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
-         if (WORDCHAR_P (d) && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1)))
-           break;
-          goto fail;
-
-       case wordend:
-          DEBUG_PRINT1 ("EXECUTING wordend.\n");
-         if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1)
-              && (!WORDCHAR_P (d) || AT_STRINGS_END (d)))
-           break;
-          goto fail;
-
-#ifdef emacs
-#ifdef emacs19
-       case before_dot:
-          DEBUG_PRINT1 ("EXECUTING before_dot.\n");
-         if (PTR_CHAR_POS ((unsigned char *) d) >= point)
-           goto fail;
-         break;
-  
-       case at_dot:
-          DEBUG_PRINT1 ("EXECUTING at_dot.\n");
-         if (PTR_CHAR_POS ((unsigned char *) d) != point)
-           goto fail;
-         break;
-  
-       case after_dot:
-          DEBUG_PRINT1 ("EXECUTING after_dot.\n");
-          if (PTR_CHAR_POS ((unsigned char *) d) <= point)
-           goto fail;
-         break;
-#else /* not emacs19 */
-       case at_dot:
-          DEBUG_PRINT1 ("EXECUTING at_dot.\n");
-         if (PTR_CHAR_POS ((unsigned char *) d) + 1 != point)
-           goto fail;
-         break;
-#endif /* not emacs19 */
-
-       case syntaxspec:
-          DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
-         mcnt = *p++;
-         goto matchsyntax;
-
-        case wordchar:
-          DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
-         mcnt = (int) Sword;
-        matchsyntax:
-         PREFETCH ();
-         if (SYNTAX (*d++) != (enum syntaxcode) mcnt)
-            goto fail;
-          SET_REGS_MATCHED ();
-         break;
-
-       case notsyntaxspec:
-          DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
-         mcnt = *p++;
-         goto matchnotsyntax;
-
-        case notwordchar:
-          DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
-         mcnt = (int) Sword;
-        matchnotsyntax:
-         PREFETCH ();
-         if (SYNTAX (*d++) == (enum syntaxcode) mcnt)
-            goto fail;
-         SET_REGS_MATCHED ();
-          break;
-
-#else /* not emacs */
-       case wordchar:
-          DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
-         PREFETCH ();
-          if (!WORDCHAR_P (d))
-            goto fail;
-         SET_REGS_MATCHED ();
-          d++;
-         break;
-         
-       case notwordchar:
-          DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
-         PREFETCH ();
-         if (WORDCHAR_P (d))
-            goto fail;
-          SET_REGS_MATCHED ();
-          d++;
-         break;
-#endif /* not emacs */
-          
-        default:
-          abort ();
-       }
-      continue;  /* Successfully executed one pattern command; keep going.  */
-
-
-    /* We goto here if a matching operation fails. */
-    fail:
-      if (!FAIL_STACK_EMPTY ())
-       { /* A restart point is known.  Restore to that state.  */
-          DEBUG_PRINT1 ("\nFAIL:\n");
-          POP_FAILURE_POINT (d, p,
-                             lowest_active_reg, highest_active_reg,
-                             regstart, regend, reg_info);
-
-          /* If this failure point is a dummy, try the next one.  */
-          if (!p)
-           goto fail;
-
-          /* If we failed to the end of the pattern, don't examine *p.  */
-         assert (p <= pend);
-          if (p < pend)
-            {
-              boolean is_a_jump_n = false;
-              
-              /* If failed to a backwards jump that's part of a repetition
-                 loop, need to pop this failure point and use the next one.  */
-              switch ((re_opcode_t) *p)
-                {
-                case jump_n:
-                  is_a_jump_n = true;
-                case maybe_pop_jump:
-                case pop_failure_jump:
-                case jump:
-                  p1 = p + 1;
-                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-                  p1 += mcnt;  
-
-                  if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n)
-                      || (!is_a_jump_n
-                          && (re_opcode_t) *p1 == on_failure_jump))
-                    goto fail;
-                  break;
-                default:
-                  /* do nothing */ ;
-                }
-            }
-
-          if (d >= string1 && d <= end1)
-           dend = end_match_1;
-        }
-      else
-        break;   /* Matching at this starting point really fails.  */
-    } /* for (;;) */
-
-  if (best_regs_set)
-    goto restore_best_regs;
-
-  FREE_VARIABLES ();
-
-  return -1;                           /* Failure to match.  */
-} /* re_match_2 */
-\f
-/* Subroutine definitions for re_match_2.  */
-
-
-/* We are passed P pointing to a register number after a start_memory.
-   
-   Return true if the pattern up to the corresponding stop_memory can
-   match the empty string, and false otherwise.
-   
-   If we find the matching stop_memory, sets P to point to one past its number.
-   Otherwise, sets P to an undefined byte less than or equal to END.
-
-   We don't handle duplicates properly (yet).  */
-
-static boolean
-group_match_null_string_p (p, end, reg_info)
-    unsigned char **p, *end;
-    register_info_type *reg_info;
-{
-  int mcnt;
-  /* Point to after the args to the start_memory.  */
-  unsigned char *p1 = *p + 2;
-  
-  while (p1 < end)
-    {
-      /* Skip over opcodes that can match nothing, and return true or
-        false, as appropriate, when we get to one that can't, or to the
-         matching stop_memory.  */
-      
-      switch ((re_opcode_t) *p1)
-        {
-        /* Could be either a loop or a series of alternatives.  */
-        case on_failure_jump:
-          p1++;
-          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-          
-          /* If the next operation is not a jump backwards in the
-            pattern.  */
-
-         if (mcnt >= 0)
-           {
-              /* Go through the on_failure_jumps of the alternatives,
-                 seeing if any of the alternatives cannot match nothing.
-                 The last alternative starts with only a jump,
-                 whereas the rest start with on_failure_jump and end
-                 with a jump, e.g., here is the pattern for `a|b|c':
-
-                 /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
-                 /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
-                 /exactn/1/c                                           
-
-                 So, we have to first go through the first (n-1)
-                 alternatives and then deal with the last one separately.  */
-
-
-              /* Deal with the first (n-1) alternatives, which start
-                 with an on_failure_jump (see above) that jumps to right
-                 past a jump_past_alt.  */
-
-              while ((re_opcode_t) p1[mcnt-3] == jump_past_alt)
-                {
-                  /* `mcnt' holds how many bytes long the alternative
-                     is, including the ending `jump_past_alt' and
-                     its number.  */
-
-                  if (!alt_match_null_string_p (p1, p1 + mcnt - 3, 
-                                                     reg_info))
-                    return false;
-
-                  /* Move to right after this alternative, including the
-                    jump_past_alt.  */
-                  p1 += mcnt;  
-
-                  /* Break if it's the beginning of an n-th alternative
-                     that doesn't begin with an on_failure_jump.  */
-                  if ((re_opcode_t) *p1 != on_failure_jump)
-                    break;
-               
-                 /* Still have to check that it's not an n-th
-                    alternative that starts with an on_failure_jump.  */
-                 p1++;
-                  EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-                  if ((re_opcode_t) p1[mcnt-3] != jump_past_alt)
-                    {
-                     /* Get to the beginning of the n-th alternative.  */
-                      p1 -= 3;
-                      break;
-                    }
-                }
-
-              /* Deal with the last alternative: go back and get number
-                 of the `jump_past_alt' just before it.  `mcnt' contains
-                 the length of the alternative.  */
-              EXTRACT_NUMBER (mcnt, p1 - 2);
-
-              if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
-                return false;
-
-              p1 += mcnt;      /* Get past the n-th alternative.  */
-            } /* if mcnt > 0 */
-          break;
-
-          
-        case stop_memory:
-         assert (p1[1] == **p);
-          *p = p1 + 2;
-          return true;
-
-        
-        default: 
-          if (!common_op_match_null_string_p (&p1, end, reg_info))
-            return false;
-        }
-    } /* while p1 < end */
-
-  return false;
-} /* group_match_null_string_p */
-
-
-/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
-   It expects P to be the first byte of a single alternative and END one
-   byte past the last. The alternative can contain groups.  */
-   
-static boolean
-alt_match_null_string_p (p, end, reg_info)
-    unsigned char *p, *end;
-    register_info_type *reg_info;
-{
-  int mcnt;
-  unsigned char *p1 = p;
-  
-  while (p1 < end)
-    {
-      /* Skip over opcodes that can match nothing, and break when we get 
-         to one that can't.  */
-      
-      switch ((re_opcode_t) *p1)
-        {
-       /* It's a loop.  */
-        case on_failure_jump:
-          p1++;
-          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-          p1 += mcnt;
-          break;
-          
-       default: 
-          if (!common_op_match_null_string_p (&p1, end, reg_info))
-            return false;
-        }
-    }  /* while p1 < end */
-
-  return true;
-} /* alt_match_null_string_p */
-
-
-/* Deals with the ops common to group_match_null_string_p and
-   alt_match_null_string_p.  
-   
-   Sets P to one after the op and its arguments, if any.  */
-
-static boolean
-common_op_match_null_string_p (p, end, reg_info)
-    unsigned char **p, *end;
-    register_info_type *reg_info;
-{
-  int mcnt;
-  boolean ret;
-  int reg_no;
-  unsigned char *p1 = *p;
-
-  switch ((re_opcode_t) *p1++)
-    {
-    case no_op:
-    case begline:
-    case endline:
-    case begbuf:
-    case endbuf:
-    case wordbeg:
-    case wordend:
-    case wordbound:
-    case notwordbound:
-#ifdef emacs
-    case before_dot:
-    case at_dot:
-    case after_dot:
-#endif
-      break;
-
-    case start_memory:
-      reg_no = *p1;
-      assert (reg_no > 0 && reg_no <= MAX_REGNUM);
-      ret = group_match_null_string_p (&p1, end, reg_info);
-      
-      /* Have to set this here in case we're checking a group which
-         contains a group and a back reference to it.  */
-
-      if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
-        REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
-
-      if (!ret)
-        return false;
-      break;
-          
-    /* If this is an optimized succeed_n for zero times, make the jump.  */
-    case jump:
-      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-      if (mcnt >= 0)
-        p1 += mcnt;
-      else
-        return false;
-      break;
-
-    case succeed_n:
-      /* Get to the number of times to succeed.  */
-      p1 += 2;         
-      EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-
-      if (mcnt == 0)
-        {
-          p1 -= 4;
-          EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-          p1 += mcnt;
-        }
-      else
-        return false;
-      break;
-
-    case duplicate: 
-      if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
-        return false;
-      break;
-
-    case set_number_at:
-      p1 += 4;
-
-    default:
-      /* All other opcodes mean we cannot match the empty string.  */
-      return false;
-  }
-
-  *p = p1;
-  return true;
-} /* common_op_match_null_string_p */
-
-
-/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN
-   bytes; nonzero otherwise.  */
-   
-static int
-bcmp_translate (s1, s2, len, translate)
-     unsigned char *s1, *s2;
-     register int len;
-     char *translate;
-{
-  register unsigned char *p1 = s1, *p2 = s2;
-  while (len)
-    {
-      if (translate[*p1++] != translate[*p2++]) return 1;
-      len--;
-    }
-  return 0;
-}
-\f
-/* Entry points for GNU code.  */
-
-/* re_compile_pattern is the GNU regular expression compiler: it
-   compiles PATTERN (of length SIZE) and puts the result in BUFP.
-   Returns 0 if the pattern was valid, otherwise an error string.
-   
-   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
-   are set in BUFP on entry.
-   
-   We call regex_compile to do the actual compilation.  */
-
-const char *
-re_compile_pattern (pattern, length, bufp)
-     const char *pattern;
-     int length;
-     struct re_pattern_buffer *bufp;
-{
-  reg_errcode_t ret;
-  
-  /* GNU code is written to assume at least RE_NREGS registers will be set
-     (and at least one extra will be -1).  */
-  bufp->regs_allocated = REGS_UNALLOCATED;
-  
-  /* And GNU code determines whether or not to get register information
-     by passing null for the REGS argument to re_match, etc., not by
-     setting no_sub.  */
-  bufp->no_sub = 0;
-  
-  /* Match anchors at newline.  */
-  bufp->newline_anchor = 1;
-  
-  ret = regex_compile (pattern, length, re_syntax_options, bufp);
-
-  return re_error_msg[(int) ret];
-}     
-\f
-/* Entry points compatible with 4.2 BSD regex library.  We don't define
-   them if this is an Emacs or POSIX compilation.  */
-
-#if !defined (emacs) && !defined (_POSIX_SOURCE)
-
-/* BSD has one and only one pattern buffer.  */
-static struct re_pattern_buffer re_comp_buf;
-
-char *
-re_comp (s)
-    const char *s;
-{
-  reg_errcode_t ret;
-  
-  if (!s)
-    {
-      if (!re_comp_buf.buffer)
-       return "No previous regular expression";
-      return 0;
-    }
-
-  if (!re_comp_buf.buffer)
-    {
-      re_comp_buf.buffer = (unsigned char *) malloc (200);
-      if (re_comp_buf.buffer == NULL)
-        return "Memory exhausted";
-      re_comp_buf.allocated = 200;
-
-      re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH);
-      if (re_comp_buf.fastmap == NULL)
-       return "Memory exhausted";
-    }
-
-  /* Since `re_exec' always passes NULL for the `regs' argument, we
-     don't need to initialize the pattern buffer fields which affect it.  */
-
-  /* Match anchors at newlines.  */
-  re_comp_buf.newline_anchor = 1;
-
-  ret = regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf);
-  
-  /* Yes, we're discarding `const' here.  */
-  return (char *) re_error_msg[(int) ret];
-}
-
-
-int
-re_exec (s)
-    const char *s;
-{
-  const int len = strlen (s);
-  return
-    0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0);
-}
-#endif /* not emacs and not _POSIX_SOURCE */
-\f
-/* POSIX.2 functions.  Don't define these for Emacs.  */
-
-#ifndef emacs
-
-/* regcomp takes a regular expression as a string and compiles it.
-
-   PREG is a regex_t *.  We do not expect any fields to be initialized,
-   since POSIX says we shouldn't.  Thus, we set
-
-     `buffer' to the compiled pattern;
-     `used' to the length of the compiled pattern;
-     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
-       REG_EXTENDED bit in CFLAGS is set; otherwise, to
-       RE_SYNTAX_POSIX_BASIC;
-     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
-     `fastmap' and `fastmap_accurate' to zero;
-     `re_nsub' to the number of subexpressions in PATTERN.
-
-   PATTERN is the address of the pattern string.
-
-   CFLAGS is a series of bits which affect compilation.
-
-     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
-     use POSIX basic syntax.
-
-     If REG_NEWLINE is set, then . and [^...] don't match newline.
-     Also, regexec will try a match beginning after every newline.
-
-     If REG_ICASE is set, then we considers upper- and lowercase
-     versions of letters to be equivalent when matching.
-
-     If REG_NOSUB is set, then when PREG is passed to regexec, that
-     routine will report only success or failure, and nothing about the
-     registers.
-
-   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
-   the return codes and their meanings.)  */
-
-int
-regcomp (preg, pattern, cflags)
-    regex_t *preg;
-    const char *pattern; 
-    int cflags;
-{
-  reg_errcode_t ret;
-  unsigned syntax
-    = (cflags & REG_EXTENDED) ?
-      RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC;
-
-  /* regex_compile will allocate the space for the compiled pattern.  */
-  preg->buffer = 0;
-  preg->allocated = 0;
-  
-  /* Don't bother to use a fastmap when searching.  This simplifies the
-     REG_NEWLINE case: if we used a fastmap, we'd have to put all the
-     characters after newlines into the fastmap.  This way, we just try
-     every character.  */
-  preg->fastmap = 0;
-  
-  if (cflags & REG_ICASE)
-    {
-      unsigned i;
-      
-      preg->translate = (char *) malloc (CHAR_SET_SIZE);
-      if (preg->translate == NULL)
-        return (int) REG_ESPACE;
-
-      /* Map uppercase characters to corresponding lowercase ones.  */
-      for (i = 0; i < CHAR_SET_SIZE; i++)
-        preg->translate[i] = ISUPPER (i) ? tolower (i) : i;
-    }
-  else
-    preg->translate = NULL;
-
-  /* If REG_NEWLINE is set, newlines are treated differently.  */
-  if (cflags & REG_NEWLINE)
-    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
-      syntax &= ~RE_DOT_NEWLINE;
-      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
-      /* It also changes the matching behavior.  */
-      preg->newline_anchor = 1;
-    }
-  else
-    preg->newline_anchor = 0;
-
-  preg->no_sub = !!(cflags & REG_NOSUB);
-
-  /* POSIX says a null character in the pattern terminates it, so we 
-     can use strlen here in compiling the pattern.  */
-  ret = regex_compile (pattern, strlen (pattern), syntax, preg);
-  
-  /* POSIX doesn't distinguish between an unmatched open-group and an
-     unmatched close-group: both are REG_EPAREN.  */
-  if (ret == REG_ERPAREN) ret = REG_EPAREN;
-  
-  return (int) ret;
-}
-
-
-/* regexec searches for a given pattern, specified by PREG, in the
-   string STRING.
-   
-   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
-   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
-   least NMATCH elements, and we set them to the offsets of the
-   corresponding matched substrings.
-   
-   EFLAGS specifies `execution flags' which affect matching: if
-   REG_NOTBOL is set, then ^ does not match at the beginning of the
-   string; if REG_NOTEOL is set, then $ does not match at the end.
-   
-   We return 0 if we find a match and REG_NOMATCH if not.  */
-
-int
-regexec (preg, string, nmatch, pmatch, eflags)
-    const regex_t *preg;
-    const char *string; 
-    size_t nmatch; 
-    regmatch_t pmatch[]; 
-    int eflags;
-{
-  int ret;
-  struct re_registers regs;
-  regex_t private_preg;
-  int len = strlen (string);
-  boolean want_reg_info = !preg->no_sub && nmatch > 0;
-
-  private_preg = *preg;
-  
-  private_preg.not_bol = !!(eflags & REG_NOTBOL);
-  private_preg.not_eol = !!(eflags & REG_NOTEOL);
-  
-  /* The user has told us exactly how many registers to return
-     information about, via `nmatch'.  We have to pass that on to the
-     matching routines.  */
-  private_preg.regs_allocated = REGS_FIXED;
-  
-  if (want_reg_info)
-    {
-      regs.num_regs = nmatch;
-      regs.start = TALLOC (nmatch, regoff_t);
-      regs.end = TALLOC (nmatch, regoff_t);
-      if (regs.start == NULL || regs.end == NULL)
-        return (int) REG_NOMATCH;
-    }
-
-  /* Perform the searching operation.  */
-  ret = re_search (&private_preg, string, len,
-                   /* start: */ 0, /* range: */ len,
-                   want_reg_info ? &regs : (struct re_registers *) 0);
-  
-  /* Copy the register information to the POSIX structure.  */
-  if (want_reg_info)
-    {
-      if (ret >= 0)
-        {
-          unsigned r;
-
-          for (r = 0; r < nmatch; r++)
-            {
-              pmatch[r].rm_so = regs.start[r];
-              pmatch[r].rm_eo = regs.end[r];
-            }
-        }
-
-      /* If we needed the temporary register info, free the space now.  */
-      free (regs.start);
-      free (regs.end);
-    }
-
-  /* We want zero return to mean success, unlike `re_search'.  */
-  return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH;
-}
-
-
-/* Returns a message corresponding to an error code, ERRCODE, returned
-   from either regcomp or regexec.   We don't use PREG here.  */
-
-size_t
-regerror (errcode, preg, errbuf, errbuf_size)
-    int errcode;
-    const regex_t *preg;
-    char *errbuf;
-    size_t errbuf_size;
-{
-  const char *msg;
-  size_t msg_size;
-
-  if (errcode < 0
-      || errcode >= (sizeof (re_error_msg) / sizeof (re_error_msg[0])))
-    /* Only error codes returned by the rest of the code should be passed 
-       to this routine.  If we are given anything else, or if other regex
-       code generates an invalid error code, then the program has a bug.
-       Dump core so we can fix it.  */
-    abort ();
-
-  msg = re_error_msg[errcode];
-
-  /* POSIX doesn't require that we do anything in this case, but why
-     not be nice.  */
-  if (! msg)
-    msg = "Success";
-
-  msg_size = strlen (msg) + 1; /* Includes the null.  */
-  
-  if (errbuf_size != 0)
-    {
-      if (msg_size > errbuf_size)
-        {
-          strncpy (errbuf, msg, errbuf_size - 1);
-          errbuf[errbuf_size - 1] = 0;
-        }
-      else
-        strcpy (errbuf, msg);
-    }
-
-  return msg_size;
-}
-
-
-/* Free dynamically allocated space used by PREG.  */
-
-void
-regfree (preg)
-    regex_t *preg;
-{
-  if (preg->buffer != NULL)
-    free (preg->buffer);
-  preg->buffer = NULL;
-  
-  preg->allocated = 0;
-  preg->used = 0;
-
-  if (preg->fastmap != NULL)
-    free (preg->fastmap);
-  preg->fastmap = NULL;
-  preg->fastmap_accurate = 0;
-
-  if (preg->translate != NULL)
-    free (preg->translate);
-  preg->translate = NULL;
-}
-
-#endif /* not emacs  */
-\f
-/*
-Local variables:
-make-backup-files: t
-version-control: t
-trim-versions-without-asking: nil
-End:
-*/
diff --git a/lib/contrib/regex.h b/lib/contrib/regex.h
deleted file mode 100644 (file)
index 408dd21..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-/* Definitions for data structures and routines for the regular
-   expression library, version 0.12.
-
-   Copyright (C) 1985, 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-#ifndef __REGEXP_LIBRARY_H__
-#define __REGEXP_LIBRARY_H__
-
-/* POSIX says that <sys/types.h> must be included (by the caller) before
-   <regex.h>.  */
-
-#ifdef VMS
-/* VMS doesn't have `size_t' in <sys/types.h>, even though POSIX says it
-   should be there.  */
-#include <stddef.h>
-#endif
-
-
-/* The following bits are used to determine the regexp syntax we
-   recognize.  The set/not-set meanings are chosen so that Emacs syntax
-   remains the value 0.  The bits are given in alphabetical order, and
-   the definitions shifted by one from the previous bit; thus, when we
-   add or remove a bit, only one other definition need change.  */
-typedef unsigned reg_syntax_t;
-
-/* If this bit is not set, then \ inside a bracket expression is literal.
-   If set, then such a \ quotes the following character.  */
-#define RE_BACKSLASH_ESCAPE_IN_LISTS (1)
-
-/* If this bit is not set, then + and ? are operators, and \+ and \? are
-     literals. 
-   If set, then \+ and \? are operators and + and ? are literals.  */
-#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)
-
-/* If this bit is set, then character classes are supported.  They are:
-     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],
-     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].
-   If not set, then character classes are not supported.  */
-#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)
-
-/* If this bit is set, then ^ and $ are always anchors (outside bracket
-     expressions, of course).
-   If this bit is not set, then it depends:
-        ^  is an anchor if it is at the beginning of a regular
-           expression or after an open-group or an alternation operator;
-        $  is an anchor if it is at the end of a regular expression, or
-           before a close-group or an alternation operator.  
-
-   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because
-   POSIX draft 11.2 says that * etc. in leading positions is undefined.
-   We already implemented a previous draft which made those constructs
-   invalid, though, so we haven't changed the code back.  */
-#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)
-
-/* If this bit is set, then special characters are always special
-     regardless of where they are in the pattern.
-   If this bit is not set, then special characters are special only in
-     some contexts; otherwise they are ordinary.  Specifically, 
-     * + ? and intervals are only special when not after the beginning,
-     open-group, or alternation operator.  */
-#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)
-
-/* If this bit is set, then *, +, ?, and { cannot be first in an re or
-     immediately after an alternation or begin-group operator.  */
-#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)
-
-/* If this bit is set, then . matches newline.
-   If not set, then it doesn't.  */
-#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)
-
-/* If this bit is set, then . doesn't match NUL.
-   If not set, then it does.  */
-#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)
-
-/* If this bit is set, nonmatching lists [^...] do not match newline.
-   If not set, they do.  */
-#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)
-
-/* If this bit is set, either \{...\} or {...} defines an
-     interval, depending on RE_NO_BK_BRACES. 
-   If not set, \{, \}, {, and } are literals.  */
-#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)
-
-/* If this bit is set, +, ? and | aren't recognized as operators.
-   If not set, they are.  */
-#define RE_LIMITED_OPS (RE_INTERVALS << 1)
-
-/* If this bit is set, newline is an alternation operator.
-   If not set, newline is literal.  */
-#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)
-
-/* If this bit is set, then `{...}' defines an interval, and \{ and \}
-     are literals.
-  If not set, then `\{...\}' defines an interval.  */
-#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)
-
-/* If this bit is set, (...) defines a group, and \( and \) are literals.
-   If not set, \(...\) defines a group, and ( and ) are literals.  */
-#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)
-
-/* If this bit is set, then \<digit> matches <digit>.
-   If not set, then \<digit> is a back-reference.  */
-#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)
-
-/* If this bit is set, then | is an alternation operator, and \| is literal. 
-   If not set, then \| is an alternation operator, and | is literal.  */
-#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)
-
-/* If this bit is set, then an ending range point collating higher
-     than the starting range point, as in [z-a], is invalid.
-   If not set, then when ending range point collates higher than the
-     starting range point, the range is ignored.  */
-#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)
-
-/* If this bit is set, then an unmatched ) is ordinary.
-   If not set, then an unmatched ) is invalid.  */
-#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)
-
-/* This global variable defines the particular regexp syntax to use (for
-   some interfaces).  When a regexp is compiled, the syntax used is
-   stored in the pattern buffer, so changing this does not affect
-   already-compiled regexps.  */
-extern reg_syntax_t re_syntax_options;
-\f
-/* Define combinations of the above bits for the standard possibilities.
-   (The [[[ comments delimit what gets put into the Texinfo file, so
-   don't delete them!)  */ 
-/* [[[begin syntaxes]]] */
-#define RE_SYNTAX_EMACS 0
-
-#define RE_SYNTAX_AWK                                                  \
-  (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL                      \
-   | RE_NO_BK_PARENS            | RE_NO_BK_REFS                                \
-   | RE_NO_BK_VBAR               | RE_NO_EMPTY_RANGES                  \
-   | RE_UNMATCHED_RIGHT_PAREN_ORD)
-
-#define RE_SYNTAX_POSIX_AWK                                            \
-  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS)
-
-#define RE_SYNTAX_GREP                                                 \
-  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES                                \
-   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS                           \
-   | RE_NEWLINE_ALT)
-
-#define RE_SYNTAX_EGREP                                                        \
-  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS                   \
-   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE                   \
-   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS                            \
-   | RE_NO_BK_VBAR)
-
-#define RE_SYNTAX_POSIX_EGREP                                          \
-  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES)
-
-/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */
-#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC
-
-#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC
-
-/* Syntax bits common to both basic and extended POSIX regex syntax.  */
-#define _RE_SYNTAX_POSIX_COMMON                                                \
-  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL             \
-   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)
-
-#define RE_SYNTAX_POSIX_BASIC                                          \
-  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM)
-
-/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes
-   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this
-   isn't minimal, since other operators, such as \`, aren't disabled.  */
-#define RE_SYNTAX_POSIX_MINIMAL_BASIC                                  \
-  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)
-
-#define RE_SYNTAX_POSIX_EXTENDED                                       \
-  (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS                  \
-   | RE_CONTEXT_INDEP_OPS  | RE_NO_BK_BRACES                           \
-   | RE_NO_BK_PARENS       | RE_NO_BK_VBAR                             \
-   | RE_UNMATCHED_RIGHT_PAREN_ORD)
-
-/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INVALID_OPS
-   replaces RE_CONTEXT_INDEP_OPS and RE_NO_BK_REFS is added.  */
-#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED                               \
-  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS                 \
-   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES                          \
-   | RE_NO_BK_PARENS        | RE_NO_BK_REFS                            \
-   | RE_NO_BK_VBAR         | RE_UNMATCHED_RIGHT_PAREN_ORD)
-/* [[[end syntaxes]]] */
-\f
-/* Maximum number of duplicates an interval can allow.  Some systems
-   (erroneously) define this in other header files, but we want our
-   value, so remove any previous define.  */
-#ifdef RE_DUP_MAX
-#undef RE_DUP_MAX
-#endif
-#define RE_DUP_MAX ((1 << 15) - 1) 
-
-
-/* POSIX `cflags' bits (i.e., information for `regcomp').  */
-
-/* If this bit is set, then use extended regular expression syntax.
-   If not set, then use basic regular expression syntax.  */
-#define REG_EXTENDED 1
-
-/* If this bit is set, then ignore case when matching.
-   If not set, then case is significant.  */
-#define REG_ICASE (REG_EXTENDED << 1)
-/* If this bit is set, then anchors do not match at newline
-     characters in the string.
-   If not set, then anchors do match at newlines.  */
-#define REG_NEWLINE (REG_ICASE << 1)
-
-/* If this bit is set, then report only success or fail in regexec.
-   If not set, then returns differ between not matching and errors.  */
-#define REG_NOSUB (REG_NEWLINE << 1)
-
-
-/* POSIX `eflags' bits (i.e., information for regexec).  */
-
-/* If this bit is set, then the beginning-of-line operator doesn't match
-     the beginning of the string (presumably because it's not the
-     beginning of a line).
-   If not set, then the beginning-of-line operator does match the
-     beginning of the string.  */
-#define REG_NOTBOL 1
-
-/* Like REG_NOTBOL, except for the end-of-line.  */
-#define REG_NOTEOL (1 << 1)
-
-
-/* If any error codes are removed, changed, or added, update the
-   `re_error_msg' table in regex.c.  */
-typedef enum
-{
-  REG_NOERROR = 0,     /* Success.  */
-  REG_NOMATCH,         /* Didn't find a match (for regexec).  */
-
-  /* POSIX regcomp return error codes.  (In the order listed in the
-     standard.)  */
-  REG_BADPAT,          /* Invalid pattern.  */
-  REG_ECOLLATE,                /* Not implemented.  */
-  REG_ECTYPE,          /* Invalid character class name.  */
-  REG_EESCAPE,         /* Trailing backslash.  */
-  REG_ESUBREG,         /* Invalid back reference.  */
-  REG_EBRACK,          /* Unmatched left bracket.  */
-  REG_EPAREN,          /* Parenthesis imbalance.  */ 
-  REG_EBRACE,          /* Unmatched \{.  */
-  REG_BADBR,           /* Invalid contents of \{\}.  */
-  REG_ERANGE,          /* Invalid range end.  */
-  REG_ESPACE,          /* Ran out of memory.  */
-  REG_BADRPT,          /* No preceding re for repetition op.  */
-
-  /* Error codes we've added.  */
-  REG_EEND,            /* Premature end.  */
-  REG_ESIZE,           /* Compiled pattern bigger than 2^16 bytes.  */
-  REG_ERPAREN          /* Unmatched ) or \); not returned from regcomp.  */
-} reg_errcode_t;
-\f
-/* This data structure represents a compiled pattern.  Before calling
-   the pattern compiler, the fields `buffer', `allocated', `fastmap',
-   `translate', and `no_sub' can be set.  After the pattern has been
-   compiled, the `re_nsub' field is available.  All other fields are
-   private to the regex routines.  */
-
-struct re_pattern_buffer
-{
-/* [[[begin pattern_buffer]]] */
-       /* Space that holds the compiled pattern.  It is declared as
-          `unsigned char *' because its elements are
-           sometimes used as array indexes.  */
-  unsigned char *buffer;
-
-       /* Number of bytes to which `buffer' points.  */
-  unsigned long allocated;
-
-       /* Number of bytes actually used in `buffer'.  */
-  unsigned long used;  
-
-        /* Syntax setting with which the pattern was compiled.  */
-  reg_syntax_t syntax;
-
-        /* Pointer to a fastmap, if any, otherwise zero.  re_search uses
-           the fastmap, if there is one, to skip over impossible
-           starting points for matches.  */
-  char *fastmap;
-
-        /* Either a translate table to apply to all characters before
-           comparing them, or zero for no translation.  The translation
-           is applied to a pattern when it is compiled and to a string
-           when it is matched.  */
-  char *translate;
-
-       /* Number of subexpressions found by the compiler.  */
-  size_t re_nsub;
-
-        /* Zero if this pattern cannot match the empty string, one else.
-           Well, in truth it's used only in `re_search_2', to see
-           whether or not we should use the fastmap, so we don't set
-           this absolutely perfectly; see `re_compile_fastmap' (the
-           `duplicate' case).  */
-  unsigned can_be_null : 1;
-
-        /* If REGS_UNALLOCATED, allocate space in the `regs' structure
-             for `max (RE_NREGS, re_nsub + 1)' groups.
-           If REGS_REALLOCATE, reallocate space if necessary.
-           If REGS_FIXED, use what's there.  */
-#define REGS_UNALLOCATED 0
-#define REGS_REALLOCATE 1
-#define REGS_FIXED 2
-  unsigned regs_allocated : 2;
-
-        /* Set to zero when `regex_compile' compiles a pattern; set to one
-           by `re_compile_fastmap' if it updates the fastmap.  */
-  unsigned fastmap_accurate : 1;
-
-        /* If set, `re_match_2' does not return information about
-           subexpressions.  */
-  unsigned no_sub : 1;
-
-        /* If set, a beginning-of-line anchor doesn't match at the
-           beginning of the string.  */ 
-  unsigned not_bol : 1;
-
-        /* Similarly for an end-of-line anchor.  */
-  unsigned not_eol : 1;
-
-        /* If true, an anchor at a newline matches.  */
-  unsigned newline_anchor : 1;
-
-/* [[[end pattern_buffer]]] */
-};
-
-typedef struct re_pattern_buffer regex_t;
-
-
-/* search.c (search_buffer) in Emacs needs this one opcode value.  It is
-   defined both in `regex.c' and here.  */
-#define RE_EXACTN_VALUE 1
-\f
-/* Type for byte offsets within the string.  POSIX mandates this.  */
-typedef int regoff_t;
-
-
-/* This is the structure we store register match data in.  See
-   regex.texinfo for a full description of what registers match.  */
-struct re_registers
-{
-  unsigned num_regs;
-  regoff_t *start;
-  regoff_t *end;
-};
-
-
-/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,
-   `re_match_2' returns information about at least this many registers
-   the first time a `regs' structure is passed.  */
-#ifndef RE_NREGS
-#define RE_NREGS 30
-#endif
-
-
-/* POSIX specification for registers.  Aside from the different names than
-   `re_registers', POSIX uses an array of structures, instead of a
-   structure of arrays.  */
-typedef struct
-{
-  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */
-  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */
-} regmatch_t;
-\f
-/* Declarations for routines.  */
-
-/* To avoid duplicating every routine declaration -- once with a
-   prototype (if we are ANSI), and once without (if we aren't) -- we
-   use the following macro to declare argument types.  This
-   unfortunately clutters up the declarations a bit, but I think it's
-   worth it.  */
-
-#if __STDC__
-
-#define _RE_ARGS(args) args
-
-#else /* not __STDC__ */
-
-#define _RE_ARGS(args) ()
-
-#endif /* not __STDC__ */
-
-/* Sets the current default syntax to SYNTAX, and return the old syntax.
-   You can also simply assign to the `re_syntax_options' variable.  */
-extern reg_syntax_t re_set_syntax _RE_ARGS ((reg_syntax_t syntax));
-
-/* Compile the regular expression PATTERN, with length LENGTH
-   and syntax given by the global `re_syntax_options', into the buffer
-   BUFFER.  Return NULL if successful, and an error string if not.  */
-extern const char *re_compile_pattern
-  _RE_ARGS ((const char *pattern, int length,
-             struct re_pattern_buffer *buffer));
-
-
-/* Compile a fastmap for the compiled pattern in BUFFER; used to
-   accelerate searches.  Return 0 if successful and -2 if was an
-   internal error.  */
-extern int re_compile_fastmap _RE_ARGS ((struct re_pattern_buffer *buffer));
-
-
-/* Search in the string STRING (with length LENGTH) for the pattern
-   compiled into BUFFER.  Start searching at position START, for RANGE
-   characters.  Return the starting position of the match, -1 for no
-   match, or -2 for an internal error.  Also return register
-   information in REGS (if REGS and BUFFER->no_sub are nonzero).  */
-extern int re_search
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
-            int length, int start, int range, struct re_registers *regs));
-
-
-/* Like `re_search', but search in the concatenation of STRING1 and
-   STRING2.  Also, stop searching at index START + STOP.  */
-extern int re_search_2
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
-             int length1, const char *string2, int length2,
-             int start, int range, struct re_registers *regs, int stop));
-
-
-/* Like `re_search', but return how many characters in STRING the regexp
-   in BUFFER matched, starting at position START.  */
-extern int re_match
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string,
-             int length, int start, struct re_registers *regs));
-
-
-/* Relates to `re_match' as `re_search_2' relates to `re_search'.  */
-extern int re_match_2 
-  _RE_ARGS ((struct re_pattern_buffer *buffer, const char *string1,
-             int length1, const char *string2, int length2,
-             int start, struct re_registers *regs, int stop));
-
-
-/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
-   ENDS.  Subsequent matches using BUFFER and REGS will use this memory
-   for recording register information.  STARTS and ENDS must be
-   allocated with malloc, and must each be at least `NUM_REGS * sizeof
-   (regoff_t)' bytes long.
-
-   If NUM_REGS == 0, then subsequent matches should allocate their own
-   register data.
-
-   Unless this function is called, the first search or match using
-   PATTERN_BUFFER will allocate its own register data, without
-   freeing the old data.  */
-extern void re_set_registers
-  _RE_ARGS ((struct re_pattern_buffer *buffer, struct re_registers *regs,
-             unsigned num_regs, regoff_t *starts, regoff_t *ends));
-
-/* 4.2 bsd compatibility.  */
-extern char *re_comp _RE_ARGS ((const char *));
-extern int re_exec _RE_ARGS ((const char *));
-
-/* POSIX compatibility.  */
-extern int regcomp _RE_ARGS ((regex_t *preg, const char *pattern, int cflags));
-extern int regexec
-  _RE_ARGS ((const regex_t *preg, const char *string, size_t nmatch,
-             regmatch_t pmatch[], int eflags));
-extern size_t regerror
-  _RE_ARGS ((int errcode, const regex_t *preg, char *errbuf,
-             size_t errbuf_size));
-extern void regfree _RE_ARGS ((regex_t *preg));
-
-#endif /* not __REGEXP_LIBRARY_H__ */
-\f
-/*
-Local variables:
-make-backup-files: t
-version-control: t
-trim-versions-without-asking: nil
-End:
-*/
diff --git a/lib/contrib/regexpr.c b/lib/contrib/regexpr.c
new file mode 100644 (file)
index 0000000..ca5e741
--- /dev/null
@@ -0,0 +1,1722 @@
+/*
+
+regexpr.c
+
+Author: Tatu Ylonen <ylo@ngs.fi>
+
+Copyright (c) 1991 Tatu Ylonen, Espoo, Finland
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation is hereby granted without fee, provided that the
+above copyright notice appears in all source code copies, the name of
+Tatu Ylonen is not used to advertise products containing this software
+or a derivation thereof, and all modified versions are clearly marked
+as such.
+
+This software is provided "as is" without express or implied warranty.
+
+Created: Thu Sep 26 17:14:05 1991 ylo
+Last modified: Sun Mar 29 16:47:31 1992 ylo
+
+This code draws many ideas from the regular expression packages by
+Henry Spencer of the University of Toronto and Richard Stallman of the
+Free Software Foundation.
+
+Emacs-specific code and syntax table code is almost directly borrowed
+from GNU regexp.
+
+$Id$
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include <stdio.h>
+#include <assert.h>
+//#include "silcincludes.h"
+#include "regexpr.h"
+
+#define MACRO_BEGIN do {
+#define MACRO_END } while (0)
+
+enum regexp_compiled_ops /* opcodes for compiled regexp */
+{
+  Cend,                        /* end of pattern reached */
+  Cbol,                        /* beginning of line */
+  Ceol,                        /* end of line */
+  Cset,                        /* character set.  Followed by 32 bytes of set. */
+  Cexact,              /* followed by a byte to match */
+  Canychar,            /* matches any character except newline */
+  Cstart_memory,       /* set register start addr (followed by reg number) */
+  Cend_memory,         /* set register end addr (followed by reg number) */
+  Cmatch_memory,       /* match a duplicate of reg contents (regnum follows)*/
+  Cjump,               /* followed by two bytes (lsb,msb) of displacement. */
+  Cstar_jump,          /* will change to jump/update_failure_jump at runtime */
+  Cfailure_jump,       /* jump to addr on failure */
+  Cupdate_failure_jump,        /* update topmost failure point and jump */
+  Cdummy_failure_jump, /* push a dummy failure point and jump */
+  Cbegbuf,             /* match at beginning of buffer */
+  Cendbuf,             /* match at end of buffer */
+  Cwordbeg,            /* match at beginning of word */
+  Cwordend,            /* match at end of word */
+  Cwordbound,          /* match if at word boundary */
+  Cnotwordbound,       /* match if not at word boundary */
+#ifdef emacs
+  Cemacs_at_dot,       /* emacs only: matches at dot */
+#endif /* emacs */
+  Csyntaxspec,         /* matches syntax code (1 byte follows) */
+  Cnotsyntaxspec       /* matches if syntax code does not match (1 byte foll)*/
+};
+
+enum regexp_syntax_op  /* syntax codes for plain and quoted characters */
+{
+  Rend,                        /* special code for end of regexp */
+  Rnormal,             /* normal character */
+  Ranychar,            /* any character except newline */
+  Rquote,              /* the quote character */
+  Rbol,                        /* match beginning of line */
+  Reol,                        /* match end of line */
+  Roptional,           /* match preceding expression optionally */
+  Rstar,               /* match preceding expr zero or more times */
+  Rplus,               /* match preceding expr one or more times */
+  Ror,                 /* match either of alternatives */
+  Ropenpar,            /* opening parenthesis */
+  Rclosepar,           /* closing parenthesis */
+  Rmemory,             /* match memory register */
+  Rextended_memory,    /* \vnn to match registers 10-99 */
+  Ropenset,            /* open set.  Internal syntax hard-coded below. */
+  /* the following are gnu extensions to "normal" regexp syntax */
+  Rbegbuf,             /* beginning of buffer */
+  Rendbuf,             /* end of buffer */
+  Rwordchar,           /* word character */
+  Rnotwordchar,                /* not word character */
+  Rwordbeg,            /* beginning of word */
+  Rwordend,            /* end of word */
+  Rwordbound,          /* word bound */
+  Rnotwordbound,       /* not word bound */
+#ifdef emacs
+  Remacs_at_dot,       /* emacs: at dot */
+  Remacs_syntaxspec,   /* syntaxspec */
+  Remacs_notsyntaxspec,        /* notsyntaxspec */
+#endif /* emacs */
+  Rnum_ops
+};
+
+static int re_compile_initialized = 0;
+static int regexp_syntax = 0;
+static unsigned char regexp_plain_ops[256];
+static unsigned char regexp_quoted_ops[256];
+static unsigned char regexp_precedences[Rnum_ops];
+static int regexp_context_indep_ops;
+static int regexp_ansi_sequences;
+
+#define NUM_LEVELS  5    /* number of precedence levels in use */
+#define MAX_NESTING 100  /* max nesting level of operators */
+
+#ifdef emacs
+
+/* This code is for emacs compatibility only. */
+
+#include "config.h"
+#include "lisp.h"
+#include "buffer.h"
+#include "syntax.h"
+
+/* emacs defines NULL in some strange way? */
+#undef NULL
+#define NULL 0
+
+#else /* emacs */
+
+#define SYNTAX(ch) re_syntax_table[(unsigned char)(ch)]
+#define Sword 1
+
+#ifdef SYNTAX_TABLE
+char *re_syntax_table;
+#else
+static char re_syntax_table[256];
+#endif /* SYNTAX_TABLE */
+
+#endif /* emacs */
+
+static void re_compile_initialize()
+{
+  int a;
+  
+#if !defined(emacs) && !defined(SYNTAX_TABLE)
+  static int syntax_table_inited = 0;
+  
+  if (!syntax_table_inited)
+    {
+      syntax_table_inited = 1;
+      memset(re_syntax_table, 0, 256);
+      for (a = 'a'; a <= 'z'; a++)
+       re_syntax_table[a] = Sword;
+      for (a = 'A'; a <= 'Z'; a++)
+       re_syntax_table[a] = Sword;
+      for (a = '0'; a <= '9'; a++)
+       re_syntax_table[a] = Sword;
+    }
+#endif /* !emacs && !SYNTAX_TABLE */
+  re_compile_initialized = 1;
+  for (a = 0; a < 256; a++)
+    {
+      regexp_plain_ops[a] = Rnormal;
+      regexp_quoted_ops[a] = Rnormal;
+    }
+  for (a = '0'; a <= '9'; a++)
+    regexp_quoted_ops[a] = Rmemory;
+  regexp_plain_ops['\134'] = Rquote;
+  if (regexp_syntax & RE_NO_BK_PARENS)
+    {
+      regexp_plain_ops['('] = Ropenpar;
+      regexp_plain_ops[')'] = Rclosepar;
+    }
+  else
+    {
+      regexp_quoted_ops['('] = Ropenpar;
+      regexp_quoted_ops[')'] = Rclosepar;
+    }
+  if (regexp_syntax & RE_NO_BK_VBAR)
+    regexp_plain_ops['\174'] = Ror;
+  else
+    regexp_quoted_ops['\174'] = Ror;
+  regexp_plain_ops['*'] = Rstar;
+  if (regexp_syntax & RE_BK_PLUS_QM)
+    {
+      regexp_quoted_ops['+'] = Rplus;
+      regexp_quoted_ops['?'] = Roptional;
+    }
+  else
+    {
+      regexp_plain_ops['+'] = Rplus;
+      regexp_plain_ops['?'] = Roptional;
+    }
+  if (regexp_syntax & RE_NEWLINE_OR)
+    regexp_plain_ops['\n'] = Ror;
+  regexp_plain_ops['\133'] = Ropenset;
+  regexp_plain_ops['\136'] = Rbol;
+  regexp_plain_ops['$'] = Reol;
+  regexp_plain_ops['.'] = Ranychar;
+  if (!(regexp_syntax & RE_NO_GNU_EXTENSIONS))
+    {
+#ifdef emacs
+      regexp_quoted_ops['='] = Remacs_at_dot;
+      regexp_quoted_ops['s'] = Remacs_syntaxspec;
+      regexp_quoted_ops['S'] = Remacs_notsyntaxspec;
+#endif /* emacs */
+      regexp_quoted_ops['w'] = Rwordchar;
+      regexp_quoted_ops['W'] = Rnotwordchar;
+      regexp_quoted_ops['<'] = Rwordbeg;
+      regexp_quoted_ops['>'] = Rwordend;
+      regexp_quoted_ops['b'] = Rwordbound;
+      regexp_quoted_ops['B'] = Rnotwordbound;
+      regexp_quoted_ops['`'] = Rbegbuf;
+      regexp_quoted_ops['\''] = Rendbuf;
+    }
+  if (regexp_syntax & RE_ANSI_HEX)
+    regexp_quoted_ops['v'] = Rextended_memory;
+  for (a = 0; a < Rnum_ops; a++)
+    regexp_precedences[a] = 4;
+  if (regexp_syntax & RE_TIGHT_VBAR)
+    {
+      regexp_precedences[Ror] = 3;
+      regexp_precedences[Rbol] = 2;
+      regexp_precedences[Reol] = 2;
+    }
+  else
+    {
+      regexp_precedences[Ror] = 2;
+      regexp_precedences[Rbol] = 3;
+      regexp_precedences[Reol] = 3;
+    }
+  regexp_precedences[Rclosepar] = 1;
+  regexp_precedences[Rend] = 0;
+  regexp_context_indep_ops = (regexp_syntax & RE_CONTEXT_INDEP_OPS) != 0;
+  regexp_ansi_sequences = (regexp_syntax & RE_ANSI_HEX) != 0;
+}
+
+int re_set_syntax(syntax)
+int syntax;
+{
+  int ret;
+
+  ret = regexp_syntax;
+  regexp_syntax = syntax;
+  re_compile_initialize();
+  return ret;
+}
+
+static int hex_char_to_decimal(ch)
+int ch;
+{
+  if (ch >= '0' && ch <= '9')
+    return ch - '0';
+  if (ch >= 'a' && ch <= 'f')
+    return ch - 'a' + 10;
+  if (ch >= 'A' && ch <= 'F')
+    return ch - 'A' + 10;
+  return 16;
+}
+
+char *re_compile_pattern(regex, size, bufp)
+char *regex;
+int size;
+regexp_t bufp;
+{
+  int a, pos, op, current_level, level, opcode;
+  int pattern_offset = 0, alloc;
+  int starts[NUM_LEVELS * MAX_NESTING], starts_base;
+  int future_jumps[MAX_NESTING], num_jumps;
+  unsigned char ch = 0;
+  char *pattern, *translate;
+  int next_register, paren_depth, num_open_registers, open_registers[RE_NREGS];
+  int beginning_context;
+
+#define NEXTCHAR(var)                  \
+  MACRO_BEGIN                          \
+    if (pos >= size)                   \
+      goto ends_prematurely;           \
+    (var) = regex[pos];                        \
+    pos++;                             \
+  MACRO_END
+
+#define ALLOC(amount)                          \
+  MACRO_BEGIN                                  \
+    if (pattern_offset+(amount) > alloc)       \
+      {                                                \
+       alloc += 256 + (amount);                \
+       pattern = realloc(pattern, alloc);      \
+       if (!pattern)                           \
+         goto out_of_memory;                   \
+      }                                                \
+  MACRO_END
+
+#define STORE(ch) pattern[pattern_offset++] = (ch)
+
+#define CURRENT_LEVEL_START (starts[starts_base + current_level])
+
+#define SET_LEVEL_START starts[starts_base + current_level] = pattern_offset
+
+#define PUSH_LEVEL_STARTS if (starts_base < (MAX_NESTING-1)*NUM_LEVELS) \
+                           starts_base += NUM_LEVELS;                  \
+                          else                                         \
+                           goto too_complex
+
+#define POP_LEVEL_STARTS starts_base -= NUM_LEVELS
+
+#define PUT_ADDR(offset,addr)                          \
+  MACRO_BEGIN                                          \
+    int disp = (addr) - (offset) - 2;                  \
+    pattern[(offset)] = disp & 0xff;                   \
+    pattern[(offset)+1] = (disp>>8) & 0xff;            \
+  MACRO_END
+
+#define INSERT_JUMP(pos,type,addr)                     \
+  MACRO_BEGIN                                          \
+    int a, p = (pos), t = (type), ad = (addr);         \
+    for (a = pattern_offset - 1; a >= p; a--)          \
+      pattern[a + 3] = pattern[a];                     \
+    pattern[p] = t;                                    \
+    PUT_ADDR(p+1,ad);                                  \
+    pattern_offset += 3;                               \
+  MACRO_END
+
+#define SETBIT(buf,offset,bit) (buf)[(offset)+(bit)/8] |= (1<<((bit) & 7))
+
+#define SET_FIELDS                             \
+  MACRO_BEGIN                                  \
+    bufp->allocated = alloc;                   \
+    bufp->buffer = pattern;                    \
+    bufp->used = pattern_offset;               \
+  MACRO_END
+    
+#define GETHEX(var)                                            \
+  MACRO_BEGIN                                                  \
+    char gethex_ch, gethex_value;                              \
+    NEXTCHAR(gethex_ch);                                       \
+    gethex_value = hex_char_to_decimal(gethex_ch);             \
+    if (gethex_value == 16)                                    \
+      goto hex_error;                                          \
+    NEXTCHAR(gethex_ch);                                       \
+    gethex_ch = hex_char_to_decimal(gethex_ch);                        \
+    if (gethex_ch == 16)                                       \
+      goto hex_error;                                          \
+    (var) = gethex_value * 16 + gethex_ch;                     \
+  MACRO_END
+
+#define ANSI_TRANSLATE(ch)                             \
+  MACRO_BEGIN                                          \
+    switch (ch)                                                \
+      {                                                        \
+      case 'a':                                                \
+      case 'A':                                                \
+       ch = 7; /* audible bell */                      \
+       break;                                          \
+      case 'b':                                                \
+      case 'B':                                                \
+       ch = 8; /* backspace */                         \
+       break;                                          \
+      case 'f':                                                \
+      case 'F':                                                \
+       ch = 12; /* form feed */                        \
+       break;                                          \
+      case 'n':                                                \
+      case 'N':                                                \
+       ch = 10; /* line feed */                        \
+       break;                                          \
+      case 'r':                                                \
+      case 'R':                                                \
+       ch = 13; /* carriage return */                  \
+       break;                                          \
+      case 't':                                                \
+      case 'T':                                                \
+       ch = 9; /* tab */                               \
+       break;                                          \
+      case 'v':                                                \
+      case 'V':                                                \
+       ch = 11; /* vertical tab */                     \
+       break;                                          \
+      case 'x': /* hex code */                         \
+      case 'X':                                                \
+       GETHEX(ch);                                     \
+       break;                                          \
+      default:                                         \
+       /* other characters passed through */           \
+       if (translate)                                  \
+         ch = translate[(unsigned char)ch];            \
+       break;                                          \
+      }                                                        \
+  MACRO_END
+
+  if (!re_compile_initialized)
+    re_compile_initialize();
+  bufp->used = 0;
+  bufp->fastmap_accurate = 0;
+  bufp->uses_registers = 0;
+  translate = bufp->translate;
+  pattern = bufp->buffer;
+  alloc = bufp->allocated;
+  if (alloc == 0 || pattern == NULL)
+    {
+      alloc = 256;
+      pattern = malloc(alloc);
+      if (!pattern)
+       goto out_of_memory;
+    }
+  pattern_offset = 0;
+  starts_base = 0;
+  num_jumps = 0;
+  current_level = 0;
+  SET_LEVEL_START;
+  num_open_registers = 0;
+  next_register = 1;
+  paren_depth = 0;
+  beginning_context = 1;
+  op = -1;
+  /* we use Rend dummy to ensure that pending jumps are updated (due to
+     low priority of Rend) before exiting the loop. */
+  pos = 0;
+  while (op != Rend)
+    {
+      if (pos >= size)
+       op = Rend;
+      else
+       {
+         NEXTCHAR(ch);
+         if (translate)
+           ch = translate[(unsigned char)ch];
+         op = regexp_plain_ops[(unsigned char)ch];
+         if (op == Rquote)
+           {
+             NEXTCHAR(ch);
+             op = regexp_quoted_ops[(unsigned char)ch];
+             if (op == Rnormal && regexp_ansi_sequences)
+               ANSI_TRANSLATE(ch);
+           }
+       }
+      level = regexp_precedences[op];
+      /* printf("ch='%c' op=%d level=%d current_level=%d curlevstart=%d\n",
+            ch, op, level, current_level, CURRENT_LEVEL_START); */
+      if (level > current_level)
+       {
+         for (current_level++; current_level < level; current_level++)
+           SET_LEVEL_START;
+         SET_LEVEL_START;
+       }
+      else
+       if (level < current_level)
+         {
+           current_level = level;
+           for (;num_jumps > 0 &&
+                future_jumps[num_jumps-1] >= CURRENT_LEVEL_START;
+                num_jumps--)
+             PUT_ADDR(future_jumps[num_jumps-1], pattern_offset);
+         }
+      switch (op)
+       {
+       case Rend:
+         break;
+       case Rnormal:
+       normal_char:
+         opcode = Cexact;
+       store_opcode_and_arg: /* opcode & ch must be set */
+         SET_LEVEL_START;
+         ALLOC(2);
+         STORE(opcode);
+         STORE(ch);
+         break;
+       case Ranychar:
+         opcode = Canychar;
+       store_opcode:
+         SET_LEVEL_START;
+         ALLOC(1);
+         STORE(opcode);
+         break;
+       case Rquote:
+         abort();
+         /*NOTREACHED*/
+       case Rbol:
+         if (!beginning_context) {
+           if (regexp_context_indep_ops)
+             goto op_error;
+           else
+             goto normal_char;
+         }
+         opcode = Cbol;
+         goto store_opcode;
+       case Reol:
+         if (!((pos >= size) ||
+               ((regexp_syntax & RE_NO_BK_VBAR) ?
+                (regex[pos] == '\174') :
+                (pos+1 < size && regex[pos] == '\134' &&
+                 regex[pos+1] == '\174')) ||
+               ((regexp_syntax & RE_NO_BK_PARENS)?
+                (regex[pos] == ')'):
+                (pos+1 < size && regex[pos] == '\134' &&
+                 regex[pos+1] == ')')))) {
+           if (regexp_context_indep_ops)
+             goto op_error;
+           else
+             goto normal_char;
+         }
+         opcode = Ceol;
+         goto store_opcode;
+         break;
+       case Roptional:
+         if (beginning_context) {
+           if (regexp_context_indep_ops)
+             goto op_error;
+           else
+             goto normal_char;
+         }
+         if (CURRENT_LEVEL_START == pattern_offset)
+           break; /* ignore empty patterns for ? */
+         ALLOC(3);
+         INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
+                     pattern_offset + 3);
+         break;
+       case Rstar:
+       case Rplus:
+         if (beginning_context) {
+           if (regexp_context_indep_ops)
+             goto op_error;
+           else
+             goto normal_char;
+         }
+         if (CURRENT_LEVEL_START == pattern_offset)
+           break; /* ignore empty patterns for + and * */
+         ALLOC(9);
+         INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
+                     pattern_offset + 6);
+         INSERT_JUMP(pattern_offset, Cstar_jump, CURRENT_LEVEL_START);
+         if (op == Rplus)  /* jump over initial failure_jump */
+           INSERT_JUMP(CURRENT_LEVEL_START, Cdummy_failure_jump,
+                       CURRENT_LEVEL_START + 6);
+         break;
+       case Ror:
+         ALLOC(6);
+         INSERT_JUMP(CURRENT_LEVEL_START, Cfailure_jump,
+                     pattern_offset + 6);
+         if (num_jumps >= MAX_NESTING)
+           goto too_complex;
+         STORE(Cjump);
+         future_jumps[num_jumps++] = pattern_offset;
+         STORE(0);
+         STORE(0);
+         SET_LEVEL_START;
+         break;
+       case Ropenpar:
+         SET_LEVEL_START;
+         if (next_register < RE_NREGS)
+           {
+             bufp->uses_registers = 1;
+             ALLOC(2);
+             STORE(Cstart_memory);
+             STORE(next_register);
+             open_registers[num_open_registers++] = next_register;
+             next_register++;
+           }
+         paren_depth++;
+         PUSH_LEVEL_STARTS;
+         current_level = 0;
+         SET_LEVEL_START;
+         break;
+       case Rclosepar:
+         if (paren_depth <= 0)
+           goto parenthesis_error;
+         POP_LEVEL_STARTS;
+         current_level = regexp_precedences[Ropenpar];
+         paren_depth--;
+         if (paren_depth < num_open_registers)
+           {
+             bufp->uses_registers = 1;
+             ALLOC(2);
+             STORE(Cend_memory);
+             num_open_registers--;
+             STORE(open_registers[num_open_registers]);
+           }
+         break;
+       case Rmemory:
+         if (ch == '0')
+           goto bad_match_register;
+         assert(ch >= '0' && ch <= '9');
+         bufp->uses_registers = 1;
+         opcode = Cmatch_memory;
+         ch -= '0';
+         goto store_opcode_and_arg;
+       case Rextended_memory:
+         NEXTCHAR(ch);
+         if (ch < '0' || ch > '9')
+           goto bad_match_register;
+         NEXTCHAR(a);
+         if (a < '0' || a > '9')
+           goto bad_match_register;
+         ch = 10 * (a - '0') + ch - '0';
+         if (ch <= 0 || ch >= RE_NREGS)
+           goto bad_match_register;
+         bufp->uses_registers = 1;
+         opcode = Cmatch_memory;
+         goto store_opcode_and_arg;
+       case Ropenset:
+         {
+           int complement,prev,offset,range,firstchar;
+           
+           SET_LEVEL_START;
+           ALLOC(1+256/8);
+           STORE(Cset);
+           offset = pattern_offset;
+           for (a = 0; a < 256/8; a++)
+             STORE(0);
+           NEXTCHAR(ch);
+           if (translate)
+             ch = translate[(unsigned char)ch];
+           if (ch == '\136')
+             {
+               complement = 1;
+               NEXTCHAR(ch);
+               if (translate)
+                 ch = translate[(unsigned char)ch];
+             }
+           else
+             complement = 0;
+           prev = -1;
+           range = 0;
+           firstchar = 1;
+           while (ch != '\135' || firstchar)
+             {
+               firstchar = 0;
+               if (regexp_ansi_sequences && ch == '\134')
+                 {
+                   NEXTCHAR(ch);
+                   ANSI_TRANSLATE(ch);
+                 }
+               if (range)
+                 {
+                   for (a = prev; a <= ch; a++)
+                     SETBIT(pattern, offset, a);
+                   prev = -1;
+                   range = 0;
+                 }
+               else
+                 if (prev != -1 && ch == '-')
+                   range = 1;
+                 else
+                   {
+                     SETBIT(pattern, offset, ch);
+                     prev = ch;
+                   }
+               NEXTCHAR(ch);
+               if (translate)
+                 ch = translate[(unsigned char)ch];
+             }
+           if (range)
+             SETBIT(pattern, offset, '-');
+           if (complement)
+             {
+               for (a = 0; a < 256/8; a++)
+                 pattern[offset+a] ^= 0xff;
+             }
+           break;
+         }
+       case Rbegbuf:
+         opcode = Cbegbuf;
+         goto store_opcode;
+       case Rendbuf:
+         opcode = Cendbuf;
+         goto store_opcode;
+       case Rwordchar:
+         opcode = Csyntaxspec;
+         ch = Sword;
+         goto store_opcode_and_arg;
+       case Rnotwordchar:
+         opcode = Cnotsyntaxspec;
+         ch = Sword;
+         goto store_opcode_and_arg;
+       case Rwordbeg:
+         opcode = Cwordbeg;
+         goto store_opcode;
+       case Rwordend:
+         opcode = Cwordend;
+         goto store_opcode;
+       case Rwordbound:
+         opcode = Cwordbound;
+         goto store_opcode;
+       case Rnotwordbound:
+         opcode = Cnotwordbound;
+         goto store_opcode;
+#ifdef emacs
+       case Remacs_at_dot:
+         opcode = Cemacs_at_dot;
+         goto store_opcode;
+       case Remacs_syntaxspec:
+         NEXTCHAR(ch);
+         if (translate)
+           ch = translate[(unsigned char)ch];
+         opcode = Csyntaxspec;
+         ch = syntax_spec_code[(unsigned char)ch];
+         goto store_opcode_and_arg;
+       case Remacs_notsyntaxspec:
+         NEXTCHAR(ch);
+         if (translate)
+           ch = translate[(unsigned char)ch];
+         opcode = Cnotsyntaxspec;
+         ch = syntax_spec_code[(unsigned char)ch];
+         goto store_opcode_and_arg;
+#endif /* emacs */
+       default:
+         abort();
+       }
+      beginning_context = (op == Ropenpar || op == Ror);
+    }
+  if (starts_base != 0)
+    goto parenthesis_error;
+  assert(num_jumps == 0);
+  ALLOC(1);
+  STORE(Cend);
+  SET_FIELDS;
+  return NULL;
+
+ op_error:
+  SET_FIELDS;
+  return "Badly placed special character";
+
+ bad_match_register:
+  SET_FIELDS;
+  return "Bad match register number";
+
+ hex_error:
+  SET_FIELDS;
+  return "Bad hexadecimal number";
+
+ parenthesis_error:
+  SET_FIELDS;
+  return "Badly placed parenthesis";
+
+ out_of_memory:
+  SET_FIELDS;
+  return "Out of memory";
+
+ ends_prematurely:
+  SET_FIELDS;
+  return "Regular expression ends prematurely";
+
+ too_complex:
+  SET_FIELDS;
+  return "Regular expression too complex";
+}
+#undef CHARAT
+#undef NEXTCHAR
+#undef GETHEX
+#undef ALLOC
+#undef STORE
+#undef CURRENT_LEVEL_START
+#undef SET_LEVEL_START
+#undef PUSH_LEVEL_STARTS
+#undef POP_LEVEL_STARTS
+#undef PUT_ADDR
+#undef INSERT_JUMP
+#undef SETBIT
+#undef SET_FIELDS
+
+static void re_compile_fastmap_aux(code, pos, visited, can_be_null, fastmap)
+char *code, *visited, *can_be_null, *fastmap;
+int pos;
+{
+  int a, b, syntaxcode;
+
+  if (visited[pos])
+    return;  /* we have already been here */
+  visited[pos] = 1;
+  for (;;)
+    switch (code[pos++])
+      {
+      case Cend:
+       *can_be_null = 1;
+       return;
+      case Cbol:
+      case Cbegbuf:
+      case Cendbuf:
+      case Cwordbeg:
+      case Cwordend:
+      case Cwordbound:
+      case Cnotwordbound:
+#ifdef emacs
+      case Cemacs_at_dot:
+#endif /* emacs */
+       break;
+      case Csyntaxspec:
+       syntaxcode = code[pos++];
+       for (a = 0; a < 256; a++)
+         if (SYNTAX(a) == syntaxcode)
+           fastmap[a] = 1;
+       return;
+      case Cnotsyntaxspec:
+       syntaxcode = code[pos++];
+       for (a = 0; a < 256; a++)
+         if (SYNTAX(a) != syntaxcode)
+           fastmap[a] = 1;
+       return;
+      case Ceol:
+       fastmap['\n'] = 1;
+       if (*can_be_null == 0)
+         *can_be_null = 2;  /* can match null, but only at end of buffer*/
+       return;
+      case Cset:
+       for (a = 0; a < 256/8; a++)
+         if (code[pos + a] != 0)
+           for (b = 0; b < 8; b++)
+             if (code[pos + a] & (1 << b))
+               fastmap[(a << 3) + b] = 1;
+       pos += 256/8;
+       return;
+      case Cexact:
+       fastmap[(unsigned char)code[pos]] = 1;
+       return;
+      case Canychar:
+       for (a = 0; a < 256; a++)
+         if (a != '\n')
+           fastmap[a] = 1;
+       return;
+      case Cstart_memory:
+      case Cend_memory:
+       pos++;
+       break;
+      case Cmatch_memory:
+       for (a = 0; a < 256; a++)
+         fastmap[a] = 1;
+       *can_be_null = 1;
+       return;
+      case Cjump:
+      case Cdummy_failure_jump:
+      case Cupdate_failure_jump:
+      case Cstar_jump:
+       a = (unsigned char)code[pos++];
+       a |= (unsigned char)code[pos++] << 8;
+       pos += (int)(short)a;
+       if (visited[pos])
+         {
+           /* argh... the regexp contains empty loops.  This is not
+              good, as this may cause a failure stack overflow when
+              matching.  Oh well. */
+           /* this path leads nowhere; pursue other paths. */
+           return;
+         }
+       visited[pos] = 1;
+       break;
+      case Cfailure_jump:
+       a = (unsigned char)code[pos++];
+       a |= (unsigned char)code[pos++] << 8;
+       a = pos + (int)(short)a;
+       re_compile_fastmap_aux(code, a, visited, can_be_null, fastmap);
+       break;
+      default:
+       abort();  /* probably some opcode is missing from this switch */
+       /*NOTREACHED*/
+      }
+}
+
+static int re_do_compile_fastmap(buffer, used, pos, can_be_null, fastmap)
+char *buffer, *fastmap, *can_be_null;
+int used, pos;
+{
+  char small_visited[512], *visited;
+
+  if (used <= sizeof(small_visited))
+    visited = small_visited;
+  else
+    {
+      visited = malloc(used);
+      if (!visited)
+       return 0;
+    }
+  *can_be_null = 0;
+  memset(fastmap, 0, 256);
+  memset(visited, 0, used);
+  re_compile_fastmap_aux(buffer, pos, visited, can_be_null, fastmap);
+  if (visited != small_visited)
+    free(visited);
+  return 1;
+}
+
+void re_compile_fastmap(bufp)
+regexp_t bufp;
+{
+  if (!bufp->fastmap || bufp->fastmap_accurate)
+    return;
+  assert(bufp->used > 0);
+  if (!re_do_compile_fastmap(bufp->buffer, bufp->used, 0, &bufp->can_be_null,
+                            bufp->fastmap))
+    return;
+  if (bufp->buffer[0] == Cbol)
+    bufp->anchor = 1;   /* begline */
+  else
+    if (bufp->buffer[0] == Cbegbuf)
+      bufp->anchor = 2; /* begbuf */
+    else
+      bufp->anchor = 0; /* none */
+  bufp->fastmap_accurate = 1;
+}
+
+#define INITIAL_FAILURES  128  /* initial # failure points to allocate */
+#define MAX_FAILURES     4100  /* max # of failure points before failing */
+
+int re_match_2(bufp, string1, size1, string2, size2, pos, regs, mstop)
+regexp_t bufp;
+char *string1, *string2;
+int size1, size2, pos, mstop;
+regexp_registers_t regs;
+{
+  struct failure_point { char *text, *partend, *code; }
+    *failure_stack_start, *failure_sp, *failure_stack_end,
+    initial_failure_stack[INITIAL_FAILURES];
+  char *code, *translate, *text, *textend, *partend, *part_2_end;
+  char *regstart_text[RE_NREGS], *regstart_partend[RE_NREGS];
+  char *regend_text[RE_NREGS], *regend_partend[RE_NREGS];
+  int a, b, ch, reg, regch, match_end;
+  char *regtext, *regpartend, *regtextend;
+
+#define PREFETCH                                       \
+  MACRO_BEGIN                                          \
+    if (text == partend)                               \
+      {                                                        \
+       if (text == textend)                            \
+         goto fail;                                    \
+       text = string2;                                 \
+       partend = part_2_end;                           \
+      }                                                        \
+  MACRO_END
+
+#define NEXTCHAR(var)                          \
+  MACRO_BEGIN                                  \
+    PREFETCH;                                  \
+    (var) = (unsigned char)*text++;            \
+    if (translate)                             \
+      (var) = (unsigned char)translate[(var)]; \
+  MACRO_END
+
+  assert(pos >= 0 && size1 >= 0 && size2 >= 0 && mstop >= 0);
+  assert(mstop <= size1 + size2);
+  assert(pos <= mstop);
+
+  if (pos <= size1)
+    {
+      text = string1 + pos;
+      if (mstop <= size1)
+       {
+         partend = string1 + mstop;
+         textend = partend;
+       }
+      else
+       {
+         partend = string1 + size1;
+         textend = string2 + mstop - size1;
+       }
+      part_2_end = string2 + mstop - size1;
+    }
+  else
+    {
+      text = string2 + pos - size1;
+      partend = string2 + mstop - size1;
+      textend = partend;
+      part_2_end = partend;
+    }
+
+  if (bufp->uses_registers && regs != NULL)
+    for (a = 0; a < RE_NREGS; a++)
+      regend_text[a] = NULL;
+
+  code = bufp->buffer;
+  translate = bufp->translate;
+  failure_stack_start = failure_sp = initial_failure_stack;
+  failure_stack_end = initial_failure_stack + INITIAL_FAILURES;
+
+#if 0
+  /* re_search_2 has already done this, and otherwise we get little benefit
+     from this.  So I'll leave this out. */
+  if (bufp->fastmap_accurate && !bufp->can_be_null &&
+      text != textend &&
+      !bufp->fastmap[translate ?
+                    (unsigned char)translate[(unsigned char)*text] :
+                    (unsigned char)*text])
+    return -1;  /* it can't possibly match */
+#endif
+
+ continue_matching:
+  for (;;)
+    {
+      switch (*code++)
+       {
+       case Cend:
+         if (partend != part_2_end)
+           match_end = text - string1;
+         else
+           match_end = text - string2 + size1;
+         if (regs)
+           {
+             regs->start[0] = pos;
+             regs->end[0] = match_end;
+             if (!bufp->uses_registers)
+               {
+                 for (a = 1; a < RE_NREGS; a++)
+                   {
+                     regs->start[a] = -1;
+                     regs->end[a] = -1;
+                   }
+               }
+             else
+               {
+                 for (a = 1; a < RE_NREGS; a++)
+                   {
+                     if (regend_text[a] == NULL)
+                       {
+                         regs->start[a] = -1;
+                         regs->end[a] = -1;
+                         continue;
+                       }
+                     if (regstart_partend[a] != part_2_end)
+                       regs->start[a] = regstart_text[a] - string1;
+                     else
+                       regs->start[a] = regstart_text[a] - string2 + size1;
+                     if (regend_partend[a] != part_2_end)
+                       regs->end[a] = regend_text[a] - string1;
+                     else
+                       regs->end[a] = regend_text[a] - string2 + size1;
+                   }
+               }
+           }
+         if (failure_stack_start != initial_failure_stack)
+           free((char *)failure_stack_start);
+         return match_end - pos;
+       case Cbol:
+         if (text == string1 || text[-1] == '\n') /* text[-1] always valid */
+           break;
+         goto fail;
+       case Ceol:
+         if (text == string2 + size2 ||
+             (text == string1 + size1 ?
+              (size2 == 0 || *string2 == '\n') :
+              *text == '\n'))
+           break;
+         goto fail;
+       case Cset:
+         NEXTCHAR(ch);
+         if (code[ch/8] & (1<<(ch & 7)))
+           {
+             code += 256/8;
+             break;
+           }
+         goto fail;
+       case Cexact:
+         NEXTCHAR(ch);
+         if (ch != (unsigned char)*code++)
+           goto fail;
+         break;
+       case Canychar:
+         NEXTCHAR(ch);
+         if (ch == '\n')
+           goto fail;
+         break;
+       case Cstart_memory:
+         reg = *code++;
+         regstart_text[reg] = text;
+         regstart_partend[reg] = partend;
+         break;
+       case Cend_memory:
+         reg = *code++;
+         regend_text[reg] = text;
+         regend_partend[reg] = partend;
+         break;
+       case Cmatch_memory:
+         reg = *code++;
+         if (regend_text[reg] == NULL)
+           goto fail;  /* or should we just match nothing? */
+         regtext = regstart_text[reg];
+         regtextend = regend_text[reg];
+         if (regstart_partend[reg] == regend_partend[reg])
+           regpartend = regtextend;
+         else
+           regpartend = string1 + size1;
+         
+         for (;regtext != regtextend;)
+           {
+             NEXTCHAR(ch);
+             if (regtext == regpartend)
+               regtext = string2;
+             regch = (unsigned char)*regtext++;
+             if (translate)
+               regch = (unsigned char)translate[regch];
+             if (regch != ch)
+               goto fail;
+           }
+         break;
+       case Cstar_jump:
+         /* star is coded as:
+              1: failure_jump 2
+                 ... code for operand of star
+                 star_jump 1
+              2: ... code after star
+            We change the star_jump to update_failure_jump if we can determine
+            that it is safe to do so; otherwise we change it to an ordinary
+            jump.
+            plus is coded as
+                 jump 2
+              1: failure_jump 3
+              2: ... code for operand of plus
+                 star_jump 1
+              3: ... code after plus
+            For star_jump considerations this is processed identically
+            to star. */
+         a = (unsigned char)*code++;
+         a |= (unsigned char)*code++ << 8;
+         a = (int)(short)a;
+         {
+           char map[256], can_be_null;
+           char *p1, *p2;
+
+           p1 = code + a + 3; /* skip the failure_jump */
+           assert(p1[-3] == Cfailure_jump);
+           p2 = code;
+           /* p1 points inside loop, p2 points to after loop */
+           if (!re_do_compile_fastmap(bufp->buffer, bufp->used,
+                                      p2 - bufp->buffer, &can_be_null, map))
+             goto make_normal_jump;
+           /* If we might introduce a new update point inside the loop,
+              we can't optimize because then update_jump would update a
+              wrong failure point.  Thus we have to be quite careful here. */
+         loop_p1:
+           /* loop until we find something that consumes a character */
+           switch (*p1++)
+             {
+              case Cbol:
+              case Ceol:
+              case Cbegbuf:
+              case Cendbuf:
+              case Cwordbeg:
+              case Cwordend:
+              case Cwordbound:
+              case Cnotwordbound:
+#ifdef emacs
+              case Cemacs_at_dot:
+#endif /* emacs */
+                goto loop_p1;
+              case Cstart_memory:
+              case Cend_memory:
+                p1++;
+                goto loop_p1;
+             case Cexact:
+               ch = (unsigned char)*p1++;
+               if (map[ch])
+                 goto make_normal_jump;
+               break;
+             case Canychar:
+               for (b = 0; b < 256; b++)
+                 if (b != '\n' && map[b])
+                   goto make_normal_jump;
+               break;
+             case Cset:
+               for (b = 0; b < 256; b++)
+                 if ((p1[b >> 3] & (1 << (b & 7))) && map[b])
+                   goto make_normal_jump;
+               p1 += 256/8;
+               break;
+             default:
+               goto make_normal_jump;
+             }
+           /* now we know that we can't backtrack. */
+           while (p1 != p2 - 3)
+             {
+               switch (*p1++)
+                 {
+                 case Cend:
+                   abort();  /* we certainly shouldn't get this inside loop */
+                   /*NOTREACHED*/
+                 case Cbol:
+                 case Ceol:
+                 case Canychar:
+                 case Cbegbuf:
+                 case Cendbuf:
+                 case Cwordbeg:
+                 case Cwordend:
+                 case Cwordbound:
+                 case Cnotwordbound:
+#ifdef emacs
+                 case Cemacs_at_dot:
+#endif /* emacs */
+                   break;
+                 case Cset:
+                   p1 += 256/8;
+                   break;
+                 case Cexact:
+                 case Cstart_memory:
+                 case Cend_memory:
+                 case Cmatch_memory:
+                 case Csyntaxspec:
+                 case Cnotsyntaxspec:
+                   p1++;
+                   break;
+                 case Cjump:
+                 case Cstar_jump:
+                 case Cfailure_jump:
+                 case Cupdate_failure_jump:
+                 case Cdummy_failure_jump:
+                   goto make_normal_jump;
+                 default:
+                   printf("regexpr.c: processing star_jump: unknown op %d\n", p1[-1]);
+                   break;
+                 }
+             }
+           goto make_update_jump;
+         }
+       make_normal_jump:
+         /* printf("changing to normal jump\n"); */
+         code -= 3;
+         *code = Cjump;
+         break;
+       make_update_jump:
+         /* printf("changing to update jump\n"); */
+         code -= 2;
+         a += 3;  /* jump to after the Cfailure_jump */
+         code[-1] = Cupdate_failure_jump;
+         code[0] = a & 0xff;
+         code[1] = a >> 8;
+         /* fall to next case */
+       case Cupdate_failure_jump:
+         failure_sp[-1].text = text;
+         failure_sp[-1].partend = partend;
+         /* fall to next case */
+       case Cjump:
+         a = (unsigned char)*code++;
+         a |= (unsigned char)*code++ << 8;
+         code += (int)(short)a;
+         break;
+       case Cdummy_failure_jump:
+       case Cfailure_jump:
+         if (failure_sp == failure_stack_end)
+           {
+             if (failure_stack_start != initial_failure_stack)
+               goto error;
+             failure_stack_start = (struct failure_point *)
+               malloc(MAX_FAILURES * sizeof(*failure_stack_start));
+             failure_stack_end = failure_stack_start + MAX_FAILURES;
+             memcpy((char *)failure_stack_start, (char *)initial_failure_stack,
+                    INITIAL_FAILURES * sizeof(*failure_stack_start));
+             failure_sp = failure_stack_start + INITIAL_FAILURES;
+           }
+         a = (unsigned char)*code++;
+         a |= (unsigned char)*code++ << 8;
+         a = (int)(short)a;
+         if (code[-3] == Cdummy_failure_jump)
+           { /* this is only used in plus */
+             assert(*code == Cfailure_jump);
+             b = (unsigned char)code[1];
+             b |= (unsigned char)code[2] << 8;
+             failure_sp->code = code + (int)(short)b + 3;
+             failure_sp->text = NULL;
+             code += a;
+           }
+         else
+           {
+             failure_sp->code = code + a;
+             failure_sp->text = text;
+             failure_sp->partend = partend;
+           }
+         failure_sp++;
+         break;
+       case Cbegbuf:
+         if (text == string1)
+           break;
+         goto fail;
+       case Cendbuf:
+         if (size2 == 0 ? text == string1 + size1 : text == string2 + size2)
+           break;
+         goto fail;
+       case Cwordbeg:
+         if (text == string2 + size2)
+           goto fail;
+         if (size2 == 0 && text == string1 + size1)
+           goto fail;
+         if (SYNTAX(text == string1 + size1 ? *string1 : *text) != Sword)
+           goto fail;
+         if (text == string1)
+           break;
+         if (SYNTAX(text[-1]) != Sword)
+           break;
+         goto fail;
+       case Cwordend:
+         if (text == string1)
+           goto fail;
+         if (SYNTAX(text[-1]) != Sword)
+           goto fail;
+         if (text == string2 + size2)
+           break;
+         if (size2 == 0 && text == string1 + size1)
+           break;
+         if (SYNTAX(*text) == Sword)
+           goto fail;
+         break;
+       case Cwordbound:
+         /* Note: as in gnu regexp, this also matches at the beginning
+            and end of buffer. */
+         if (text == string1 || text == string2 + size2 ||
+             (size2 == 0 && text == string1 + size1))
+           break;
+         if ((SYNTAX(text[-1]) == Sword) ^
+             (SYNTAX(text == string1 + size1 ? *string2 : *text) == Sword))
+           break;
+         goto fail;
+       case Cnotwordbound:
+         /* Note: as in gnu regexp, this never matches at the beginning
+            and end of buffer. */
+         if (text == string1 || text == string2 + size2 ||
+             (size2 == 0 && text == string1 + size1))
+           goto fail;
+         if (!((SYNTAX(text[-1]) == Sword) ^
+               (SYNTAX(text == string1 + size1 ? *string2 : *text) == Sword)))
+           goto fail;
+         break;
+       case Csyntaxspec:
+         NEXTCHAR(ch);
+         if (SYNTAX(ch) != (unsigned char)*code++)
+           goto fail;
+         break;
+       case Cnotsyntaxspec:
+         NEXTCHAR(ch);
+         if (SYNTAX(ch) != (unsigned char)*code++)
+           break;
+         goto fail;
+#ifdef emacs
+       case Cemacs_at_dot:
+         if (PTR_CHAR_POS((unsigned char *)text) + 1 != point)
+           goto fail;
+         break;
+#endif /* emacs */
+       default:
+         abort();
+         /*NOTREACHED*/
+       }
+    }
+  abort();
+  /*NOTREACHED*/
+
+ fail:
+  if (failure_sp != failure_stack_start)
+    {
+      failure_sp--;
+      text = failure_sp->text;
+      if (text == NULL)
+       goto fail;
+      partend = failure_sp->partend;
+      code = failure_sp->code;
+      goto continue_matching;
+    }
+  if (failure_stack_start != initial_failure_stack)
+    free((char *)failure_stack_start);
+  return -1;
+
+ error:
+  if (failure_stack_start != initial_failure_stack)
+    free((char *)failure_stack_start);
+  return -2;
+}
+
+#undef PREFETCH
+#undef NEXTCHAR
+#undef PUSH_FAILURE
+
+int re_match(bufp, string, size, pos, regs)
+regexp_t bufp;
+char *string;
+int size, pos;
+regexp_registers_t regs;
+{
+  return re_match_2(bufp, string, size, (char *)NULL, 0, pos, regs, size);
+}
+
+int re_search_2(bufp, string1, size1, string2, size2, pos, range, regs,
+               mstop)
+regexp_t bufp;
+char *string1, *string2;
+int size1, size2, pos, range, mstop;
+regexp_registers_t regs;
+{
+  char *fastmap, *translate, *text, *partstart, *partend;
+  int dir, ret;
+  char anchor;
+  
+  assert(size1 >= 0 && size2 >= 0 && pos >= 0 && mstop >= 0);
+  assert(pos + range >= 0 && pos + range <= size1 + size2);
+  assert(pos <= mstop);
+  
+  fastmap = bufp->fastmap;
+  translate = bufp->translate;
+  if (fastmap && !bufp->fastmap_accurate)
+    re_compile_fastmap(bufp);
+  anchor = bufp->anchor;
+  if (bufp->can_be_null == 1) /* can_be_null == 2: can match null at eob */
+    fastmap = NULL;
+  if (range < 0)
+    {
+      dir = -1;
+      range = -range;
+    }
+  else
+    dir = 1;
+  if (anchor == 2) {
+    if (pos != 0)
+      return -1;
+    else
+      range = 0;
+  }
+  for (; range >= 0; range--, pos += dir)
+    {
+      if (fastmap)
+       {
+         if (dir == 1)
+           { /* searching forwards */
+             if (pos < size1)
+               {
+                 text = string1 + pos;
+                 if (pos + range > size1)
+                   partend = string1 + size1;
+                 else
+                   partend = string1 + pos + range;
+               }
+             else
+               {
+                 text = string2 + pos - size1;
+                 partend = string2 + pos + range - size1;
+               }
+             partstart = text;
+             if (translate)
+               while (text != partend &&
+                      !fastmap[(unsigned char)
+                               translate[(unsigned char)*text]])
+                 text++;
+             else
+               while (text != partend && !fastmap[(unsigned char)*text])
+                 text++;
+             pos += text - partstart;
+             range -= text - partstart;
+             if (pos == size1 + size2 && bufp->can_be_null == 0)
+               return -1;
+           }
+         else
+           { /* searching backwards */
+             if (pos <= size1)
+               {
+                 text = string1 + pos;
+                 partstart = string1 + pos - range;
+               }
+             else
+               {
+                 text = string2 + pos - size1;
+                 if (range < pos - size1)
+                   partstart = string2 + pos - size1 - range;
+                 else
+                   partstart = string2;
+               }
+             partend = text;
+             if (translate)
+               while (text != partstart &&
+                      !fastmap[(unsigned char)
+                               translate[(unsigned char)*text]])
+                 text--;
+             else
+               while (text != partstart &&
+                      !fastmap[(unsigned char)*text])
+                 text--;
+             pos -= partend - text;
+             range -= partend - text;
+           }
+       }
+      if (anchor == 1)
+       { /* anchored to begline */
+         if (pos > 0 &&
+             (pos <= size1 ? string1[pos - 1] :
+              string2[pos - size1 - 1]) != '\n')
+           continue;
+       }
+      assert(pos >= 0 && pos <= size1 + size2);
+      ret = re_match_2(bufp, string1, size1, string2, size2, pos, regs, mstop);
+      if (ret >= 0)
+       return pos;
+      if (ret == -2)
+       return -2;
+    }
+  return -1;
+}
+
+int re_search(bufp, string, size, startpos, range, regs)
+regexp_t bufp;
+char *string;
+int size, startpos, range;
+regexp_registers_t regs;
+{
+  return re_search_2(bufp, string, size, (char *)NULL, 0,
+                    startpos, range, regs, size);
+}
+
+static struct re_pattern_buffer re_comp_buf;
+
+char *re_comp(s)
+char *s;
+{
+  if (s == NULL)
+    {
+      if (!re_comp_buf.buffer)
+       return "Out of memory";
+      return NULL;
+    }
+  if (!re_comp_buf.buffer)
+    {
+      /* the buffer will be allocated automatically */
+      re_comp_buf.fastmap = malloc(256);
+      re_comp_buf.translate = NULL;
+    }
+  return re_compile_pattern(s, strlen(s), &re_comp_buf);
+}
+
+int re_exec(s)
+char *s;
+{
+  int len = strlen(s);
+  
+  return re_search(&re_comp_buf, s, len, 0, len, (regexp_registers_t)NULL) >= 0;
+}
+
+/* POSIX Compatibility */
+
+int regcomp(regex_t *preg, const char *regex, int cflags)
+{
+  int syntax = 0;
+  memset(preg, 0, sizeof(*preg));
+  if (cflags & REG_EXTENDED)
+    syntax |= (RE_CONTEXT_INDEP_OPS | RE_NO_BK_PARENS | RE_NO_BK_VBAR);
+  re_set_syntax(syntax);
+  if (re_compile_pattern((char *)regex, strlen(regex), preg) == NULL)
+    return 0;
+  return -1;
+}
+
+int regexec(const regex_t *preg, const char *string, size_t nmatch,
+            regmatch_t pmatch[], int eflags)
+{
+  int len = strlen(string);
+  int ret;
+  
+  ret = re_search((regex_t *)preg, (char *)string, len, 0, len, (regexp_registers_t)NULL);
+  if (ret >= 0)
+    return 0;
+
+  return ret;
+}
+
+size_t regerror(int errcode, const regex_t *preg, char *errbuf,
+                size_t errbuf_size)
+{
+  return -1;
+}
+
+void regfree(regex_t *preg)
+{
+  free(preg->buffer);
+}
+
+#ifdef TEST_REGEXP
+
+int main()
+{
+  char buf[500];
+  char *cp;
+  struct re_pattern_buffer exp;
+  struct re_registers regs;
+  int a,pos;
+  char fastmap[256];
+
+  exp.allocated = 0;
+  exp.buffer = 0;
+  exp.translate = NULL;
+  exp.fastmap = fastmap;
+
+  /* re_set_syntax(RE_NO_BK_PARENS|RE_NO_BK_VBAR|RE_ANSI_HEX); */
+
+  while (1)
+    {
+      printf("Enter regexp:\n");
+      gets(buf);
+      cp=re_compile_pattern(buf, strlen(buf), &exp);
+      if (cp)
+       {
+         printf("Error: %s\n", cp);
+         continue;
+       }
+      re_compile_fastmap(&exp);
+      printf("dump:\n");
+      for (pos = 0; pos < exp.used;)
+       {
+         printf("%d: ", pos);
+         switch (exp.buffer[pos++])
+           {
+           case Cend:
+             strcpy(buf, "end");
+             break;
+           case Cbol:
+             strcpy(buf, "bol");
+             break;
+           case Ceol:
+             strcpy(buf, "eol");
+             break;
+           case Cset:
+             strcpy(buf, "set ");
+             for (a = 0; a < 256/8; a++)
+               sprintf(buf+strlen(buf)," %02x",
+                       (unsigned char)exp.buffer[pos++]);
+             break;
+           case Cexact:
+             sprintf(buf, "exact '%c' 0x%x", exp.buffer[pos],
+                     (unsigned char)exp.buffer[pos]);
+             pos++;
+             break;
+           case Canychar:
+             strcpy(buf, "anychar");
+             break;
+           case Cstart_memory:
+             sprintf(buf, "start_memory %d", exp.buffer[pos++]);
+             break;
+           case Cend_memory:
+             sprintf(buf, "end_memory %d", exp.buffer[pos++]);
+             break;
+           case Cmatch_memory:
+             sprintf(buf, "match_memory %d", exp.buffer[pos++]);
+             break;
+           case Cjump:
+           case Cdummy_failure_jump:
+           case Cstar_jump:
+           case Cfailure_jump:
+           case Cupdate_failure_jump:
+             a = (unsigned char)exp.buffer[pos++];
+             a += (unsigned char)exp.buffer[pos++] << 8;
+             a = (int)(short)a;
+             switch (exp.buffer[pos-3])
+               {
+               case Cjump:
+                 cp = "jump";
+                 break;
+               case Cstar_jump:
+                 cp = "star_jump";
+                 break;
+               case Cfailure_jump:
+                 cp = "failure_jump";
+                 break;
+               case Cupdate_failure_jump:
+                 cp = "update_failure_jump";
+                 break;
+               case Cdummy_failure_jump:
+                 cp = "dummy_failure_jump";
+                 break;
+               default:
+                 cp = "unknown jump";
+                 break;
+               }
+             sprintf(buf, "%s %d", cp, a + pos);
+             break;
+           case Cbegbuf:
+             strcpy(buf,"begbuf");
+             break;
+           case Cendbuf:
+             strcpy(buf,"endbuf");
+             break;
+           case Cwordbeg:
+             strcpy(buf,"wordbeg");
+             break;
+           case Cwordend:
+             strcpy(buf,"wordend");
+             break;
+           case Cwordbound:
+             strcpy(buf,"wordbound");
+             break;
+           case Cnotwordbound:
+             strcpy(buf,"notwordbound");
+             break;
+           default:
+             sprintf(buf, "unknown code %d",
+                     (unsigned char)exp.buffer[pos - 1]);
+             break;
+           }
+         printf("%s\n", buf);
+       }
+      printf("can_be_null = %d uses_registers = %d anchor = %d\n",
+            exp.can_be_null, exp.uses_registers, exp.anchor);
+      
+      printf("fastmap:");
+      for (a = 0; a < 256; a++)
+       if (exp.fastmap[a])
+         printf(" %d", a);
+      printf("\n");
+      printf("Enter strings.  An empty line terminates.\n");
+      while (fgets(buf, sizeof(buf), stdin))
+       {
+         if (buf[0] == '\n')
+           break;
+         a = re_search(&exp, buf, strlen(buf), 0, strlen(buf), &regs);
+         printf("search returns %d\n", a);
+         if (a != -1)
+           {
+             for (a = 0; a < RE_NREGS; a++)
+               {
+                 printf("buf %d: %d to %d\n", a, regs.start[a], regs.end[a]);
+               }
+           }
+       }
+    }
+}
+
+#endif /* TEST_REGEXP */
diff --git a/lib/contrib/regexpr.h b/lib/contrib/regexpr.h
new file mode 100644 (file)
index 0000000..b692735
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+
+regexpr.h
+
+Author: Tatu Ylonen <ylo@ngs.fi>
+
+Copyright (c) 1991 Tatu Ylonen, Espoo, Finland
+
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation is hereby granted without fee, provided that the
+above copyright notice appears in all source code copies, the name of
+Tatu Ylonen is not used to advertise products containing this software
+or a derivation thereof, and all modified versions are clearly marked
+as such.
+
+This software is provided "as is" without express or implied warranty.
+
+Created: Thu Sep 26 17:15:36 1991 ylo
+Last modified: Fri Jan  3 12:05:45 1992 ylo
+
+*/
+
+/* $Id$ */
+
+#ifndef REGEXPR_H
+#define REGEXPR_H
+
+#define RE_NREGS       10  /* number of registers available */
+
+typedef struct re_pattern_buffer
+{
+  char *buffer;         /* compiled pattern */
+  int allocated;        /* allocated size of compiled pattern */
+  int used;             /* actual length of compiled pattern */
+  char *fastmap;        /* fastmap[ch] is true if ch can start pattern */
+  char *translate;      /* translation to apply during compilation/matching */
+  char fastmap_accurate; /* true if fastmap is valid */
+  char can_be_null;     /* true if can match empty string */
+  char uses_registers;  /* registers are used and need to be initialized */
+  char anchor;          /* anchor: 0=none 1=begline 2=begbuf */
+} *regexp_t;
+
+typedef struct re_registers
+{
+  int start[RE_NREGS];  /* start offset of region */
+  int end[RE_NREGS];    /* end offset of region */
+} *regexp_registers_t;
+
+/* bit definitions for syntax */
+#define RE_NO_BK_PARENS                1    /* no quoting for parentheses */
+#define RE_NO_BK_VBAR          2    /* no quoting for vertical bar */
+#define RE_BK_PLUS_QM          4    /* quoting needed for + and ? */
+#define RE_TIGHT_VBAR          8    /* | binds tighter than ^ and $ */
+#define RE_NEWLINE_OR          16   /* treat newline as or */
+#define RE_CONTEXT_INDEP_OPS   32   /* ^$?*+ are special in all contexts */
+#define RE_ANSI_HEX            64   /* ansi sequences (\n etc) and \xhh */
+#define RE_NO_GNU_EXTENSIONS   128   /* no gnu extensions */
+
+/* definitions for some common regexp styles */
+#define RE_SYNTAX_AWK  (RE_NO_BK_PARENS|RE_NO_BK_VBAR|RE_CONTEXT_INDEP_OPS)
+#define RE_SYNTAX_EGREP        (RE_SYNTAX_AWK|RE_NEWLINE_OR)
+#define RE_SYNTAX_GREP (RE_BK_PLUS_QM|RE_NEWLINE_OR)
+#define RE_SYNTAX_EMACS        0
+
+int re_set_syntax(int syntax);
+/* This sets the syntax to use and returns the previous syntax.  The
+   syntax is specified by a bit mask of the above defined bits. */
+
+char *re_compile_pattern(char *regex, int regex_size, regexp_t compiled);
+/* This compiles the regexp (given in regex and length in regex_size).
+   This returns NULL if the regexp compiled successfully, and an error
+   message if an error was encountered.  The buffer field must be
+   initialized to a memory area allocated by malloc (or to NULL) before
+   use, and the allocated field must be set to its length (or 0 if buffer is
+   NULL).  Also, the translate field must be set to point to a valid
+   translation table, or NULL if it is not used. */
+
+int re_match(regexp_t compiled, char *string, int size, int pos,
+            regexp_registers_t regs);
+/* This tries to match the regexp against the string.  This returns the
+   length of the matched portion, or -1 if the pattern could not be
+   matched and -2 if an error (such as failure stack overflow) is
+   encountered. */
+
+int re_match_2(regexp_t compiled, char *string1, int size1,
+             char *string2, int size2, int pos, regexp_registers_t regs,
+              int mstop);
+/* This tries to match the regexp to the concatenation of string1 and
+   string2.  This returns the length of the matched portion, or -1 if the
+   pattern could not be matched and -2 if an error (such as failure stack
+   overflow) is encountered. */
+
+int re_search(regexp_t compiled, char *string, int size, int startpos,
+             int range, regexp_registers_t regs);
+/* This rearches for a substring matching the regexp.  This returns the first
+   index at which a match is found.  range specifies at how many positions to
+   try matching; positive values indicate searching forwards, and negative
+   values indicate searching backwards.  mstop specifies the offset beyond
+   which a match must not go.  This returns -1 if no match is found, and
+   -2 if an error (such as failure stack overflow) is encountered. */
+
+int re_search_2(regexp_t compiled, char *string1, int size1,
+               char *string2, int size2, int startpos, int range,
+               regexp_registers_t regs, int mstop);
+/* This is like re_search, but search from the concatenation of string1 and
+   string2.  */
+
+void re_compile_fastmap(regexp_t compiled);
+/* This computes the fastmap for the regexp.  For this to have any effect,
+   the calling program must have initialized the fastmap field to point
+   to an array of 256 characters. */
+
+char *re_comp(char *s);
+/* BSD 4.2 regex library routine re_comp.  This compiles the regexp into
+   an internal buffer.  This returns NULL if the regexp was compiled
+   successfully, and an error message if there was an error. */
+
+int re_exec(char *s);
+/* BSD 4.2 regexp library routine re_exec.  This returns true if the string
+   matches the regular expression (that is, a matching part is found
+   anywhere in the string). */
+
+/* POSIX Compatibility */
+#define regex_t struct re_pattern_buffer
+#define regmatch_t struct re_registers
+#define REG_EXTENDED 1
+#define REG_ICASE (REG_EXTENDED << 1)
+#define REG_NEWLINE (REG_ICASE << 1)
+#define REG_NOSUB (REG_NEWLINE << 1)
+#define REG_NOTBOL 1
+#define REG_NOTEOL (REG_NOTBOL << 1)
+int regcomp(regex_t *preg, const char *regex, int cflags);
+int regexec(const regex_t *preg, const char *string, size_t nmatch,
+           regmatch_t pmatch[], int eflags);
+size_t regerror(int errcode, const regex_t *preg, char *errbuf,
+               size_t errbuf_size);
+void regfree(regex_t *preg);
+
+#endif /* REGEXPR_H */
index ec18e30c98b6dd2f872a495029a86a17893cafb1..4415d45f33a67675ab78177c33457d08ab4664d5 100644 (file)
@@ -77,18 +77,6 @@ If your system doesn't provide iconv() function in its native libraries
 you may want to use libiconv instead.  The DIR is the upper path in your
 system which contains lib/ and include/ for libiconv (e.g. /usr/local).
 
-<br />&nbsp;<br />
-<tt>--without-irssi</tt><br />
-<tt>--without-silcd</tt>
-
-<br />&nbsp;<br />
-By default the SILC Toolkit will also build the Irssi SILC client and
-the SILC Server which use the SILC Toolkit as well.  If you do not
-wish to compile these applications you can give --without-irssi to
-not compile Irssi SILC client (irssi/ directory) and/or --without-silcd
-to not compile SILC Server (silcd/ directory).  Other applications
-the Toolkit does not build automatically.
-
 <br />&nbsp;<br />
 <tt>--without-pthreads</tt>
 
index a38209e9df6b57aa618222c32ed85b97a7acfb17..562282a5a99be60ac84f5c7b7f008043c9103059 100644 (file)
@@ -399,6 +399,20 @@ SilcPublicKey public_key
 </td>
 </tr>
 
+<tr>
+<td><small>SILC_COMMAND_SERVICE</td>
+<td><small>
+Returns the service list in the server, or information on the accepted
+and authenticated service.  The 'service_list' maybe NULL if server does
+not support any services.  It is NULL also when 'name' is not NULL.  The
+'service_list' is a comma separated list of services the server supports.
+The 'name' MAY be NULL also.  The 'name' is the requested service, and it is
+non-NULL only if server accepted and authenticated client's request.
+</td>
+<td width="50%"><small>const char *server_list, const char *service_name
+</td>
+</tr>
+
 </table>
 
 <br />&nbsp;<br />
index 780c7f312245d9893499502be4a8d4fd51a692fb..ba6583172e1a2aec31e50ad4577241258aefd30c 100644 (file)
@@ -29,7 +29,7 @@ and other utility functions.
 <b>Including Library Headers</b>
 
 <br />&nbsp;<br />
-Your application must include the following includes in your sources to 
+Your application must include the following includes in your sources to
 get access all SILC Client Library routines:
 
 <br />&nbsp;<br />
@@ -83,7 +83,7 @@ manner:
 `context' can be some application specific context that will be saved into
 the SilcClient object.  It is up to the caller to free this context.
 SilcClient is always passed to the application thus the application
-specific context can be retrieved from the SilcClient object.  See 
+specific context can be retrieved from the SilcClient object.  See
 `client.h' file for detailed definition of SilcClient object.
 
 <br />&nbsp;<br />
@@ -179,30 +179,30 @@ should initialize the user interface.
 <b>Running the Client in GUI application</b>
 
 <br />&nbsp;<br />
-Many GUI applications has their own main loop or event loop, which they 
-would like to use or are forced to use by the underlaying system.  If you 
-are developing for example GUI application on Unix system, and you are 
-using GTK+ or QT as GUI library you would probably like to use their own 
-main loop.  SILC Client can be run under external main loop as well.  The 
-interface provides a function silc_client_run_one which will run the 
-client library once, and returns immediately.  During that running it can 
-process incoming data and send outgoing data, but it is guaranteed that it 
+Many GUI applications has their own main loop or event loop, which they
+would like to use or are forced to use by the underlaying system.  If you
+are developing for example GUI application on Unix system, and you are
+using GTK+ or QT as GUI library you would probably like to use their own
+main loop.  SILC Client can be run under external main loop as well.  The
+interface provides a function silc_client_run_one which will run the
+client library once, and returns immediately.  During that running it can
+process incoming data and send outgoing data, but it is guaranteed that it
 will not block the calling process.
 
 <br />&nbsp;<br />
-It is suggested that you would call this function as many times in a 
-second as possible to provide smooth action for the client library.  You 
-can use an timeout task, or an idle task provided by your GUI library to 
-accomplish this.  After you have initialized the client library with 
-silc_client_init, you should register the timeout task or idle task that 
-will call the silc_client_run_one periodically.  In the Toolkit package 
-there is GTK-- GUI example in silcer/ directory.  That example calls the 
-silc_client_run_one every 50 milliseconds, and it should be sufficient for 
+It is suggested that you would call this function as many times in a
+second as possible to provide smooth action for the client library.  You
+can use an timeout task, or an idle task provided by your GUI library to
+accomplish this.  After you have initialized the client library with
+silc_client_init, you should register the timeout task or idle task that
+will call the silc_client_run_one periodically.  In the Toolkit package
+there is GTK-- GUI example in silcer/ directory.  That example calls the
+silc_client_run_one every 50 milliseconds, and it should be sufficient for
 smooth working.
 
 <br />&nbsp;<br />
-For Win32 the silc_client_run can be used instead of using the Windows's 
-own event loop.  However, if you would like to use the silc_client_run_one 
+For Win32 the silc_client_run can be used instead of using the Windows's
+own event loop.  However, if you would like to use the silc_client_run_one
 also on Win32 systems it is possible.
 
 
@@ -210,7 +210,7 @@ also on Win32 systems it is possible.
 <b>Running Client in GTK--</b>
 
 <br />&nbsp;<br />
-Here is a short example how to run the SILC Client libary under the 
+Here is a short example how to run the SILC Client libary under the
 Gnome/GTK--'s main loop:
 
 <br />&nbsp;<br />
@@ -238,8 +238,8 @@ Gnome::Main::timeout.connect(slot(this, &YourClass::silc_scheduler), 50);<br />
 </tt>
 
 <br />&nbsp;<br />
-This will call the function silc_scheduler every 50 millisecconds, which 
-on the otherhand will call silc_client_run_one, which will make the SILC 
+This will call the function silc_scheduler every 50 millisecconds, which
+on the otherhand will call silc_client_run_one, which will make the SILC
 Client library work on the background of the GUI application.
 
 
@@ -263,9 +263,9 @@ screen.  IRC is usually implemented this way, however it is not the
 necessary way to associate the client's connections.  SilcClientConnection
 object is provided by the library (and is always passed to the application)
 that can be used in the application to associate the connection from the
-library.  Application specific context can be saved to the 
+library.  Application specific context can be saved to the
 SilcClientConnection object which then can be retrieved in the application,
-thus perhaps associate the connection with what ever object in 
+thus perhaps associate the connection with what ever object in
 application (window or something else).
 
 
@@ -299,7 +299,7 @@ After connection has been created application must call:
 
 <br />&nbsp;<br />
 NOTE: These calls are performed only and only if application did not call
-silc_client_connect_to_server function, but performed the connecting 
+silc_client_connect_to_server function, but performed the connecting
 process manually.
 
 
@@ -317,21 +317,21 @@ debugging is enabled.
 Then, to say in your application you would like to use the debugging use
 the SILC_ENABLE_DEBUG macro.  Put this macro to your main header file, or
 some other file that needs the debugging enabled.  After using this macro
-you are able to use the debugging routines provided by the SILC Toolkit.  
+you are able to use the debugging routines provided by the SILC Toolkit.
 Note that, the Toolkit library must be compiled with --enable-debug for
 this macro to have any effect.
 
 <br />&nbsp;<br />
-To turn on the run-time debugging set the global variable "silc_debug" to
-TRUE.  To see packet hexdumps you can set also "silc_debug_hexdump" to TRUE.
-Hexdumps can create more debug log so not setting it to TRUE by default is
-probably best.  To get debug messages out of specific modules you can set
-a debug string with silc_log_set_debug_string function.  The function takes
-regex string as argument, for example:
+To turn on the run-time debugging call function silc_log_debug with TRUE
+value.  To see packet hexdumps you can call also silc_log_debug_hexdump
+with TRUE value.  Hexdumps can create more debug log so not setting it
+to TRUE by default is probably best.  To get debug messages out of specific
+modules you can set a debug string with silc_log_set_debug_string function.
+The function takes regex string as argument, for example:
 
 <br />&nbsp;<br />
 <tt>
-&nbsp;&nbsp;silc_debug = TRUE;<br />
+&nbsp;&nbsp;silc_log_debug(TRUE);<br />
 &nbsp;&nbsp;silc_log_set_debug_string("*");<br />
 </tt>
 
@@ -457,7 +457,7 @@ int main()
        /* Start the client. This will start the scheduler. At this phase
           the user might have the user interface in front of him already.
           He will use the user interface to create the connection to the
-          server for example. When this function returns the program is 
+          server for example. When this function returns the program is
          ended. */
        silc_client_run(client);
 
index 0a1a2bce02be1881d04adf7090e0fed0e5abdd0e..947bcbc08d5174b836f7993a808d4a3c42d01555 100644 (file)
@@ -7,6 +7,6 @@ Name: @PACKAGE@
 Description: SILC Library
 Version: @VERSION@
 Conflicts: libsilc <= 0.9.12
-Libs: @LIBS@ -L${libdir} -lsilc
+Libs: -L${libdir} -lsilc @LIBS@
 Cflags: -I${includedir}
 
index cd5854f705ee95ed9d4322dfa1ca0386d296a484..d0437b05282a87eb844188ec1314c391d11acf6a 100644 (file)
@@ -8,6 +8,6 @@ Description: SILC Client Library
 Version: @VERSION@
 Conflicts: libsilc <= 0.9.12
 Requires: silc = @VERSION@
-Libs: @LIBS@ -L${libdir} -lsilcclient
+Libs: -L${libdir} -lsilcclient @LIBS@
 Cflags: -I${includedir}
 
index 4fe166a873b54004f30519bb3ffd58b1dfd550ce..7c03f1c49cde424de92cb0a9e11b55e74696fdb9 100644 (file)
@@ -5,7 +5,9 @@
 
    At the end of this file SilcClientOperation structure is defined, and
    it is the one the you will give as an argument to the silc_client_alloc
-   function. See also lib/silcclient/README file, and silcclient.h. */
+   function. See also lib/silcclient/README file, and silcclient.h.
+
+   You may freely use this file in your application. */
 
 
 /* Message sent to the application by library. `conn' associates the
index e2537fe69ca3b2a7a5daf0347e83ef4f63895531..0122fee97007d4129bb0c21be8320322224e3ac5 100644 (file)
@@ -2624,6 +2624,47 @@ SILC_CLIENT_CMD_FUNC(getkey)
   silc_client_command_free(cmd);
 }
 
+/* Command SERVICE.  Negotiates service agreement with server. */
+/* XXX incomplete */
+
+SILC_CLIENT_CMD_FUNC(service)
+{
+  SilcClientCommandContext cmd = (SilcClientCommandContext)context;
+  SilcClientConnection conn = cmd->conn;
+  SilcBuffer buffer;
+  char *name;
+
+  if (!cmd->conn) {
+    SILC_NOT_CONNECTED(cmd->client, cmd->conn);
+    COMMAND_ERROR(SILC_STATUS_ERR_NOT_REGISTERED);
+    goto out;
+  }
+
+  if (cmd->argc < 2) {
+    SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+       "Usage: /SERVICE [<service name>] [-pubkey]");
+    COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
+
+  name = cmd->argv[1];
+
+  /* Send SERVICE command to the server */
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_SERVICE,
+                                         ++conn->cmd_ident, 1,
+                                         1, name, strlen(name));
+  silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND,
+                         NULL, 0, NULL, NULL, buffer->data,
+                         buffer->len, TRUE);
+  silc_buffer_free(buffer);
+
+  /* Notify application */
+  COMMAND(SILC_STATUS_OK);
+
+ out:
+  silc_client_command_free(cmd);
+}
+
 /* Register a new command indicated by the `command' to the SILC client.
    The `name' is optional command name.  If provided the command may be
    searched using the silc_client_command_find by that name.  The
@@ -2847,6 +2888,7 @@ void silc_client_commands_register(SilcClient client)
   SILC_CLIENT_CMD(leave, LEAVE, "LEAVE", 2);
   SILC_CLIENT_CMD(users, USERS, "USERS", 2);
   SILC_CLIENT_CMD(getkey, GETKEY, "GETKEY", 2);
+  SILC_CLIENT_CMD(service, SERVICE, "SERVICE", 10);
 
   SILC_CLIENT_CMD(connect, PRIV_CONNECT, "CONNECT", 3);
   SILC_CLIENT_CMD(close, PRIV_CLOSE, "CLOSE", 3);
@@ -2883,6 +2925,7 @@ void silc_client_commands_unregister(SilcClient client)
   SILC_CLIENT_CMDU(leave, LEAVE, "LEAVE");
   SILC_CLIENT_CMDU(users, USERS, "USERS");
   SILC_CLIENT_CMDU(getkey, GETKEY, "GETKEY");
+  SILC_CLIENT_CMDU(service, SERVICE, "SERVICE");
 
   SILC_CLIENT_CMDU(connect, PRIV_CONNECT, "CONNECT");
   SILC_CLIENT_CMDU(close, PRIV_CLOSE, "CLOSE");
index c6c597de1cb49f038bb03bc0ca96935819c0fb00..3f5e58a339102df5535a0b9db5fe8eb247da7ddd 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -153,6 +153,7 @@ SILC_CLIENT_CMD_FUNC(silcoper);
 SILC_CLIENT_CMD_FUNC(leave);
 SILC_CLIENT_CMD_FUNC(users);
 SILC_CLIENT_CMD_FUNC(getkey);
+SILC_CLIENT_CMD_FUNC(service);
 
 SILC_CLIENT_CMD_FUNC(shutdown);
 SILC_CLIENT_CMD_FUNC(close);
index 3c041113b70157cc139bea90bbf6ef96dd56e9ca..5c64922e3992af206be3aded6576c9f6a421f96c 100644 (file)
@@ -2046,6 +2046,32 @@ SILC_CLIENT_CMD_REPLY_FUNC(getkey)
   silc_client_command_reply_free(cmd);
 }
 
+/* Reply to SERVICE command. */
+/* XXX incomplete */
+
+SILC_CLIENT_CMD_REPLY_FUNC(service)
+{
+  SilcClientCommandReplyContext cmd = (SilcClientCommandReplyContext)context;
+  SilcUInt32 tmp_len;
+  unsigned char *service_list, *name;
+
+  COMMAND_CHECK_STATUS;
+
+  /* Get service list */
+  service_list = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+
+  /* Get requested service name */
+  name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+
+  /* Notify application */
+  COMMAND_REPLY((SILC_ARGS, service_list, name));
+
+ out:
+  SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_SERVICE);
+ err:
+  silc_client_command_reply_free(cmd);
+}
+
 SILC_CLIENT_CMD_REPLY_FUNC(quit)
 {
   silc_client_command_reply_free(context);
index 4eb8ca18ea428b63345f25ae0234cd7d9a8f14af..e07fcccbfb1649cb3ea0a6c20020408081f5c91e 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2003 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -111,6 +111,7 @@ SILC_CLIENT_CMD_REPLY_FUNC(silcoper);
 SILC_CLIENT_CMD_REPLY_FUNC(leave);
 SILC_CLIENT_CMD_REPLY_FUNC(users);
 SILC_CLIENT_CMD_REPLY_FUNC(getkey);
+SILC_CLIENT_CMD_REPLY_FUNC(service);
 SILC_CLIENT_CMD_REPLY_FUNC(quit);
 
 /* Internal command reply functions */
index 5e6ddf6e496ad20ac2315913f0c98df700b8af50..385f6807b452361a4821192422600f17fadb663a 100644 (file)
@@ -4,12 +4,11 @@
  
   Author: Pekka Riikonen <priikone@silcnet.org>
  
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index dc0e64823b193f4622ba1f072205ca6266f20e7a..f1d12909d1530636ed5ab531f90be8ef1f68a9fe 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index ee2b1edb9b68e942f41d0632dadc17bb3677d7a7..ad0bf94b76ecc3df13e71514c7fd2a20530a18cf 100644 (file)
@@ -2,14 +2,13 @@
 
   id.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 741ad9edb8cf9e884ca0fbf7dc74d280c9c10c94..05aed905cbe40af8eb4191bd4c16e8801651cbe1 100644 (file)
@@ -4,12 +4,11 @@
  
   Author: Pekka Riikonen <priikone@silcnet.org>
  
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 62fb5af0a1b3a7694477d5fe3e1738874ea3b2c1..a2a279cc4567b48abfc8f98439e655b49b47cb04 100644 (file)
@@ -8,8 +8,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index b5612d391e9e3267b30b15add1fff8dd529a0919..e445b0a4035e9bda852ef0893efd2e40a7fc60fc 100644 (file)
@@ -8,8 +8,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 98f9f2247a969229e9594c52a23ce83b07f85566..86a2a1be3cada203cbe39cddd885385dc1cad5f4 100644 (file)
@@ -4,12 +4,11 @@
  
   Author: Pekka Riikonen <priikone@silcnet.org>
   
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 0c7fb6a89489df2d1bc702cbb1dbcc0059b26a4a..41b6d7c5aaba5cc2b0e46509d88ef5c029349b62 100644 (file)
@@ -4,12 +4,11 @@
  
   Author: Pekka Riikonen <priikone@silcnet.org>
  
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index b2c9dd2790dc0b121ffc10c5f3919e452aa3dd01..2288208323e7bf60c369ebb2ab4ea094325bf092 100644 (file)
@@ -536,6 +536,7 @@ int silc_packet_receive(SilcSocketConnection sock);
  *    bool silc_packet_receive_process(SilcSocketConnection sock,
  *                                     bool local_is_router,
  *                                     SilcCipher cipher, SilcHmac hmac,
+ *                                     SilcUInt32 sequence,
  *                                     SilcPacketParserCallback parser,
  *                                     void *parser_context);
  *
index 6efd6582de3b6b87a82f2254d809e45ac851bfde..d9d3810fdd906e0eb1477e91ae1f7c35d91f4b20 100644 (file)
@@ -2,14 +2,13 @@
 
   rijndael.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index c0caeee7cd96f76657492f15a741fefbd71c5b1d..d67d8739863cd330a30f8a113555ea703b8e878d 100644 (file)
@@ -2,14 +2,13 @@
 
   blowfish.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 19126f03f226613159353f1c4e03909cbf5b1cfa..980036f1b14fb60210b2311eef0c476a787839f8 100644 (file)
@@ -2,14 +2,13 @@
 
   blowfish_internal.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index fe7351906037a48b61e9c25390f09c1a9fcfdd66..f83ce64388a377ca73f3c81eb54618fac36b2c65 100644 (file)
@@ -2,14 +2,13 @@
 
   cast.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1999 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 9ba848866791acc170a97503f37a5727d2b6a9c6..a70c95d2f9c69809d1356558ddafb9b7cb72c4bd 100644 (file)
@@ -2,14 +2,13 @@
 
   cast_internal.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1999 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 94eeef68f9f79058f87c33c2fa92d4317116468c..0fb9391cc0643864f149e06ca0f53c8f794f7292 100644 (file)
@@ -2,14 +2,13 @@
 
   ciphers.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 98e445c400c605055e0cd7a625685c1a1e559777..e254e68f93c1e9256b7140421abcb8f080e99514 100644 (file)
@@ -2,14 +2,13 @@
 
   ciphers_def.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1999 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 8b10d7ea4f5ff1801c3cd22de01f3c0fd34125f6..455f66de025dd88e8af7e8dfcd6a8e94e8099ed8 100644 (file)
@@ -2,14 +2,13 @@
 
   md5.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 35835b82451431817aa2dc89cf4731c236b474b9..66ec97bcccc485d50932decbe41d3ac4778cc9bf 100644 (file)
@@ -1,4 +1,4 @@
-/* file ripped from noiz-0.5. -Pekka */
+/* file ripped from noiz-0.5. -Pekka.  Public domain. */
 
 #ifndef MD5_INTERNAL_H
 #define MD5_INTERNAL_H
index ea6e6484e5fc5c0127b15b7825d820f2d71fa66f..65a362028e965b5f8e8661a85254fd76a360aeef 100644 (file)
@@ -2,14 +2,13 @@
 
   none.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 316ea8784130bd71534dfcd20babddaad2a6f436..8986bba83842c5b75c46505636bdd89657cecc46 100644 (file)
@@ -2,14 +2,13 @@
 
   none.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 /*
  * $Id$
  * $Log$
- * Revision 1.1  2000/06/27 11:36:54  priikone
- * Initial revision
+ * Revision 1.2  2005/05/10 18:31:17  priikone
+ *     Merged silc_1_0_branch to trunk.
+ *
+ * Revision 1.1.1.1.4.1  2005/04/30 15:31:26  priikone
+ *     Header changes.
+ *
+ * Revision 1.1.1.1  2000/06/27 11:36:54  priikone
+ *     Importet from internal CVS/Added Log headers.
  *
  *
  */
index 8909ebc04e5f622cc58809ef51eb04a855a5210e..afc374695ee22aea95f904754b7cd9b59d7932d0 100644 (file)
@@ -2,14 +2,13 @@
 
   rc5.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 23dc8cf86bb0df27e23f11ff9904d7486ef5ddd3..8f84c05d809eda2b7fee0eada6935abd8c46ff96 100644 (file)
@@ -2,14 +2,13 @@
 
   rc5_internal.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index ae8b7308adf599ca5f72e72b04ae3eb44d38ab1f..f3893e6839260712b3af5ba02889f8b5b3a9d621 100644 (file)
@@ -2,14 +2,13 @@
 
   rijndael_internal.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 7f9beb17d727d02cd835bbfeb7e90474b75c908b..c52f0b8a516ca25126a979cebb59fb8249bbd2ee 100644 (file)
@@ -1,51 +1,51 @@
 /*
- * rsa.c       RSA Public and Private key generation functions,
- *             RSA encrypt and decrypt functions.
- *
- * Author: Pekka Riikonen <priikone@silcnet.org>
- *
- * Copyright (C) 1997 - 2003 Pekka Riikonen
- *
- * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 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 General Public License for more details.
- *
* Created: Sat Mar  1 13:26:45 1997 pekka
- *
* RSA public key cryptographic algorithm used in this distribution is:
- *
*     Key generation:
*     p, q            primes
*     p != q
*     n = p * q       modulus
- *
*     Public key exponent:
*     e   relatively prime to (p-1) * (q-1)
*     Private key exponent:
*     d = e ^ -1 mod lcm(((p-1) * (q-1)))
- *
*     Encryption:
*     c = m ^ e mod n
*     Decryption:
*     m = c ^ d mod n
- *
* Supports CRT (Chinese Remainder Theorem) for private key operations.
- *
* The SSH's (Secure Shell), PGP's (Pretty Good Privacy) and RSAREF
* Toolkit were used as reference when coding this implementation. They
* all were a big help for me.
- *
* I also suggest reading Bruce Schneier's; Applied Cryptography, Second
* Edition, John Wiley & Sons, Inc. 1996. This book deals about RSA and
* everything else too about cryptography.
- *
- */
+
+  rsa.c        RSA Public and Private key generation functions,
+               RSA encrypt and decrypt functions.
+  Author: Pekka Riikonen <priikone@silcnet.org>
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
 the Free Software Foundation; version 2 of the License.
+  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 General Public License for more details.
+  Created: Sat Mar  1 13:26:45 1997 pekka
+  RSA public key cryptographic algorithm used in this distribution is:
      Key generation:
      p, q            primes
      p != q
      n = p * q       modulus
      Public key exponent:
      e   relatively prime to (p-1) * (q-1)
      Private key exponent:
      d = e ^ -1 mod lcm(((p-1) * (q-1)))
      Encryption:
      c = m ^ e mod n
      Decryption:
      m = c ^ d mod n
+  Supports CRT (Chinese Remainder Theorem) for private key operations.
+  The SSH's (Secure Shell), PGP's (Pretty Good Privacy) and RSAREF
+  Toolkit were used as reference when coding this implementation. They
+  all were a big help for me.
+  I also suggest reading Bruce Schneier's; Applied Cryptography, Second
+  Edition, John Wiley & Sons, Inc. 1996. This book deals about RSA and
+  everything else too about cryptography.
+*/
 /* $Id$ */
 
 /*
index 425ce6a96e57b0359d4b75994248e23e0b560fbc..d82c579df7725fbe73359993951a3dcdd4b116f4 100644 (file)
@@ -8,8 +8,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 378bd73cc1d93d677dd0ec4e737c00903ff4d685..40b4bf2f0c89789c010843763e462f60e0eaa7e8 100644 (file)
@@ -66,9 +66,11 @@ const SilcCipherObject silc_default_ciphers[] =
   { "cast-128-cbc", 16, 128, silc_cast_set_key, silc_cast_set_key_with_string,
     silc_cast_encrypt_cbc, silc_cast_decrypt_cbc,
     silc_cast_context_len },
+#ifdef SILC_DEBUG
   { "none", 0, 0, silc_none_set_key, silc_none_set_key_with_string,
     silc_none_encrypt_cbc, silc_none_decrypt_cbc,
     silc_none_context_len },
+#endif /* SILC_DEBUG */
 
   { NULL, 0, 0, NULL, NULL, NULL, NULL, NULL }
 };
index 95478d2e6f428710bc2932ca43f3dbb9407e1820..5947533430aba237c4dca56405e11f41584c040d 100644 (file)
@@ -2,14 +2,13 @@
 
   silccipher.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2002 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index d2c50121c8d42632d8e3922d8fd286b022ac830d..e92af48a5619e7b5dee6e0d9ea9eccd757176889 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silchmac.c 
+  silchmac.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1999 - 2001 Pekka Riikonen
+  Copyright (C) 1999 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 struct SilcHmacStruct {
   SilcHmacObject *hmac;
   SilcHash hash;
-
-  unsigned char *key;
-  SilcUInt32 key_len;
-
   unsigned char inner_pad[64];
   unsigned char outer_pad[64];
-  bool allocated_hash;         /* TRUE if the hash was allocated */
+  unsigned char *key;
+  unsigned int key_len        : 31;
+  unsigned int allocated_hash : 1;   /* TRUE if the hash was allocated */
 };
 
 #ifndef SILC_EPOC
@@ -146,7 +144,7 @@ bool silc_hmac_unregister(SilcHmacObject *hmac)
   return FALSE;
 }
 
-/* Function that registers all the default hmacs (all builtin ones). 
+/* Function that registers all the default hmacs (all builtin ones).
    The application may use this to register the default hmacs if
    specific hmacs in any specific order is not wanted. */
 
@@ -220,7 +218,7 @@ bool silc_hmac_alloc(const char *name, SilcHash hash, SilcHmac *new_hmac)
     silc_dlist_start(silc_hmac_list);
     while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) {
       if (!strcmp(entry->name, name)) {
-       (*new_hmac)->hmac = entry; 
+       (*new_hmac)->hmac = entry;
        return TRUE;
       }
     }
@@ -290,7 +288,7 @@ bool silc_hmac_is_supported(const char *name)
 
   if (!name)
     return FALSE;
-  
+
   if (silc_hmac_list) {
     silc_dlist_start(silc_hmac_list);
     while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) {
@@ -323,8 +321,8 @@ char *silc_hmac_get_supported()
     while ((entry = silc_dlist_get(silc_hmac_list)) != SILC_LIST_END) {
       len += strlen(entry->name);
       list = silc_realloc(list, len + 1);
-      
-      memcpy(list + (len - strlen(entry->name)), 
+
+      memcpy(list + (len - strlen(entry->name)),
             entry->name, strlen(entry->name));
       memcpy(list + len, ",", 1);
       len++;
@@ -337,8 +335,8 @@ char *silc_hmac_get_supported()
       entry = (SilcHmacObject *)&(silc_default_hmacs[i]);
       len += strlen(entry->name);
       list = silc_realloc(list, len + 1);
-      
-      memcpy(list + (len - strlen(entry->name)), 
+
+      memcpy(list + (len - strlen(entry->name)),
             entry->name, strlen(entry->name));
       memcpy(list + len, ",", 1);
       len++;
@@ -383,7 +381,7 @@ void silc_hmac_make(SilcHmac hmac, unsigned char *data,
    key. The key is sent as argument to the function. */
 
 void silc_hmac_make_with_key(SilcHmac hmac, unsigned char *data,
-                            SilcUInt32 data_len, 
+                            SilcUInt32 data_len,
                             unsigned char *key, SilcUInt32 key_len,
                             unsigned char *return_hash,
                             SilcUInt32 *return_len)
@@ -397,7 +395,7 @@ void silc_hmac_make_with_key(SilcHmac hmac, unsigned char *data,
 
 /* Creates the HMAC just as above except that the hash value is truncated
    to the truncated_len sent as argument. NOTE: One should not truncate to
-   less than half of the length of original hash value. However, this 
+   less than half of the length of original hash value. However, this
    routine allows these dangerous truncations. */
 
 void silc_hmac_make_truncated(SilcHmac hmac, unsigned char *data,
index 6b96b302b388f7863702ce5bac14e29e72401521..03269467075f4d9c1e231023ab9943ae2a2b336d 100644 (file)
@@ -2,14 +2,13 @@
 
   twofish.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 0cabe2c400e4f3c8ff521a6562c9674d8736534f..c0071ac00816bc1f557b00ac392b9476808138d1 100644 (file)
@@ -2,14 +2,13 @@
 
   twofish_internal.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index a65c9d88f9dceb8e777f30e090eb39172868001e..3afe5f6e370fd026df9de4696873155e63d4112a 100644 (file)
 
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
-if SILC_MP_NSS_MPI
-SUBDIRS = mpi
-else
-SUBDIRS =
-endif
+noinst_LTLIBRARIES = libsilcmath.la
 
-DIST_SUBDIRS = mpi
+if SILC_MP_SILCMATH
+MP_SOURCE = \
+#ifdef SILC_DIST_TMA
+       mp_tma.c \
+       tma.c
+#endif SILC_DIST_TMA
+#ifdef SILC_DIST_TFM
+       mp_tfm.c \
+       tfm.c
+#endif SILC_DIST_TFM
 
-noinst_LTLIBRARIES = libsilcmath.la
+MP_HEADER = \
+#ifdef SILC_DIST_TMA
+       mp_tma.h \
+       tma.h \
+       tma_class.h \
+       tma_superclass.h
+#endif SILC_DIST_TMA
+#ifdef SILC_DIST_TFM
+       mp_tfm.h \
+       tfm.h
+#endif SILC_DIST_TFM
 
-if SILC_MP_NSS_MPI
-MP_SOURCE = mp_mpi.c
+AM_CFLAGS = @MATH_CFLAGS@
 else
 MP_SOURCE = mp_gmp.c
+MP_HEADER =
 endif
 
 libsilcmath_la_SOURCES = \
@@ -40,15 +55,13 @@ libsilcmath_la_SOURCES = \
        $(MP_SOURCE)
 
 #ifdef SILC_DIST_TOOLKIT
-MP_HEADER = mpi/mpi.h mpi/mplogic.h mpi/mpi-config.h
 include_HEADERS =      \
        mp_gmp.h        \
-       mp_mpi.h        \
+       $(MP_HEADER)    \
        silcmath.h      \
-       silcmp.h        \
-       $(MP_HEADER)
+       silcmp.h
 #endif SILC_DIST_TOOLKIT
 
-EXTRA_DIST = mp_gmp.c mp_mpi.c *.h
+EXTRA_DIST = silcmp.h silcmath.h $(MP_SOURCE) $(MP_HEADER) mp_gmp.c mp_gmp.h
 
 include $(top_srcdir)/Makefile.defines.in
diff --git a/lib/silcmath/configure.ad b/lib/silcmath/configure.ad
new file mode 100644 (file)
index 0000000..4bc79b1
--- /dev/null
@@ -0,0 +1,128 @@
+#ifdef SILC_DIST_MATH
+#
+#  lib/silcmath/configure.ad
+#
+#  Author: Pekka Riikonen <priikone@silcnet.org>
+#
+#  Copyright (C) 2005 Pekka Riikonen
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; version 2 of the License.
+#
+#  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 General Public License for more details.
+#
+
+if test x$compile_libs = xtrue; then
+
+AC_MSG_NOTICE([configuring math library])
+
+#ifdef SILC_DIST_TMA
+SILC_ADD_CC_FLAGS(MATH, -O3, SILC_ADD_CC_FLAGS(MATH, -O2))
+SILC_ADD_CC_FLAGS(MATH, -funroll-all-loops)
+if test x$enable_stack_trace != xyes; then
+SILC_ADD_CC_FLAGS(MATH, -fomit-frame-pointer)
+fi
+#endif SILC_DIST_TMA
+
+#ifdef SILC_DIST_TFM
+# Put here any platform specific stuff
+#
+case "$target" in
+
+  alpha*-*-*)
+    if test ! "$GCC"; then
+      SILC_ADD_CC_FLAGS(MATH, -DTFM_NO_ASM)
+      SILC_ADD_CC_FLAGS(MATH, -O -Olimit 4000)
+      SILC_ADD_CC_FLAGS(MATH, -std1 -DOSF1)
+    fi
+    ;;
+
+  sparcv9-*-* | sparc64-*-*)
+    SILC_ADD_CC_FLAGS(MATH, -O3, SILC_ADD_CC_FLAGS(MATH, -O2))
+    if test ! "$GCC"; then
+      SILC_ADD_CC_FLAGS(MATH, -DTFM_NO_ASM)
+    fi
+    ;;
+
+  ultrasparc*-*-*)
+    SILC_ADD_CC_FLAGS(MATH, -O3, SILC_ADD_CC_FLAGS(MATH, -O2))
+    if test ! "$GCC"; then
+      SILC_ADD_CC_FLAGS(MATH, -DTFM_NO_ASM)
+    fi
+    ;;
+
+  hppa2.0w*-*-*)
+    if test ! "$GCC"; then
+      SILC_ADD_CC_FLAGS(MATH, -DTFM_NO_ASM)
+      SILC_ADD_CC_FLAGS(MATH, -O)
+      SILC_ADD_CC_FLAGS(MATH, -Ae)
+      SILC_ADD_CC_FLAGS(MATH, +Z)
+      SILC_ADD_CC_FLAGS(MATH, +e)
+      SILC_ADD_CC_FLAGS(MATH, -z)
+      SILC_ADD_CC_FLAGS(MATH, +DA2.0W)
+      SILC_ADD_CC_FLAGS(MATH, +O3)
+      SILC_ADD_CC_FLAGS(MATH, +DChpux)
+      SILC_ADD_CC_FLAGS(MATH, -DHPUX10 -D_POSIX_C_SOURCE=199506L -DHPUX -Dhppa-D_HPUX_SOURCE -DHPUX11 -DXP_UNIX)
+    fi
+    ;;
+
+  hppa2.0n*-*-*)
+    if test ! "$GCC"; then
+      SILC_ADD_CC_FLAGS(MATH, -DTFM_NO_ASM)
+      SILC_ADD_CC_FLAGS(MATH, -O)
+      SILC_ADD_CC_FLAGS(MATH, -Ae)
+      SILC_ADD_CC_FLAGS(MATH, +Z)
+      SILC_ADD_CC_FLAGS(MATH, +e)
+      SILC_ADD_CC_FLAGS(MATH, -z)
+      SILC_ADD_CC_FLAGS(MATH, +DA2.0)
+      SILC_ADD_CC_FLAGS(MATH, +O3)
+      SILC_ADD_CC_FLAGS(MATH, +DChpux)
+      SILC_ADD_CC_FLAGS(MATH, -DHPUX10 -D_POSIX_C_SOURCE=199506L -DHPUX -Dhppa-D_HPUX_SOURCE -DHPUX11 -DXP_UNIX)
+    fi
+    ;;
+
+  hppa*-*-*)
+    if test ! "$GCC"; then
+      SILC_ADD_CC_FLAGS(MATH, -DTFM_NO_ASM)
+      SILC_ADD_CC_FLAGS(MATH, -O)
+      SILC_ADD_CC_FLAGS(MATH, -Ae)
+      SILC_ADD_CC_FLAGS(MATH, +Z)
+      SILC_ADD_CC_FLAGS(MATH, +DAportable)
+      SILC_ADD_CC_FLAGS(MATH, +DS1.1)
+      SILC_ADD_CC_FLAGS(MATH, -DHPUX10 -D_POSIX_C_SOURCE=199506L -DHPUX -Dhppa-D_HPUX_SOURCE -DHPUX11 -DXP_UNIX)
+      AS="$(CC) $(CFLAGS) $(MPI_CFLAGS) -c"
+    fi
+    ;;
+
+  armv4*-*-*)
+    SILC_ADD_CC_FLAGS(MATH, -DTFM_ARM)
+    ;;
+
+  *)
+    SILC_ADD_CC_FLAGS(MATH, -O3, SILC_ADD_CC_FLAGS(MATH, -O2))
+    if test x$enable_stack_trace != xyes; then
+      SILC_ADD_CC_FLAGS(MATH, -fomit-frame-pointer)
+    fi
+    ;;
+esac
+
+if test "$GCC"; then
+  SILC_ADD_CC_FLAGS(MATH, -funroll-all-loops)
+fi
+if test x$want_asm = xfalse; then
+  SILC_ADD_CC_FLAGS(MATH, -DTFM_NO_ASM)
+fi
+#endif SILC_DIST_TFM
+
+AC_SUBST(MATH_CFLAGS)
+
+AC_CONFIG_FILES(
+lib/silcmath/Makefile
+)
+
+fi     # compile_libs
+#endif SILC_DIST_MATH
index 7863923e4bf7dc76c88163d91812bd638255a3fd..5c6e0657ad5338284f89dab9f0f4ca2c35e4184e 100644 (file)
@@ -2,15 +2,14 @@
 
   modinv.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -29,21 +28,21 @@ typedef struct {
 #define plus1  (i == 2 ? 0 : i + 1)
 #define minus1         (i == 0 ? 2 : i - 1)
 
-/* Find multiplicative inverse using Euclid's extended algorithm. 
-   Computes inverse such that a * inv mod n = 1, where 0 < a < n. 
+/* Find multiplicative inverse using Euclid's extended algorithm.
+   Computes inverse such that a * inv mod n = 1, where 0 < a < n.
    Algorithm goes like this:
-   
+
    g(0) = n    v(0) = 0
    g(1) = a    v(1) = 1
-   
+
    y = g(i-1) / g(i)
    g(i+1) = g(i-1) - y * g(i) = g(i)-1 mod g(i)
    v(i+1) = v(i-1) - y * v(i)
-   
-   do until g(i) = 0, then inverse = v(i-1). If inverse is negative then n, 
-   is added to inverse making it positive again. (Sometimes the algorithm 
-   has a variable u defined too and it behaves just like v, except that 
-   initalize values are swapped (i.e. u(0) = 1, u(1) = 0). However, u is 
+
+   do until g(i) = 0, then inverse = v(i-1). If inverse is negative then n,
+   is added to inverse making it positive again. (Sometimes the algorithm
+   has a variable u defined too and it behaves just like v, except that
+   initalize values are swapped (i.e. u(0) = 1, u(1) = 0). However, u is
    not needed by the algorithm so it does not have to be included.)
 */
 
@@ -52,10 +51,10 @@ void silc_mp_modinv(SilcMPInt *inv, SilcMPInt *a, SilcMPInt *n)
   int i;
   SilcMPInt y;
   SilcMPInt x;
-  
+
   ModInv g[3];
   ModInv v[3];
-  
+
   /* init MP vars */
   silc_mp_init(&y);
   silc_mp_init(&x);
@@ -69,7 +68,7 @@ void silc_mp_modinv(SilcMPInt *inv, SilcMPInt *a, SilcMPInt *n)
   silc_mp_set(&g[0].x, n);                     /* g(0) = n */
   silc_mp_set(&g[1].x, a);             /* g(1) = a */
   silc_mp_init(&g[2].x);
-  
+
   i = 1;
   while(silc_mp_cmp_ui(&g[i].x, 0) != 0) {
     silc_mp_div(&y, &g[minus1].x, &g[i].x);            /* y = n / a */
@@ -79,14 +78,14 @@ void silc_mp_modinv(SilcMPInt *inv, SilcMPInt *a, SilcMPInt *n)
     silc_mp_sub(&v[plus1].x, &v[plus1].x, &x);
     i = plus1;
   }
-  
+
   /* set the inverse */
   silc_mp_set(inv, &v[minus1].x);
-  
+
   /* if inverse is negative, add n to inverse */
   if (silc_mp_cmp_ui(inv, 0) < 0)
     silc_mp_add(inv, inv, n);
-  
+
   /* clear the vars */
   memset(&g, 0, sizeof(g));
   memset(&v, 0, sizeof(v));
index 9d62bac4ebc346b5ab4731d99894eb1129f8a6e1..876296493aed60a7305492e965a8ddd2f6673905 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  mp_gmp.c 
+  mp_gmp.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -121,7 +121,7 @@ void silc_mp_div_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
   mpz_div_ui(dst, mp1, ui);
 }
 
-void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1, 
+void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
                    SilcMPInt *mp2)
 {
   if (q && r)
@@ -137,7 +137,7 @@ void silc_mp_div_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
   mpz_fdiv_q_2exp(dst, mp1, exp);
 }
 
-void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1, 
+void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
                         SilcUInt32 exp)
 {
   if (q)
@@ -172,13 +172,13 @@ void silc_mp_pow_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
   mpz_pow_ui(dst, mp1, exp);
 }
 
-void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp, 
+void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp,
                     SilcMPInt *mod)
 {
   mpz_powm(dst, mp1, exp, mod);
 }
 
-void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp, 
+void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp,
                        SilcMPInt *mod)
 {
   mpz_powm_ui(dst, mp1, exp, mod);
index 14ae512573af1f79435c9683f24b04eedb7f994c..9b4c4d2f959acf8f6829cd93cb7264d5bccf2a71 100644 (file)
@@ -2,14 +2,13 @@
 
   mp_gmp.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 2001 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/lib/silcmath/mp_tfm.c b/lib/silcmath/mp_tfm.c
new file mode 100644 (file)
index 0000000..1abbf50
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+
+  mp_tfm.c
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+/* $Id$ */
+
+#include "silcincludes.h"
+#include "mp_tfm.h"
+
+void silc_mp_init(SilcMPInt *mp)
+{
+  fp_init(mp);
+}
+
+void silc_mp_uninit(SilcMPInt *mp)
+{
+  fp_zero(mp);
+}
+
+size_t silc_mp_size(SilcMPInt *mp)
+{
+  return fp_unsigned_bin_size(mp);
+}
+
+size_t silc_mp_sizeinbase(SilcMPInt *mp, int base)
+{
+  int size = 0;
+  fp_radix_size(mp, base, &size);
+  if (size > 1)
+    size--;
+  return size;
+}
+
+void silc_mp_set(SilcMPInt *dst, SilcMPInt *src)
+{
+  fp_copy(src, dst);
+}
+
+void silc_mp_set_ui(SilcMPInt *dst, SilcUInt32 ui)
+{
+  fp_set(dst, ui);
+}
+
+void silc_mp_set_si(SilcMPInt *dst, SilcInt32 si)
+{
+  fp_set(dst, si);
+}
+
+void silc_mp_set_str(SilcMPInt *dst, const char *str, int base)
+{
+  fp_read_radix(dst, str, base);
+}
+
+SilcUInt32 silc_mp_get_ui(SilcMPInt *mp)
+{
+  SILC_NOT_IMPLEMENTED("silc_mp_get_ui");
+  assert(FALSE);
+}
+
+char *silc_mp_get_str(char *str, SilcMPInt *mp, int base)
+{
+  if (fp_toradix(mp, str, base) != MP_OKAY)
+    return NULL;
+  return str;
+}
+
+void silc_mp_add(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  fp_add(mp1, mp2, dst);
+}
+
+void silc_mp_add_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
+{
+  mp_add_d(mp1, (mp_digit)ui, dst);
+}
+
+void silc_mp_sub(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  fp_sub(mp1, mp2, dst);
+}
+
+void silc_mp_sub_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
+{
+  fp_sub_d(mp1, (mp_digit)ui, dst);
+}
+
+void silc_mp_mul(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  fp_mul(mp1, mp2, dst);
+}
+
+void silc_mp_mul_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
+{
+  fp_mul_d(mp1, (mp_digit)ui, dst);
+}
+
+void silc_mp_mul_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
+{
+  fp_mul_2d(mp1, exp, dst);
+}
+
+void silc_mp_sqrt(SilcMPInt *dst, SilcMPInt *src)
+{
+  fp_sqrt(src, dst);
+}
+
+void silc_mp_div(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  fp_div(mp1, mp2, dst, NULL);
+}
+
+void silc_mp_div_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
+{
+  fp_div_d(mp1, (mp_digit)ui, dst, NULL);
+}
+
+void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
+                   SilcMPInt *mp2)
+{
+  fp_div(mp1, mp2, q, r);
+}
+
+void silc_mp_div_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
+{
+  fp_div_2d(mp1, exp, dst, NULL);
+}
+
+void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
+                        SilcUInt32 exp)
+{
+  fp_div_2d(mp1, exp, q, r);
+}
+
+void silc_mp_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  fp_mod(mp1, mp2, dst);
+}
+
+void silc_mp_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
+{
+  fp_digit d;
+  fp_mod_d(mp1, ui, &d);
+  silc_mp_set_ui(dst, d);
+}
+
+void silc_mp_mod_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
+{
+  fp_mod_2d(mp1, ui, dst);
+}
+
+void silc_mp_pow(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp)
+{
+  SILC_NOT_IMPLEMENTED("silc_mp_pow");
+  assert(FALSE);
+}
+
+void silc_mp_pow_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
+{
+  SILC_NOT_IMPLEMENTED("silc_mp_pow_ui");
+  assert(FALSE);
+}
+
+void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp,
+                    SilcMPInt *mod)
+{
+  fp_exptmod(mp1, exp, mod, dst);
+}
+
+void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp,
+                       SilcMPInt *mod)
+{
+  SilcMPInt tmp;
+  silc_mp_init(&tmp);
+  silc_mp_set_ui(&tmp, exp);
+  silc_mp_pow_mod(dst, mp1, &tmp, mod);
+  silc_mp_uninit(&tmp);
+}
+
+void silc_mp_gcd(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  fp_gcd(mp1, mp2, dst);
+}
+
+void silc_mp_gcdext(SilcMPInt *g, SilcMPInt *s, SilcMPInt *t, SilcMPInt *mp1,
+                   SilcMPInt *mp2)
+{
+  SILC_NOT_IMPLEMENTED("silc_mp_gcdext");
+  assert(FALSE);
+}
+
+int silc_mp_cmp(SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  return fp_cmp(mp1, mp2);
+}
+
+int silc_mp_cmp_si(SilcMPInt *mp1, SilcInt32 si)
+{
+  return fp_cmp_d(mp1, si);
+}
+
+int silc_mp_cmp_ui(SilcMPInt *mp1, SilcUInt32 ui)
+{
+  return fp_cmp_d(mp1, ui);
+}
+
+void silc_mp_abs(SilcMPInt *dst, SilcMPInt *src)
+{
+  fp_abs(src, dst);
+}
+
+void silc_mp_neg(SilcMPInt *dst, SilcMPInt *src)
+{
+  fp_neg(src, dst);
+}
+
+void silc_mp_and(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  SILC_NOT_IMPLEMENTED("silc_mp_and");
+  assert(FALSE);
+}
+
+void silc_mp_or(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  SILC_NOT_IMPLEMENTED("silc_mp_or");
+  assert(FALSE);
+}
+
+void silc_mp_xor(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
+{
+  SILC_NOT_IMPLEMENTED("silc_mp_xor");
+  assert(FALSE);
+}
diff --git a/lib/silcmath/mp_tfm.h b/lib/silcmath/mp_tfm.h
new file mode 100644 (file)
index 0000000..176cd1c
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+
+  mp_tfm.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+
+#ifndef MP_TFM_H
+#define MP_TFM_H
+
+#include "tfm.h"
+
+#define SILC_MP_INT fp_int
+
+#endif /* MP_TFM_H */
similarity index 74%
rename from lib/silcmath/mp_mpi.c
rename to lib/silcmath/mp_tma.c
index 8ef0a40b5100e11ea8cfcecb3dfa6d0b974b1523..ba9f21205ef03e4673b17048fb9c83153eb3af22 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  mp_mpi.c 
+  mp_tma.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -19,8 +19,7 @@
 /* $Id$ */
 
 #include "silcincludes.h"
-#include "mpi.h"
-#include "mplogic.h"
+#include "mp_tma.h"
 
 void silc_mp_init(SilcMPInt *mp)
 {
@@ -29,22 +28,21 @@ void silc_mp_init(SilcMPInt *mp)
 
 void silc_mp_uninit(SilcMPInt *mp)
 {
-  (void)mp_clear(mp);
+  mp_clear(mp);
 }
 
 size_t silc_mp_size(SilcMPInt *mp)
 {
-  return mp_raw_size(mp);
+  return mp_unsigned_bin_size(mp);
 }
 
 size_t silc_mp_sizeinbase(SilcMPInt *mp, int base)
 {
-  size_t sib = mp_unsigned_octet_size(mp);
-  sib = s_mp_outlen(sib * CHAR_BIT, base);
-  if (sib > 2)
-    sib -= 2;                  /* Looks like MPI returns extra zero
-                                  bytes for C-strings. */
-  return sib;
+  int size = 0;
+  mp_radix_size(mp, base, &size);
+  if (size > 1)
+    size--;
+  return size;
 }
 
 void silc_mp_set(SilcMPInt *dst, SilcMPInt *src)
@@ -54,7 +52,7 @@ void silc_mp_set(SilcMPInt *dst, SilcMPInt *src)
 
 void silc_mp_set_ui(SilcMPInt *dst, SilcUInt32 ui)
 {
-  mp_set(dst, ui);
+  (void)mp_set_int(dst, ui);
 }
 
 void silc_mp_set_si(SilcMPInt *dst, SilcInt32 si)
@@ -64,12 +62,12 @@ void silc_mp_set_si(SilcMPInt *dst, SilcInt32 si)
 
 void silc_mp_set_str(SilcMPInt *dst, const char *str, int base)
 {
-  (void)mp_read_variable_radix(dst, str, base);
+  (void)mp_read_radix(dst, str, base);
 }
 
 SilcUInt32 silc_mp_get_ui(SilcMPInt *mp)
 {
-  return (SilcUInt32)MP_DIGIT(mp, 0);
+  return (SilcUInt32)mp_get_int(mp);
 }
 
 char *silc_mp_get_str(char *str, SilcMPInt *mp, int base)
@@ -86,7 +84,7 @@ void silc_mp_add(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
 
 void silc_mp_add_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
 {
-  mp_add_d(mp1, ui, dst);
+  mp_add_d(mp1, (mp_digit)ui, dst);
 }
 
 void silc_mp_sub(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
@@ -111,11 +109,7 @@ void silc_mp_mul_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
 
 void silc_mp_mul_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
 {
-  SilcMPInt tmp;
-  silc_mp_init(&tmp);
-  (void)mp_2expt(&tmp, (mp_digit)exp);
-  (void)mp_mul(mp1, &tmp, dst);
-  silc_mp_uninit(&tmp);
+  (void)mp_mul_2d(mp1, exp, dst);
 }
 
 void silc_mp_sqrt(SilcMPInt *dst, SilcMPInt *src)
@@ -133,7 +127,7 @@ void silc_mp_div_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
   (void)mp_div_d(mp1, (mp_digit)ui, dst, NULL);
 }
 
-void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1, 
+void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
                    SilcMPInt *mp2)
 {
   (void)mp_div(mp1, mp2, q, r);
@@ -141,20 +135,13 @@ void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
 
 void silc_mp_div_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
 {
-  SilcMPInt tmp;
-  silc_mp_init(&tmp);
-  (void)mp_2expt(&tmp, (mp_digit)exp);
-  (void)mp_div(mp1, &tmp, dst, NULL);
-  silc_mp_uninit(&tmp);
+  (void)mp_div_2d(mp1, exp, dst, NULL);
 }
 
-void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1, 
+void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
                         SilcUInt32 exp)
 {
-  if (q) {
-    (void)mp_2expt(q, (mp_digit)exp);
-    (void)mp_div(mp1, q, q, r);
-  }
+  (void)mp_div_2d(mp1, exp, q, r);
 }
 
 void silc_mp_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
@@ -164,23 +151,20 @@ void silc_mp_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
 
 void silc_mp_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
 {
-  mp_digit uidst;
-  (void)mp_mod_d(mp1, (mp_digit)ui, &uidst);
-  mp_set(dst, uidst);
+  mp_digit d;
+  (void)mp_mod_d(mp1, ui, &d);
+  silc_mp_set_ui(dst, d);
 }
 
 void silc_mp_mod_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
 {
-  SilcMPInt tmp;
-  silc_mp_init(&tmp);
-  (void)mp_2expt(&tmp, (mp_digit)ui);
-  (void)mp_mod(mp1, &tmp, dst);
-  silc_mp_uninit(&tmp);
+  (void)mp_mod_2d(mp1, ui, dst);
 }
 
 void silc_mp_pow(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp)
 {
-  (void)mp_expt(mp1, exp, dst);
+  SILC_NOT_IMPLEMENTED("silc_mp_pow");
+  assert(FALSE);
 }
 
 void silc_mp_pow_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
@@ -188,16 +172,20 @@ void silc_mp_pow_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
   (void)mp_expt_d(mp1, (mp_digit)exp, dst);
 }
 
-void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp, 
+void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp,
                     SilcMPInt *mod)
 {
   (void)mp_exptmod(mp1, exp, mod, dst);
 }
 
-void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp, 
+void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp,
                        SilcMPInt *mod)
 {
-  (void)mp_exptmod_d(mp1, (mp_digit)exp, mod, dst);
+  SilcMPInt tmp;
+  silc_mp_init(&tmp);
+  silc_mp_set_ui(&tmp, exp);
+  silc_mp_pow_mod(dst, mp1, &tmp, mod);
+  silc_mp_uninit(&tmp);
 }
 
 void silc_mp_gcd(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
@@ -208,7 +196,7 @@ void silc_mp_gcd(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
 void silc_mp_gcdext(SilcMPInt *g, SilcMPInt *s, SilcMPInt *t, SilcMPInt *mp1,
                    SilcMPInt *mp2)
 {
-  (void)mp_xgcd(mp1, mp2, g, s, t);
+  (void)mp_exteuclid(mp1, mp2, s, t, g);
 }
 
 int silc_mp_cmp(SilcMPInt *mp1, SilcMPInt *mp2)
@@ -218,7 +206,7 @@ int silc_mp_cmp(SilcMPInt *mp1, SilcMPInt *mp2)
 
 int silc_mp_cmp_si(SilcMPInt *mp1, SilcInt32 si)
 {
-  return mp_cmp_int(mp1, (long)si);
+  return mp_cmp_d(mp1, si);
 }
 
 int silc_mp_cmp_ui(SilcMPInt *mp1, SilcUInt32 ui)
@@ -228,25 +216,25 @@ int silc_mp_cmp_ui(SilcMPInt *mp1, SilcUInt32 ui)
 
 void silc_mp_abs(SilcMPInt *dst, SilcMPInt *src)
 {
-  mp_abs(src, dst);
+  (void)mp_abs(src, dst);
 }
 
 void silc_mp_neg(SilcMPInt *dst, SilcMPInt *src)
 {
-  mp_neg(src, dst);
+  (void)mp_neg(src, dst);
 }
 
 void silc_mp_and(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
 {
-  mpl_and(mp1, mp2, dst);
+  (void)mp_and(mp1, mp2, dst);
 }
 
 void silc_mp_or(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
 {
-  mpl_or(mp1, mp2, dst);
+  (void)mp_or(mp1, mp2, dst);
 }
 
 void silc_mp_xor(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
 {
-  mpl_xor(mp1, mp2, dst);
+  (void)mp_xor(mp1, mp2, dst);
 }
similarity index 60%
rename from lib/silcmath/mp_mpi.h
rename to lib/silcmath/mp_tma.h
index 54614a30bb9661d3480c59d2a814215ab5ac4f7a..05d115524b291f6346aadfc1cee70b84dbba2969 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
-  mp_mpi.h
+  mp_tma.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
 
 */
 
-#ifndef MP_MPI_H
-#define MP_MPI_H
+#ifndef MP_TMA_H
+#define MP_TMA_H
 
-#include "mpi.h"
-#include "mplogic.h"
+#include "tma.h"
 
 #define SILC_MP_INT mp_int
 
index 29d80f7711e71e007b2ddb8d20dde27fd766cd9d..9df0dbef46c2fb06c4a6f68f48d2e18f3beddb86 100644 (file)
@@ -2,15 +2,14 @@
 
   mpbin.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2001 Pekka Riikonen
+  Copyright (C) 2000 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -35,7 +34,7 @@ unsigned char *silc_mp_mp2bin(SilcMPInt *val, SilcUInt32 len,
 
   size = (len ? len : ((silc_mp_sizeinbase(val, 2) + 7) / 8));
   ret = silc_calloc(size, sizeof(*ret));
-  
+
   silc_mp_init(&tmp);
   silc_mp_set(&tmp, val);
 
index 64510b1dfc72227409f90c641bdc41dd081cbcce..e1bb9945aaaa5e5334653f470258727204d14a0a 100644 (file)
@@ -8,8 +8,7 @@
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index ba18ae35bfe1f2d01af2fa818aba398614f0660b..ccc15a670a7d2e4374ad959976be9baff1f924c9 100644 (file)
@@ -1,21 +1,20 @@
 /*
 
   silcmp.h
+
   Author: Pekka Riikonen <priikone@silcnet.org>
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+
+  Copyright (C) 1997 - 2005 Pekka Riikonen
+
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
+
   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 General Public License for more details.
+
 */
 
 /****h* silcmath/SILC MP Interface
  * DESCRIPTION
  *
  * SILC MP Library Interface. This interface defines the arbitrary
- * precision arithmetic routines for SILC. Currently the actual routines
- * are implemented separately, usually by some other MP library. The
- * interface is generic but is mainly intended for crypto usage. This
- * interface is used by SILC routines that needs big numbers, such as
- * RSA implementation, Diffie-Hellman implementation etc.
+ * precision arithmetic routines for SILC. The interface is generic but
+ * is mainly intended for crypto usage. This interface is used by SILC
+ * routines that needs big numbers, such as RSA implementation,
+ * Diffie-Hellman implementation etc.
  *
  ***/
 
 #if defined(SILC_MP_GMP)
 #include "mp_gmp.h"            /* SILC_MP_GMP */
 #else
-#include "mp_mpi.h"            /* SILC_MP_NSS_MPI */
+#ifdef SILC_DIST_TMA
+#include "mp_tma.h"
+#endif /* SILC_DIST_TMA */
+#ifdef SILC_DIST_TFM
+#include "mp_tfm.h"
+#endif /* SILC_DIST_TFM */
 #endif
 
 /****d* silcmath/SilcMPAPI/SilcMPInt
@@ -303,7 +306,7 @@ void silc_mp_mul_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui);
  *
  * DESCRIPTION
  *
- *    Multiply integers `mp1' with 2 ** `exp' and save the result to 
+ *    Multiply integers `mp1' with 2 ** `exp' and save the result to
  *    `dst'. This is equivalent to dst = mp1 * (2 ^ exp).
  *
  ***/
@@ -354,18 +357,18 @@ void silc_mp_div_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui);
  *
  * SYNOPSIS
  *
- *    void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1, 
+ *    void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
  *                        SilcMPInt *mp2);
  *
  * DESCRIPTION
  *
  *    Divide the `mp1' and `mp2' and save the quotient to the `q' and
- *    the remainder to the `r'.  This is equivalent to the q = mp1 / mp2, 
+ *    the remainder to the `r'.  This is equivalent to the q = mp1 / mp2,
  *    r = mp1 mod mp2 (or mp1 = mp2 * q + r). If the `q' or `r' is NULL
  *    then the operation is omitted.
  *
  ***/
-void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1, 
+void silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
                    SilcMPInt *mp2);
 
 /****f* silcmath/SilcMPAPI/silc_mp_div_2exp
@@ -386,7 +389,7 @@ void silc_mp_div_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp);
  *
  * SYNOPSIS
  *
- *    void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1, 
+ *    void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
  *                             SilcUInt32 exp);
  *
  * DESCRIPTION
@@ -397,7 +400,7 @@ void silc_mp_div_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp);
  *    is omitted.
  *
  ***/
-void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1, 
+void silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
                         SilcUInt32 exp);
 
 /****f* silcmath/SilcMPAPI/silc_mp_mod
@@ -424,7 +427,7 @@ void silc_mp_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2);
  *
  * DESCRIPTION
  *
- *    Mathematical MOD function. Produces the remainder of `mp1' and 
+ *    Mathematical MOD function. Produces the remainder of `mp1' and
  *    unsigned word `ui' and saves the result to `dst'. This is equivalent
  *    to dst = mp1 mod ui.
  *
@@ -479,7 +482,7 @@ void silc_mp_pow_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp);
  *
  * SYNOPSIS
  *
- *    void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp, 
+ *    void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp,
  *                         SilcMPInt *mod);
  *
  * DESCRIPTION
@@ -488,14 +491,14 @@ void silc_mp_pow_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp);
  *    This is equivalent to dst = (mp1 ^ exp) mod mod.
  *
  ***/
-void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp, 
+void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp,
                     SilcMPInt *mod);
 
 /****f* silcmath/SilcMPAPI/silc_mp_pow_mod_ui
  *
  * SYNOPSIS
  *
- *    void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp, 
+ *    void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp,
  *                            SilcMPInt *mod);
  *
  * DESCRIPTION
@@ -504,7 +507,7 @@ void silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp,
  *    This is equivalent to dst = (mp1 ^ exp) mod mod.
  *
  ***/
-void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp, 
+void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp,
                        SilcMPInt *mod);
 
 /****f* silcmath/SilcMPAPI/silc_mp_modinv
@@ -515,21 +518,21 @@ void silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp,
  *
  * DESCRIPTION
  *
- *    Find multiplicative inverse using Euclid's extended algorithm. 
- *    Computes inverse such that a * inv mod n = 1, where 0 < a < n. 
+ *    Find multiplicative inverse using Euclid's extended algorithm.
+ *    Computes inverse such that a * inv mod n = 1, where 0 < a < n.
  *    Algorithm goes like this:
- *  
+ *
  *    g(0) = n    v(0) = 0
  *    g(1) = a    v(1) = 1
- * 
+ *
  *    y = g(i-1) / g(i)
  *    g(i+1) = g(i-1) - y * g(i) = g(i)-1 mod g(i)
  *    v(i+1) = v(i-1) - y * v(i)
- * 
- *    do until g(i) = 0, then inverse = v(i-1). If inverse is negative then n, 
- *    is added to inverse making it positive again. (Sometimes the algorithm 
- *    has a variable u defined too and it behaves just like v, except that 
- *    initalize values are swapped (i.e. u(0) = 1, u(1) = 0). However, u is 
+ *
+ *    do until g(i) = 0, then inverse = v(i-1). If inverse is negative then n,
+ *    is added to inverse making it positive again. (Sometimes the algorithm
+ *    has a variable u defined too and it behaves just like v, except that
+ *    initalize values are swapped (i.e. u(0) = 1, u(1) = 0). However, u is
  *    not needed by the algorithm so it does not have to be included.)
  *
  ***/
@@ -553,7 +556,7 @@ void silc_mp_gcd(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2);
  *
  * SYNOPSIS
  *
- *    void silc_mp_gcdext(SilcMPInt *g, SilcMPInt *s, SilcMPInt *t, 
+ *    void silc_mp_gcdext(SilcMPInt *g, SilcMPInt *s, SilcMPInt *t,
  *                        SilcMPInt *mp1, SilcMPInt *mp2);
  *
  * DESCRIPTION
@@ -601,8 +604,8 @@ int silc_mp_cmp_si(SilcMPInt *mp1, SilcInt32 si);
  *
  * DESCRIPTION
  *
- *    Compare `mp1' and unsigned word `ui'. Returns posivite, zero, or 
- *    negative if `mp1' > `ui', `mp1' == `ui', or `mp1' < `ui', 
+ *    Compare `mp1' and unsigned word `ui'. Returns posivite, zero, or
+ *    negative if `mp1' > `ui', `mp1' == `ui', or `mp1' < `ui',
  *    respectively.
  *
  ***/
@@ -612,7 +615,7 @@ int silc_mp_cmp_ui(SilcMPInt *mp1, SilcUInt32 ui);
  *
  * SYNOPSIS
  *
- *    unsigned char *silc_mp_mp2bin(SilcMPInt *val, SilcUInt32 len, 
+ *    unsigned char *silc_mp_mp2bin(SilcMPInt *val, SilcUInt32 len,
  *                                  SilcUInt32 *ret_len);
  *
  * DESCRIPTION
@@ -622,7 +625,7 @@ int silc_mp_cmp_ui(SilcMPInt *mp1, SilcUInt32 ui);
  *    buffer is allocated that large. If zero then the size is approximated.
  *
  ***/
-unsigned char *silc_mp_mp2bin(SilcMPInt *val, SilcUInt32 len, 
+unsigned char *silc_mp_mp2bin(SilcMPInt *val, SilcUInt32 len,
                              SilcUInt32 *ret_len);
 
 /****f* silcmath/SilcMPAPI/silc_mp_mp2bin_noalloc
@@ -645,7 +648,7 @@ void silc_mp_mp2bin_noalloc(SilcMPInt *val, unsigned char *dst,
  *
  * SYNOPSIS
  *
- *    void silc_mp_bin2mp(unsigned char *data, SilcUInt32 len, 
+ *    void silc_mp_bin2mp(unsigned char *data, SilcUInt32 len,
  *                        SilcMPInt *ret);
  *
  * DESCRIPTION
index 7079f7d1885476cab8ce9ce99ef39e6e3666ce85..80bbf54eaea4a0124df4ddac6f1b3f1a56133dd8 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
   silcprimegen.c
-  
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
 
 #include "silcincludes.h"
 
-/* 
-   Fixed primetable for small prime division. We use this primetable to 
-   test if possible prime is divisible any of these. Primetable is NULL 
-   terminated. This same primetable can be found in SSH and PGP except that 
-   SSH don't have prime 2 in the table. This sort of prime table is easily 
+/*
+   Fixed primetable for small prime division. We use this primetable to
+   test if possible prime is divisible any of these. Primetable is NULL
+   terminated. This same primetable can be found in SSH and PGP except that
+   SSH don't have prime 2 in the table. This sort of prime table is easily
    created, for example, using sieve of Erastosthenes.
-   
-   Just to include; if somebody is interested about Erastosthenes. Creating a 
-   small prime table using sieve of Erastosthenes would go like this: Write 
+
+   Just to include; if somebody is interested about Erastosthenes. Creating a
+   small prime table using sieve of Erastosthenes would go like this: Write
    down a list of integers in range of 2 to n. Here in example n = 20.
-   
+
    2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
 
    Then mark all multiples of 2 (Note: 2 is a prime number):
@@ -46,9 +45,9 @@
        x   x   x x  x     x     x  x  x     x     x
 
    And continue doing this, marking all multiples of the next unmarked
-   number until there are now new unmarked numbers. And there you have a 
+   number until there are now new unmarked numbers. And there you have a
    prime table. So in this example, primes between 2 - 20 are:
-   
+
    2 3 5 7 11 13 17 19
 
 */
@@ -187,10 +186,10 @@ static SilcUInt32 primetable[] =
 };
 
 
-/* Find appropriate prime. It generates a number by taking random bytes. 
-   It then tests the number that it's not divisible by any of the small 
-   primes and then it performs Fermat's prime test. I thank Rieks Joosten 
-   (r.joosten@pijnenburg.nl) for such a good help with prime tests. 
+/* Find appropriate prime. It generates a number by taking random bytes.
+   It then tests the number that it's not divisible by any of the small
+   primes and then it performs Fermat's prime test. I thank Rieks Joosten
+   (r.joosten@pijnenburg.nl) for such a good help with prime tests.
 
    If argument verbose is TRUE this will display some status information
    about the progress of generation. */
@@ -202,6 +201,7 @@ bool silc_math_gen_prime(SilcMPInt *prime, SilcUInt32 bits, bool verbose,
   SilcUInt32 i, b, k;
   SilcUInt32 *spmods;
   SilcMPInt r, base, tmp, tmp2, oprime;
+  bool valid = FALSE;
 
   silc_mp_init(&r);
   silc_mp_init(&base);
@@ -213,92 +213,99 @@ bool silc_math_gen_prime(SilcMPInt *prime, SilcUInt32 bits, bool verbose,
 
   SILC_LOG_DEBUG(("Generating new prime"));
 
-  /* Get random number and assure that the first digit is not zero since
-     our conversion routines does not like the first digit being zero. */
-  do {
-    if (numbuf) {
-      memset(numbuf, 0, (bits / 8));
-      silc_free(numbuf);
-    }
+  while (valid == FALSE) {
+    /* Get random number */
     if (rng)
-      numbuf = silc_rng_get_rn_string(rng, (bits / 8));
+      numbuf = silc_rng_get_rn_data(rng, (bits / 8));
     else
-      numbuf = silc_rng_global_get_rn_string((bits / 8));
+      numbuf = silc_rng_global_get_rn_data((bits / 8));
     if (!numbuf)
       return FALSE;
-  } while (numbuf[0] == '0');
-
-  /* Convert into MP and set the size */
-  silc_mp_set_str(prime, numbuf, 16);  
-  silc_mp_mod_2exp(prime, prime, bits);
-
-  /* Empty buffer */
-  memset(numbuf, 0, (bits / 8));
-  silc_free(numbuf);
 
-  /* Number could be even number, so we'll make it odd. */
-  silc_mp_set_ui(&tmp, 1);
-  silc_mp_or(prime, prime, &tmp);              /* OR operator */
+    /* Convert into MP and set the size */
+    silc_mp_bin2mp(numbuf, (bits / 8), prime);
+    silc_mp_mod_2exp(prime, prime, bits);
+
+    /* Empty buffer */
+    memset(numbuf, 0, (bits / 8));
+    silc_free(numbuf);
+
+    /* Set highest bit */
+    silc_mp_set_ui(&tmp, 1);
+    silc_mp_mul_2exp(&tmp, &tmp, bits - 1);
+    silc_mp_or(prime, prime, &tmp);
+
+    /* Number could be even number, so we'll make it odd. */
+    silc_mp_set_ui(&tmp, 1);
+    silc_mp_or(prime, prime, &tmp);
+
+    /* Init modulo table with the prime candidate and the primes
+       in the primetable. */
+    spmods = silc_calloc(1, sizeof(primetable) * sizeof(SilcUInt32));
+    for (i = 0; primetable[i] != 0; i++) {
+      silc_mp_mod_ui(&tmp, prime, primetable[i]);
+      spmods[i] = silc_mp_get_ui(&tmp);
+    }
 
-  /* Init modulo table with the prime candidate and the primes
-     in the primetable. */
-  spmods = silc_calloc(1, sizeof(primetable) * sizeof(SilcUInt32));
-  for (i = 0; primetable[i] != 0; i++) {
-    silc_mp_mod_ui(&tmp, prime, primetable[i]);
-    spmods[i] = silc_mp_get_ui(&tmp);
-  }
+    /* k is added by 2, this way we skip all even numbers (prime is odd). */
+    silc_mp_set(&oprime, prime);
+    for (k = 0;; k += 2) {
+      silc_mp_add_ui(&oprime, prime, k);
+
+      /* See if the prime has a divisor in primetable[].
+       * If it has then it's a composite. We add k to the
+       * original modulo value, k is added by 2 on every roll.
+       * This way we don't have to re-init the whole table if
+       * the number is composite.
+       */
+      for (b = 0; b < i; b++) {
+       silc_mp_set_ui(&tmp2, spmods[b]);
+       silc_mp_add_ui(&tmp2, &tmp2, k);
+       silc_mp_mod_ui(&tmp, &tmp2, primetable[b]);
+
+       /* If mod is 0, the number is composite */
+       if (silc_mp_cmp_ui(&tmp, 0) == 0)
+         break;
+      }
+      if (b < i)
+       continue;
+
+      /* Passed the quick test. */
+
+      /* Does the prime pass the Fermat's prime test.
+       * r = 2 ^ p mod p, if r == 2, then p is probably a prime.
+       */
+      silc_mp_pow_mod(&r, &base, &oprime, &oprime);
+      if (silc_mp_cmp_ui(&r, 2) != 0) {
+       if (verbose) {
+         printf(".");
+         fflush(stdout);
+       }
+       continue;
+      }
 
-  /* k is added by 2, this way we skip all even numbers (prime is odd). */
-  silc_mp_set(&oprime, prime);
-  for (k = 0;; k += 2) {
-    silc_mp_add_ui(&oprime, prime, k);
-    
-    /* See if the prime has a divisor in primetable[].
-     * If it has then it's a composite. We add k to the
-     * original modulo value, k is added by 2 on every roll.
-     * This way we don't have to re-init the whole table if
-     * the number is composite. 
-     */
-    for (b = 0; b < i; b++) {
-      silc_mp_set_ui(&tmp2, spmods[b]);
-      silc_mp_add_ui(&tmp2, &tmp2, k);
-      silc_mp_mod_ui(&tmp, &tmp2, primetable[b]);
-      
-      /* If mod is 0, the number is composite */
-      if (silc_mp_cmp_ui(&tmp, 0) == 0)
-       break;
+      /* Passed the Fermat's test. And I don't think
+       * we have to do more tests. If anyone wants to do more
+       * tests, MP library has probability of prime test:
+       *
+       * if (silc_mp_probab_prime_p(prime, 25))
+       *     break;                          found a probable prime
+       *
+       * However, this is very slow.
+       */
+      /* XXX: this could be done if some argument, say strict_primes, is
+        TRUE when we are willing to spend more time on the prime test and
+        to get, perhaps, better primes. */
+      silc_mp_set(prime, &oprime);
+      break;
     }
-    if (b < i)
-      continue;
-    
-    /* Passed the quick test. */
-    
-    /* Does the prime pass the Fermat's prime test.
-     * r = 2 ^ p mod p, if r == 2, then p is probably a prime. 
-     */
-    silc_mp_pow_mod(&r, &base, &oprime, &oprime);
-    if (silc_mp_cmp_ui(&r, 2) != 0) {
-      if (verbose) {
-       printf(".");
-       fflush(stdout);
-      }
-      continue;
+
+    /* Check highest bit */
+    silc_mp_div_2exp(&tmp, prime, bits - 1);
+    if (silc_mp_get_ui(&tmp) == 1) {
+      valid = TRUE;
+      break;
     }
-    
-    /* Passed the Fermat's test. And I don't think
-     * we have to do more tests. If anyone wants to do more
-     * tests, MP library has probability of prime test:
-     *
-     * if (silc_mp_probab_prime_p(prime, 25))
-     *     break;                          found a probable prime 
-     *
-     * However, this is very slow.
-     */
-    /* XXX: this could be done if some argument, say strict_primes, is
-       TRUE when we are willing to spend more time on the prime test and
-       to get, perhaps, better primes. */
-    silc_mp_set(prime, &oprime);
-    break;
   }
 
   silc_free(spmods);
@@ -308,34 +315,34 @@ bool silc_math_gen_prime(SilcMPInt *prime, SilcUInt32 bits, bool verbose,
   silc_mp_uninit(&tmp2);
   silc_mp_uninit(&oprime);
 
-  return TRUE;
+  return valid;
 }
 
-/* Performs primality testings for given number. Returns TRUE if the 
+/* Performs primality testings for given number. Returns TRUE if the
    number is probably a prime. */
 
 bool silc_math_prime_test(SilcMPInt *p)
 {
   SilcMPInt r, base, tmp;
   int i, ret = 0;
-  
+
   silc_mp_init(&r);
   silc_mp_init(&tmp);
   silc_mp_init(&base);
   silc_mp_set_ui(&base, 2);
-  
+
   SILC_LOG_DEBUG(("Testing probability of prime"));
 
   /* See if the number is divisible by any of the
      small primes in primetable[]. */
   for (i = 0; primetable[i] != 0; i++) {
     silc_mp_mod_ui(&tmp, p, primetable[i]);
-    
+
     /* If mod is 0, the number is composite */
     if (silc_mp_cmp_ui(&tmp, 0) == 0)
       ret = -1;
   }
-  
+
   /* Does the prime pass the Fermat's prime test.
    * r = 2 ^ p mod p, if r == 2, then p is probably a prime.
    */
@@ -346,7 +353,7 @@ bool silc_math_prime_test(SilcMPInt *p)
   silc_mp_uninit(&r);
   silc_mp_uninit(&tmp);
   silc_mp_uninit(&base);
-  
+
   if (ret)
     return FALSE;
 
diff --git a/lib/silcmath/tfm.c b/lib/silcmath/tfm.c
new file mode 100644 (file)
index 0000000..b99a32f
--- /dev/null
@@ -0,0 +1,5481 @@
+/* Start: fp_2expt.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* computes a = 2**b */
+void fp_2expt(fp_int *a, int b)
+{
+   int     z;
+
+   /* zero a as per default */
+   fp_zero (a);
+
+   if (b < 0) {
+      return;
+   }
+
+   z = b / DIGIT_BIT;
+   if (z >= FP_SIZE) {
+      return;
+   }
+
+  /* set the used count of where the bit will go */
+  a->used = z + 1;
+
+  /* put the single bit in its place */
+  a->dp[z] = ((fp_digit)1) << (b % DIGIT_BIT);
+}
+
+
+/* End: fp_2expt.c */
+
+/* Start: fp_add.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_add(fp_int *a, fp_int *b, fp_int *c)
+{
+  int     sa, sb;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    s_fp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (fp_cmp_mag (a, b) == FP_LT) {
+      c->sign = sb;
+      s_fp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      s_fp_sub (a, b, c);
+    }
+  }
+}
+
+/* End: fp_add.c */
+
+/* Start: fp_add_d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a + b */
+void fp_add_d(fp_int *a, fp_digit b, fp_int *c)
+{
+   fp_int tmp;
+   fp_set(&tmp, b);
+   fp_add(a,&tmp,c);
+}
+
+/* End: fp_add_d.c */
+
+/* Start: fp_addmod.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* d = a + b (mod c) */
+int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
+{
+  fp_int tmp;
+  fp_zero(&tmp);
+  fp_add(a, b, &tmp);
+  return fp_mod(&tmp, c, d);
+}
+
+/* End: fp_addmod.c */
+
+/* Start: fp_cmp.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+int fp_cmp(fp_int *a, fp_int *b)
+{
+   if (a->sign == FP_NEG && b->sign == FP_ZPOS) {
+      return FP_LT;
+   } else if (a->sign == FP_ZPOS && b->sign == FP_NEG) {
+      return FP_GT;
+   } else {
+      /* compare digits */
+      if (a->sign == FP_NEG) {
+         /* if negative compare opposite direction */
+         return fp_cmp_mag(b, a);
+      } else {
+         return fp_cmp_mag(a, b);
+      }
+   }
+}
+
+/* End: fp_cmp.c */
+
+/* Start: fp_cmp_d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* compare against a single digit */
+int fp_cmp_d(fp_int *a, fp_digit b)
+{
+  /* compare based on sign */
+  if ((b && a->used == 0) || a->sign == FP_NEG) {
+    return FP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return FP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return FP_GT;
+  } else if (a->dp[0] < b) {
+    return FP_LT;
+  } else {
+    return FP_EQ;
+  }
+
+}
+
+/* End: fp_cmp_d.c */
+
+/* Start: fp_cmp_mag.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+int fp_cmp_mag(fp_int *a, fp_int *b)
+{
+   int x;
+
+   if (a->used > b->used) {
+      return FP_GT;
+   } else if (a->used < b->used) {
+      return FP_LT;
+   } else {
+      for (x = a->used - 1; x >= 0; x--) {
+          if (a->dp[x] > b->dp[x]) {
+             return FP_GT;
+          } else if (a->dp[x] < b->dp[x]) {
+             return FP_LT;
+          }
+      }
+   }
+   return FP_EQ;
+}
+
+
+/* End: fp_cmp_mag.c */
+
+/* Start: fp_cnt_lsb.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+static const int lnz[16] = {
+   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int fp_cnt_lsb(fp_int *a)
+{
+   int x;
+   fp_digit q, qq;
+
+   /* easy out */
+   if (fp_iszero(a) == 1) {
+      return 0;
+   }
+
+   /* scan lower digits until non-zero */
+   for (x = 0; x < a->used && a->dp[x] == 0; x++);
+   q = a->dp[x];
+   x *= DIGIT_BIT;
+
+   /* now scan this digit until a 1 is found */
+   if ((q & 1) == 0) {
+      do {
+         qq  = q & 15;
+         x  += lnz[qq];
+         q >>= 4;
+      } while (qq == 0);
+   }
+   return x;
+}
+
+
+/* End: fp_cnt_lsb.c */
+
+/* Start: fp_count_bits.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+int fp_count_bits (fp_int * a)
+{
+  int     r;
+  fp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((fp_digit) 0)) {
+    ++r;
+    q >>= ((fp_digit) 1);
+  }
+  return r;
+}
+
+/* End: fp_count_bits.c */
+
+/* Start: fp_div.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* a/b => cb + d == a */
+int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
+{
+  fp_int  q, x, y, t1, t2;
+  int     n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (fp_iszero (b) == 1) {
+    return FP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (fp_cmp_mag (a, b) == FP_LT) {
+    if (d != NULL) {
+      fp_copy (a, d);
+    }
+    if (c != NULL) {
+      fp_zero (c);
+    }
+    return FP_OKAY;
+  }
+
+  fp_init(&q);
+  q.used = a->used + 2;
+
+  fp_init(&t1);
+  fp_init(&t2);
+  fp_init_copy(&x, a);
+  fp_init_copy(&y, b);
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG;
+  x.sign = y.sign = FP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = fp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     fp_mul_2d (&x, norm, &x);
+     fp_mul_2d (&y, norm, &y);
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  fp_lshd (&y, n - t);                                             /* y = y*b**{n-t} */
+
+  while (fp_cmp (&x, &y) != FP_LT) {
+    ++(q.dp[n - t]);
+    fp_sub (&x, &y, &x);
+  }
+
+  /* reset y by shifting it back down */
+  fp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((fp_word)1) << DIGIT_BIT) - 1);
+    } else {
+      fp_word tmp;
+      tmp = ((fp_word) x.dp[i]) << ((fp_word) DIGIT_BIT);
+      tmp |= ((fp_word) x.dp[i - 1]);
+      tmp /= ((fp_word) y.dp[t]);
+      q.dp[i - t - 1] = (fp_digit) (tmp);
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) >
+             xi * b**2 + xi-1 * b + xi-2
+
+       do q{i-t-1} -= 1;
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1);
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1);
+
+      /* find left hand */
+      fp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      fp_mul_d (&t1, q.dp[i - t - 1], &t1);
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (fp_cmp_mag(&t1, &t2) == FP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    fp_mul_d (&y, q.dp[i - t - 1], &t1);
+    fp_lshd  (&t1, i - t - 1);
+    fp_sub   (&x, &t1, &x);
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == FP_NEG) {
+      fp_copy (&y, &t1);
+      fp_lshd (&t1, i - t - 1);
+      fp_add (&x, &t1, &x);
+      q.dp[i - t - 1] = q.dp[i - t - 1] - 1;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder
+   * [which we have to normalize]
+   */
+
+  /* get sign before writing to c */
+  x.sign = x.used == 0 ? FP_ZPOS : a->sign;
+
+  if (c != NULL) {
+    fp_clamp (&q);
+    fp_copy (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    fp_div_2d (&x, norm, &x, NULL);
+
+/* the following is a kludge, essentially we were seeing the right remainder but
+   with excess digits that should have been zero
+ */
+    for (i = b->used; i < x.used; i++) {
+        x.dp[i] = 0;
+    }
+    fp_clamp(&x);
+    fp_copy (&x, d);
+  }
+
+  return FP_OKAY;
+}
+
+/* End: fp_div.c */
+
+/* Start: fp_div_2.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* b = a/2 */
+void fp_div_2(fp_int * a, fp_int * b)
+{
+  int     x, oldused;
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register fp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  fp_clamp (b);
+}
+
+/* End: fp_div_2.c */
+
+/* Start: fp_div_2d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a / 2**b */
+void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d)
+{
+  fp_digit D, r, rr;
+  int      x;
+  fp_int   t;
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    fp_copy (a, c);
+    if (d != NULL) {
+      fp_zero (d);
+    }
+    return;
+  }
+
+  fp_init(&t);
+
+  /* get the remainder */
+  if (d != NULL) {
+    fp_mod_2d (a, b, &t);
+  }
+
+  /* copy */
+  fp_copy(a, c);
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    fp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (fp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register fp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((fp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  fp_clamp (c);
+  if (d != NULL) {
+    fp_copy (&t, d);
+  }
+}
+
+/* End: fp_div_2d.c */
+
+/* Start: fp_div_d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+static int s_is_power_of_two(fp_digit b, int *p)
+{
+   int x;
+
+   for (x = 1; x < DIGIT_BIT; x++) {
+      if (b == (((fp_digit)1)<<x)) {
+         *p = x;
+         return 1;
+      }
+   }
+   return 0;
+}
+
+/* a/b => cb + d == a */
+int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d)
+{
+  fp_int   q;
+  fp_word  w;
+  fp_digit t;
+  int      ix;
+
+  /* cannot divide by zero */
+  if (b == 0) {
+     return FP_VAL;
+  }
+
+  /* quick outs */
+  if (b == 1 || fp_iszero(a) == 1) {
+     if (d != NULL) {
+        *d = 0;
+     }
+     if (c != NULL) {
+        fp_copy(a, c);
+     }
+     return FP_OKAY;
+  }
+
+  /* power of two ? */
+  if (s_is_power_of_two(b, &ix) == 1) {
+     if (d != NULL) {
+        *d = a->dp[0] & ((((fp_digit)1)<<ix) - 1);
+     }
+     if (c != NULL) {
+        fp_div_2d(a, ix, c, NULL);
+     }
+     return FP_OKAY;
+  }
+
+  /* no easy answer [c'est la vie].  Just division */
+  fp_init(&q);
+
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((fp_word)DIGIT_BIT)) | ((fp_word)a->dp[ix]);
+
+     if (w >= b) {
+        t = (fp_digit)(w / b);
+        w -= ((fp_word)t) * ((fp_word)b);
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (fp_digit)t;
+  }
+
+  if (d != NULL) {
+     *d = (fp_digit)w;
+  }
+
+  if (c != NULL) {
+     fp_clamp(&q);
+     fp_copy(&q, c);
+  }
+
+  return FP_OKAY;
+}
+
+
+/* End: fp_div_d.c */
+
+/* Start: fp_exptmod.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* y = g**x (mod b)
+ * Some restrictions... x must be positive and < b
+ */
+static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
+{
+  fp_int   M[64], res;
+  fp_digit buf, mp;
+  int      err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* find window size */
+  x = fp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else {
+    winsize = 6;
+  }
+
+  /* init M array */
+  memset(M, 0, sizeof(M));
+
+  /* now setup montgomery  */
+  if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) {
+     return err;
+  }
+
+  /* setup result */
+  fp_init(&res);
+
+  /* create M table
+   *
+   * The M table contains powers of the input base, e.g. M[x] = G^x mod P
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+   /* now we need R mod m */
+   fp_montgomery_calc_normalization (&res, P);
+
+   /* now set M[1] to G * R mod m */
+   if (fp_cmp_mag(P, G) != FP_GT) {
+      /* G > P so we reduce it first */
+      fp_mod(G, P, &M[1]);
+   } else {
+      fp_copy(G, &M[1]);
+   }
+   fp_mulmod (&M[1], &res, P, &M[1]);
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  fp_copy (&M[1], &M[1 << (winsize - 1)]);
+  for (x = 0; x < (winsize - 1); x++) {
+    fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]);
+    fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp);
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    fp_mul(&M[x - 1], &M[1], &M[x]);
+    fp_montgomery_reduce(&M[x], P, mp);
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (fp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (fp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      fp_sqr(&res, &res);
+      fp_montgomery_reduce(&res, P, mp);
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        fp_sqr(&res, &res);
+        fp_montgomery_reduce(&res, P, mp);
+      }
+
+      /* then multiply */
+      fp_mul(&res, &M[bitbuf], &res);
+      fp_montgomery_reduce(&res, P, mp);
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      fp_sqr(&res, &res);
+      fp_montgomery_reduce(&res, P, mp);
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        fp_mul(&res, &M[1], &res);
+        fp_montgomery_reduce(&res, P, mp);
+      }
+    }
+  }
+
+  /* fixup result if Montgomery reduction is used
+   * recall that any value in a Montgomery system is
+   * actually multiplied by R mod n.  So we have
+   * to reduce one more time to cancel out the factor
+   * of R.
+   */
+  fp_montgomery_reduce(&res, P, mp);
+
+  /* swap res with Y */
+  fp_copy (&res, Y);
+  return FP_OKAY;
+}
+
+
+int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
+{
+   fp_int tmp;
+   int    err;
+
+   /* is X negative?  */
+   if (X->sign == FP_NEG) {
+      /* yes, copy G and invmod it */
+      fp_copy(G, &tmp);
+      if ((err = fp_invmod(&tmp, P, &tmp)) != FP_OKAY) {
+         return err;
+      }
+      X->sign = FP_ZPOS;
+      err =  _fp_exptmod(&tmp, X, P, Y);
+      X->sign = FP_NEG;
+      return err;
+   } else {
+      /* Positive exponent so just exptmod */
+      return _fp_exptmod(G, X, P, Y);
+   }
+}
+
+/* End: fp_exptmod.c */
+
+/* Start: fp_gcd.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = (a, b) */
+void fp_gcd(fp_int *a, fp_int *b, fp_int *c)
+{
+   fp_int u, v, r;
+
+   /* either zero than gcd is the largest */
+   if (fp_iszero (a) == 1 && fp_iszero (b) == 0) {
+     fp_abs (b, c);
+     return;
+   }
+   if (fp_iszero (a) == 0 && fp_iszero (b) == 1) {
+     fp_abs (a, c);
+     return;
+   }
+
+   /* optimized.  At this point if a == 0 then
+    * b must equal zero too
+    */
+   if (fp_iszero (a) == 1) {
+     fp_zero(c);
+     return;
+   }
+
+   /* sort inputs */
+   if (fp_cmp_mag(a, b) != FP_LT) {
+      fp_init_copy(&u, a);
+      fp_init_copy(&v, b);
+   } else {
+      fp_init_copy(&u, b);
+      fp_init_copy(&v, a);
+   }
+
+   fp_zero(&r);
+   while (fp_iszero(&v) == FP_NO) {
+      fp_mod(&u, &v, &r);
+      fp_copy(&v, &u);
+      fp_copy(&r, &v);
+   }
+   fp_copy(&u, c);
+}
+
+/* End: fp_gcd.c */
+
+/* Start: fp_ident.c */
+#include "tfm.h"
+
+const char *fp_ident(void)
+{
+   static char buf[1024];
+
+   memset(buf, 0, sizeof(buf));
+   snprintf(buf, sizeof(buf)-1,
+"TomsFastMath (%s)\n"
+"\n"
+"Sizeofs\n"
+"\tfp_digit = %u\n"
+"\tfp_word  = %u\n"
+"\n"
+"FP_MAX_SIZE = %u\n"
+"\n"
+"Defines: \n"
+#ifdef __i386__
+" __i386__ "
+#endif
+#ifdef __x86_64__
+" __x86_64__ "
+#endif
+#ifdef TFM_X86
+" TFM_X86 "
+#endif
+#ifdef TFM_X86_64
+" TFM_X86_64 "
+#endif
+#ifdef TFM_SSE2
+" TFM_SSE2 "
+#endif
+#ifdef TFM_ARM
+" TFM_ARM "
+#endif
+#ifdef TFM_NO_ASM
+" TFM_NO_ASM "
+#endif
+#ifdef FP_64BIT
+" FP_64BIT "
+#endif
+#ifdef TFM_LARGE
+" TFM_LARGE "
+#endif
+#ifdef TFM_HUGE
+" TFM_HUGE "
+#endif
+"\n", __DATE__, sizeof(fp_digit), sizeof(fp_word), FP_MAX_SIZE);
+
+   if (sizeof(fp_digit) == sizeof(fp_word)) {
+      strncat(buf, "WARNING: sizeof(fp_digit) == sizeof(fp_word), this build is likely to not work properly.\n",
+              sizeof(buf)-1);
+   }
+   return buf;
+}
+
+#ifdef STANDALONE
+
+int main(void)
+{
+   printf("%s\n", fp_ident());
+   return 0;
+}
+
+#endif
+
+
+/* End: fp_ident.c */
+
+/* Start: fp_invmod.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = 1/a (mod b) for odd b only */
+int fp_invmod(fp_int *a, fp_int *b, fp_int *c)
+{
+  fp_int  x, y, u, v, B, D;
+  int     neg;
+
+  /* 2. [modified] b must be odd   */
+  if (fp_iseven (b) == FP_YES) {
+    return FP_VAL;
+  }
+
+  /* init all our temps */
+  fp_init(&x);  fp_init(&y);
+  fp_init(&u);  fp_init(&v);
+  fp_init(&B);  fp_init(&D);
+
+  /* x == modulus, y == value to invert */
+  fp_copy(b, &x);
+
+  /* we need y = |a| */
+  fp_abs(a, &y);
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  fp_copy(&x, &u);
+  fp_copy(&y, &v);
+  fp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (fp_iseven (&u) == FP_YES) {
+    /* 4.1 u = u/2 */
+    fp_div_2 (&u, &u);
+
+    /* 4.2 if B is odd then */
+    if (fp_isodd (&B) == FP_YES) {
+      fp_sub (&B, &x, &B);
+    }
+    /* B = B/2 */
+    fp_div_2 (&B, &B);
+  }
+
+  /* 5.  while v is even do */
+  while (fp_iseven (&v) == FP_YES) {
+    /* 5.1 v = v/2 */
+    fp_div_2 (&v, &v);
+
+    /* 5.2 if D is odd then */
+    if (fp_isodd (&D) == FP_YES) {
+      /* D = (D-x)/2 */
+      fp_sub (&D, &x, &D);
+    }
+    /* D = D/2 */
+    fp_div_2 (&D, &D);
+  }
+
+  /* 6.  if u >= v then */
+  if (fp_cmp (&u, &v) != FP_LT) {
+    /* u = u - v, B = B - D */
+    fp_sub (&u, &v, &u);
+    fp_sub (&B, &D, &B);
+  } else {
+    /* v - v - u, D = D - B */
+    fp_sub (&v, &u, &v);
+    fp_sub (&D, &B, &D);
+  }
+
+  /* if not zero goto step 4 */
+  if (fp_iszero (&u) == FP_NO) {
+    goto top;
+  }
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (fp_cmp_d (&v, 1) != FP_EQ) {
+    return FP_VAL;
+  }
+
+  /* b is now the inverse */
+  neg = a->sign;
+  while (D.sign == FP_NEG) {
+    fp_add (&D, b, &D);
+  }
+  fp_copy (&D, c);
+  c->sign = neg;
+  return FP_OKAY;
+}
+
+/* End: fp_invmod.c */
+
+/* Start: fp_isprime.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* a few primes */
+static const fp_digit primes[256] = {
+  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083,
+  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+};
+
+int fp_isprime(fp_int *a)
+{
+   fp_int   b;
+   fp_digit d;
+   int      r, res;
+
+   /* do trial division */
+   for (r = 0; r < 256; r++) {
+       fp_mod_d(a, primes[r], &d);
+       if (d == 0) {
+          return FP_NO;
+       }
+   }
+
+   /* now do 8 miller rabins */
+   for (r = 0; r < 8; r++) {
+       fp_set(&b, primes[r]);
+       fp_prime_miller_rabin(a, &b, &res);
+       if (res == FP_NO) {
+          return FP_NO;
+       }
+   }
+   return FP_YES;
+}
+
+/* End: fp_isprime.c */
+
+/* Start: fp_lcm.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = [a, b] */
+void fp_lcm(fp_int *a, fp_int *b, fp_int *c)
+{
+   fp_int  t1, t2;
+
+   fp_init(&t1);
+   fp_init(&t2);
+   fp_gcd(a, b, &t1);
+   if (fp_cmp_mag(a, b) == FP_GT) {
+      fp_div(a, &t1, &t2, NULL);
+      fp_mul(b, &t2, c);
+   } else {
+      fp_div(b, &t1, &t2, NULL);
+      fp_mul(a, &t2, c);
+   }
+}
+
+/* End: fp_lcm.c */
+
+/* Start: fp_lshd.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_lshd(fp_int *a, int x)
+{
+   int y;
+
+   /* move up and truncate as required */
+   y = MIN(a->used + x - 1, (int)(FP_SIZE-1));
+
+   /* store new size */
+   a->used = y + 1;
+
+   /* move digits */
+   for (; y >= x; y--) {
+       a->dp[y] = a->dp[y-x];
+   }
+
+   /* zero lower digits */
+   for (; y >= 0; y--) {
+       a->dp[y] = 0;
+   }
+
+   /* clamp digits */
+   fp_clamp(a);
+}
+
+/* End: fp_lshd.c */
+
+/* Start: fp_mod.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a mod b, 0 <= c < b  */
+int fp_mod(fp_int *a, fp_int *b, fp_int *c)
+{
+   fp_int t;
+   int    err;
+
+   fp_zero(&t);
+   if ((err = fp_div(a, b, NULL, &t)) != FP_OKAY) {
+      return err;
+   }
+   if (t.sign != b->sign) {
+      fp_add(&t, b, c);
+   } else {
+      fp_copy(&t, c);
+  }
+  return FP_OKAY;
+}
+
+
+
+/* End: fp_mod.c */
+
+/* Start: fp_mod_2d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a mod 2**d */
+void fp_mod_2d(fp_int *a, int b, fp_int *c)
+{
+   int x;
+
+   /* zero if count less than or equal to zero */
+   if (b <= 0) {
+      fp_zero(c);
+      return;
+   }
+
+   /* get copy of input */
+   fp_copy(a, c);
+
+   /* if 2**d is larger than we just return */
+   if (b >= (DIGIT_BIT * a->used)) {
+      return;
+   }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &= ~((fp_digit)0) >> (DIGIT_BIT - b);
+  fp_clamp (c);
+}
+
+/* End: fp_mod_2d.c */
+
+/* Start: fp_mod_d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a mod b, 0 <= c < b  */
+int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c)
+{
+   return fp_div_d(a, b, NULL, c);
+}
+
+/* End: fp_mod_d.c */
+
+/* Start: fp_montgomery_calc_normalization.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+void fp_montgomery_calc_normalization(fp_int *a, fp_int *b)
+{
+  int     x, bits;
+
+  /* how many bits of last digit does b use */
+  bits = fp_count_bits (b) % DIGIT_BIT;
+
+  /* compute A = B^(n-1) * 2^(bits-1) */
+  if (b->used > 1) {
+     fp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1);
+  } else {
+     fp_set(a, 1);
+     bits = 1;
+  }
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    fp_mul_2 (a, a);
+    if (fp_cmp_mag (a, b) != FP_LT) {
+      s_fp_sub (a, b, a);
+    }
+  }
+}
+
+
+/* End: fp_montgomery_calc_normalization.c */
+
+/* Start: fp_montgomery_reduce.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+#if defined(TFM_X86)
+
+/* x86-32 code */
+
+#define MONT_START
+
+#define MONT_FINI
+
+#define LOOP_START \
+   mu = c[x] * mp;
+
+#define INNERMUL \
+asm(                                                                                          \
+"movl %7,%%eax                \n\t"                                                           \
+"mull %6                      \n\t"                                                           \
+"addl %%eax,%0                \n\t"                                                           \
+"adcl %%edx,%1                \n\t"                                                           \
+"adcl $0,%2                   \n\t"                                                           \
+:"=g"(_c[OFF0]), "=g"(_c[OFF1]), "=g"(_c[OFF2]):"0"(_c[OFF0]), "1"(_c[OFF1]), "2"(_c[OFF2]),  \
+                                                "g"(mu), "g"(*tmpm++)                          \
+                                               : "%eax", "%edx", "%cc");
+
+#define PROPCARRY \
+asm(                                                                                               \
+"movl %1,%%eax                \n\t"                                                                \
+"addl  %%eax,%6               \n\t"                                                                \
+"movl %2,%%eax                \n\t"                                                                \
+"adcl  %%eax,%7               \n\t"                                                                \
+"adcl $0,%8                   \n\t"                                                                \
+:"=g"(_c[OFF0]), "=g"(_c[OFF1]), "=g"(_c[OFF2]):"0"(_c[OFF0]), "1"(_c[OFF1]), "2"(_c[OFF2]),       \
+                                                "m"(_c[OFF0+1]), "m"(_c[OFF1+1]), "m"(_c[OFF2+1])  \
+: "%eax", "%cc");
+
+#elif defined(TFM_X86_64)
+/* x86-64 code */
+
+#define MONT_START
+
+#define MONT_FINI
+
+#define LOOP_START \
+   mu = c[x] * mp;
+
+#define INNERMUL \
+asm(                                                                                          \
+"movq %7,%%rax                \n\t"                                                           \
+"mulq %6                      \n\t"                                                           \
+"addq %%rax,%0                \n\t"                                                           \
+"adcq %%rdx,%1                \n\t"                                                           \
+"adcq $0,%2                   \n\t"                                                           \
+:"=g"(_c[OFF0]), "=g"(_c[OFF1]), "=g"(_c[OFF2]):"0"(_c[OFF0]), "1"(_c[OFF1]), "2"(_c[OFF2]),  \
+                                                "g"(mu), "g"(*tmpm++)                          \
+                                               : "%rax", "%rdx", "%cc");
+
+#define PROPCARRY \
+asm(                                                                                               \
+"movq %1,%%rax                \n\t"                                                                \
+"movq %2,%%rbx                \n\t"                                                                \
+"addq  %%rax,%6               \n\t"                                                                \
+"adcq  %%rbx,%7               \n\t"                                                                \
+"adcq $0,%8                   \n\t"                                                                \
+:"=g"(_c[OFF0]), "=g"(_c[OFF1]), "=g"(_c[OFF2]):"0"(_c[OFF0]), "1"(_c[OFF1]), "2"(_c[OFF2]),       \
+                                                "m"(_c[OFF0+1]), "m"(_c[OFF1+1]), "m"(_c[OFF2+1])  \
+: "%rax", "%rbx", "%cc");
+
+#elif defined(TFM_SSE2)
+
+/* SSE2 code */
+
+#define MONT_START \
+asm("movd %0,%%mm2"::"g"(mp));
+
+#define MONT_FINI \
+asm("emms");
+
+#define LOOP_START \
+asm(\
+"movd %0,%%mm1                \n\t" \
+"pmuludq %%mm2,%%mm1          \n\t" \
+:: "g"(c[x]));
+
+#define INNERMUL \
+asm(                                                                                          \
+"movd %6,%%mm0                \n\t"                                                           \
+"pmuludq %%mm1,%%mm0          \n\t"                                                           \
+"movd %%mm0,%%eax             \n\t"                                                           \
+"psrlq $32, %%mm0             \n\t"                                                           \
+"addl %%eax,%0                \n\t"                                                           \
+"movd %%mm0,%%eax             \n\t"                                                           \
+"adcl %%eax,%1                \n\t"                                                           \
+"adcl $0,%2                   \n\t"                                                           \
+:"=g"(_c[OFF0]), "=g"(_c[OFF1]), "=g"(_c[OFF2]):"0"(_c[OFF0]), "1"(_c[OFF1]), "2"(_c[OFF2]),  \
+                                                "g"(*tmpm++)                                  \
+                                               : "%eax", "%cc");
+
+#define PROPCARRY \
+asm(                                                                                               \
+"movl %1,%%eax                \n\t"                                                                \
+"addl  %%eax,%6               \n\t"                                                                \
+"movl %2,%%eax                \n\t"                                                                \
+"adcl  %%eax,%7               \n\t"                                                                \
+"adcl $0,%8                   \n\t"                                                                \
+:"=g"(_c[OFF0]), "=g"(_c[OFF1]), "=g"(_c[OFF2]):"0"(_c[OFF0]), "1"(_c[OFF1]), "2"(_c[OFF2]),       \
+                                                "g"(_c[OFF0+1]), "g"(_c[OFF1+1]), "g"(_c[OFF2+1])  \
+: "%eax", "%cc");
+
+#elif defined(TFM_ARM)
+
+/* ISO C code */
+#define MONT_START
+
+#define MONT_FINI
+
+#define LOOP_START \
+   mu = c[x] * mp;
+
+/* NOTE: later write it using two regs instead of three for _c + ... */
+#define INNERMUL \
+asm(                                             \
+"UMULL r0,r1,%0,%1                \n\t"          \
+"LDR   r2,[%2]                    \n\t"          \
+"ADDS  r2,r2,r0                   \n\t"          \
+"STR   r2,[%2]                    \n\t"          \
+"LDR   r2,[%3]                    \n\t"          \
+"ADCS  r2,r2,r1                   \n\t"          \
+"STR   r2,[%3]                    \n\t"          \
+"LDR   r2,[%4]                    \n\t"          \
+"ADC   r2,r2,#0                   \n\t"          \
+"STR   r2,[%4]                    \n\t"          \
+::"r"(mu),"r"(*tmpm++),"r"(_c + OFF0),"r"(_c + OFF1),"r"(_c + OFF2):"r0", "r1", "r2", "%cc");
+
+#define PROPCARRY \
+asm(                                             \
+"LDR   r0,[%1]                    \n\t"          \
+"LDR   r1,[%0,#4]                 \n\t"          \
+"ADDS  r0,r0,r1                   \n\t"          \
+"STR   r0,[%0,#4]                 \n\t"          \
+"LDR   r0,[%2]                    \n\t"          \
+"LDR   r1,[%1,#4]                 \n\t"          \
+"ADCS  r0,r0,r1                   \n\t"          \
+"STR   r0,[%1,#4]                 \n\t"          \
+"LDR   r0,[%2,#4]                 \n\t"          \
+"ADC   r0,r0,#0                   \n\t"          \
+"STR   r0,[%2,#4]                 \n\t"          \
+::"r"(_c + OFF0),"r"(_c + OFF1),"r"(_c + OFF2):"r0", "r1", "%cc");
+
+#else
+
+/* ISO C code */
+#define MONT_START
+
+#define MONT_FINI
+
+#define LOOP_START \
+   mu = c[x] * mp;
+
+#define INNERMUL \
+   do { fp_word t;                                                           \
+   t = (fp_word)_c[OFF0] + ((fp_word)mu) * ((fp_word)*tmpm++); _c[OFF0] = t; \
+   t = (fp_word)_c[OFF1] + (t >> DIGIT_BIT);                   _c[OFF1] = t; \
+   _c[OFF2] += (t >> DIGIT_BIT);                                             \
+   } while (0);
+
+#define PROPCARRY \
+   do { fp_word t;                                                           \
+   t = (fp_word)_c[OFF0+1] + (fp_word)_c[OFF1];                    _c[OFF0+1] = t; \
+   t = (fp_word)_c[OFF1+1] + (t >> DIGIT_BIT) + (fp_word)_c[OFF2]; _c[OFF1+1] = t; \
+   _c[OFF2+1] += (t >> DIGIT_BIT);                                           \
+   } while (0);
+
+#endif
+
+
+#define OFF0  (0)
+#define OFF1  (FP_SIZE)
+#define OFF2  (FP_SIZE+FP_SIZE)
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp)
+{
+   fp_digit c[3*FP_SIZE], *_c, *tmpm, mu;
+   int      oldused, x, y, pa;
+
+   /* now zero the buff */
+   pa = m->used;
+   memset(c, 0, sizeof(c));
+
+   /* copy the input */
+   oldused = a->used;
+   for (x = 0; x < oldused; x++) {
+       c[x] = a->dp[x];
+   }
+
+   MONT_START;
+
+   /* now let's get bizz-sy! */
+   for (x = 0; x < pa; x++) {
+       /* get Mu for this round */
+       LOOP_START;
+
+       /* our friendly neighbourhood alias */
+       _c   = c + x;
+       tmpm = m->dp;
+
+       for (y = 0; y < pa; y++) {
+          INNERMUL;
+          ++_c;
+       }
+       /* send carry up man... */
+       _c = c + x;
+       PROPCARRY;
+  }
+
+  /* fix the rest of the carries */
+  _c = c + pa;
+  for (x = pa; x < pa * 2 + 2; x++) {
+     PROPCARRY;
+     ++_c;
+  }
+
+  /* now copy out */
+  _c   = c + pa;
+  tmpm = a->dp;
+  for (x = 0; x < pa+1; x++) {
+     *tmpm++ = *_c++;
+  }
+
+  for (; x < oldused; x++)   {
+     *tmpm++ = 0;
+  }
+
+  MONT_FINI;
+
+  a->used = pa+1;
+  fp_clamp(a);
+
+  /* if A >= m then A = A - m */
+  if (fp_cmp_mag (a, m) != FP_LT) {
+    s_fp_sub (a, m, a);
+  }
+}
+
+/* End: fp_montgomery_reduce.c */
+
+/* Start: fp_montgomery_setup.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* setups the montgomery reduction */
+int fp_montgomery_setup(fp_int *a, fp_digit *rho)
+{
+  fp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = a->dp[0];
+
+  if ((b & 1) == 0) {
+    return FP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#ifdef FP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (((fp_word) 1 << ((fp_word) DIGIT_BIT)) - ((fp_word)x));
+
+  return FP_OKAY;
+}
+
+
+/* End: fp_montgomery_setup.c */
+
+/* Start: fp_mul.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a * b */
+void fp_mul(fp_int *A, fp_int *B, fp_int *C)
+{
+    int    r, y, yy, s;
+    fp_int ac, bd, comp, amb, cmd, t1, t2;
+
+     y  = MAX(A->used, B->used);
+     yy = MIN(A->used, B->used);
+     if (yy <= 8 || y <= 64) {
+
+    /* pick a comba (unrolled 4/8/16/32 x or rolled) based on the size
+       of the largest input.  We also want to avoid doing excess mults if the
+       inputs are not close to the next power of two.  That is, for example,
+       if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications
+    */
+        if (y <= 4) {
+           fp_mul_comba4(A,B,C);
+        } else if (y <= 8) {
+           fp_mul_comba8(A,B,C);
+#if defined(TFM_LARGE)
+        } else if (y <= 16 && y >= 10) {
+           fp_mul_comba16(A,B,C);
+#endif
+#if defined(TFM_HUGE)
+        } else if (y <= 32 && y >= 24) {
+           fp_mul_comba32(A,B,C);
+#endif
+        } else {
+           fp_mul_comba(A,B,C);
+        }
+    } else {
+        /* do the karatsuba action
+
+           if A = ab and B = cd for ||a|| = r we need to solve
+
+           ac*r^2 + (-(a-b)(c-d) + ac + bd)*r + bd
+
+           So we solve for the three products then we form the final result with careful shifting
+           and addition.
+
+Obvious points of optimization
+
+- "ac" parts can be memcpy'ed with an offset [all you have to do is zero upto the next 8 digits]
+- Similarly the "bd" parts can be memcpy'ed and zeroed to 8
+-
+
+        */
+        /* get our value of r */
+        r = yy >> 1;
+
+        /* now solve for ac */
+//        fp_copy(A, &t1); fp_rshd(&t1, r);
+        for (s = 0; s < A->used - r; s++) {
+            t1.dp[s] = A->dp[s+r];
+        }
+        for (; s < FP_SIZE; s++) {
+            t1.dp[s] = 0;
+        }
+        if (A->used >= r) {
+           t1.used = A->used - r;
+        } else {
+           t1.used = 0;
+        }
+        t1.sign = A->sign;
+
+//        fp_copy(B, &t2); fp_rshd(&t2, r);
+        for (s = 0; s < B->used - r; s++) {
+            t2.dp[s] = B->dp[s+r];
+        }
+        for (; s < FP_SIZE; s++) {
+            t2.dp[s] = 0;
+        }
+        if (B->used >= r) {
+           t2.used = B->used - r;
+        } else {
+           t2.used = 0;
+        }
+        t2.sign = B->sign;
+
+        fp_copy(&t1, &amb); fp_copy(&t2, &cmd);
+        fp_zero(&ac);
+        fp_mul(&t1, &t2, &ac);
+
+        /* now solve for bd */
+//        fp_mod_2d(A, r * DIGIT_BIT, &t1);
+//        fp_mod_2d(B, r * DIGIT_BIT, &t2);
+        for (s = 0; s < r; s++) {
+            t1.dp[s] = A->dp[s];
+            t2.dp[s] = B->dp[s];
+        }
+        for (; s < FP_SIZE; s++) {
+            t1.dp[s]   = 0;
+            t2.dp[s] = 0;
+        }
+        t1.used = r;
+        t2.used = r;
+        fp_clamp(&t1);
+        fp_clamp(&t2);
+
+        fp_sub(&amb, &t1, &amb); fp_sub(&cmd, &t2, &cmd);
+        fp_zero(&bd);
+        fp_mul(&t1, &t2, &bd);
+
+        /* now get the (a-b)(c-d) term */
+        fp_zero(&comp);
+        fp_mul(&amb, &cmd, &comp);
+
+        /* now solve the system, do the middle term first */
+        comp.sign ^= 1;
+        fp_add(&comp, &ac, &comp);
+        fp_add(&comp, &bd, &comp);
+        fp_lshd(&comp, r);
+
+        /* leading term */
+        fp_lshd(&ac, r+r);
+
+        /* now sum them together */
+        s = A->sign ^ B->sign;
+        fp_zero(C);
+        fp_add(&ac, &comp, C);
+        fp_add(&bd, C, C);
+        C->sign = C->used ? s : FP_ZPOS;
+    }
+}
+
+
+/* End: fp_mul.c */
+
+/* Start: fp_mul_2.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_mul_2(fp_int * a, fp_int * b)
+{
+  int     x, oldused;
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register fp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+
+      /* get what will be the *next* carry bit from the
+       * MSB of the current digit
+       */
+      rr = *tmpa >> ((fp_digit)(DIGIT_BIT - 1));
+
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((fp_digit)1)) | r);
+
+      /* copy the carry that would be from the source
+       * digit into the next iteration
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0 && b->used != (FP_SIZE-1)) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination
+     * that we didn't write to
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+}
+
+
+/* End: fp_mul_2.c */
+
+/* Start: fp_mul_2d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a * 2**d */
+void fp_mul_2d(fp_int *a, int b, fp_int *c)
+{
+   fp_digit carry, carrytmp, shift;
+   int x;
+
+   /* copy it */
+   fp_copy(a, c);
+
+   /* handle whole digits */
+   if (b >= DIGIT_BIT) {
+      fp_lshd(c, b/DIGIT_BIT);
+   }
+   b %= DIGIT_BIT;
+
+   /* shift the digits */
+   if (b != 0) {
+      carry = 0;
+      shift = DIGIT_BIT - b;
+      for (x = 0; x < c->used; x++) {
+          carrytmp = c->dp[x] >> shift;
+          c->dp[x] = (c->dp[x] << b) + carry;
+          carry = carrytmp;
+      }
+      /* store last carry if room */
+      if (carry && x < FP_SIZE) {
+         c->dp[c->used++] = carry;
+      }
+   }
+   fp_clamp(c);
+}
+
+
+/* End: fp_mul_2d.c */
+
+/* Start: fp_mul_comba.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+
+/* About this file...
+
+*/
+
+#include <tfm.h>
+
+/* these are the combas.  Worship them. */
+#if defined(TFM_X86)
+/* Generic x86 optimized code */
+
+/* anything you need at the start */
+#define COMBA_START
+
+/* clear the chaining variables */
+#define COMBA_CLEAR \
+   c0 = c1 = c2 = 0;
+
+/* forward the carry to the next digit */
+#define COMBA_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+/* store the first sum */
+#define COMBA_STORE(x) \
+   x = c0;
+
+/* store the second sum [carry] */
+#define COMBA_STORE2(x) \
+   x = c1;
+
+/* anything you need at the end */
+#define COMBA_FINI
+
+/* this should multiply i and j  */
+#define MULADD(i, j)                                      \
+asm (                                                     \
+     "movl  %6,%%eax     \n\t"                            \
+     "mull  %7           \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","%edx","%cc");
+
+#elif defined(TFM_X86_64)
+/* x86-64 optimized */
+
+/* anything you need at the start */
+#define COMBA_START
+
+/* clear the chaining variables */
+#define COMBA_CLEAR \
+   c0 = c1 = c2 = 0;
+
+/* forward the carry to the next digit */
+#define COMBA_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+/* store the first sum */
+#define COMBA_STORE(x) \
+   x = c0;
+
+/* store the second sum [carry] */
+#define COMBA_STORE2(x) \
+   x = c1;
+
+/* anything you need at the end */
+#define COMBA_FINI
+
+/* this should multiply i and j  */
+#define MULADD(i, j)                                      \
+asm  (                                                    \
+     "movq  %6,%%rax     \n\t"                            \
+     "mulq  %7           \n\t"                            \
+     "addq  %%rax,%0     \n\t"                            \
+     "adcq  %%rdx,%1     \n\t"                            \
+     "adcq  $0,%2        \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j)  :"%rax","%rdx","%cc");
+
+#elif defined(TFM_SSE2)
+/* use SSE2 optimizations */
+
+/* anything you need at the start */
+#define COMBA_START
+
+/* clear the chaining variables */
+#define COMBA_CLEAR \
+   c0 = c1 = c2 = 0;
+
+/* forward the carry to the next digit */
+#define COMBA_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+/* store the first sum */
+#define COMBA_STORE(x) \
+   x = c0;
+
+/* store the second sum [carry] */
+#define COMBA_STORE2(x) \
+   x = c1;
+
+/* anything you need at the end */
+#define COMBA_FINI \
+   asm("emms");
+
+/* this should multiply i and j  */
+   #define MULADD(i, j)                                      \
+   asm volatile (                                            \
+        "movd  %6,%%mm0     \n\t"                            \
+        "movd  %7,%%mm1     \n\t"                            \
+        "pmuludq %%mm1,%%mm0\n\t"                            \
+        "movd  %%mm0,%%eax  \n\t"                            \
+        "psrlq $32,%%mm0    \n\t"                            \
+        "addl  %%eax,%0     \n\t"                            \
+        "movd  %%mm0,%%eax  \n\t"                            \
+        "adcl  %%eax,%1     \n\t"                            \
+        "adcl  $0,%2        \n\t"                            \
+        :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","%cc");
+
+#elif defined(TFM_ARM)
+/* ARM code */
+
+#define COMBA_START
+
+#define COMBA_CLEAR \
+   c0 = c1 = c2 = 0;
+
+#define COMBA_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+#define COMBA_STORE(x) \
+   x = c0;
+
+#define COMBA_STORE2(x) \
+   x = c1;
+
+#define COMBA_FINI
+
+#define MULADD(i, j)                                          \
+asm(                                                          \
+"  UMULL  r0,r1,%6,%7           \n\t"                         \
+"  ADDS   %0,%0,r0              \n\t"                         \
+"  ADCS   %1,%1,r1              \n\t"                         \
+"  ADC    %2, %2, #0            \n\t"                         \
+:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc");
+
+#else
+/* ISO C code */
+
+#define COMBA_START
+
+#define COMBA_CLEAR \
+   c0 = c1 = c2 = 0;
+
+#define COMBA_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+#define COMBA_STORE(x) \
+   x = c0;
+
+#define COMBA_STORE2(x) \
+   x = c1;
+
+#define COMBA_FINI
+
+#define MULADD(i, j)                                                              \
+   do { fp_word t;                                                                \
+   t = (fp_word)c0 + ((fp_word)i) * ((fp_word)j); c0 = t;                         \
+   t = (fp_word)c1 + (t >> DIGIT_BIT);            c1 = t; c2 += t >> DIGIT_BIT;   \
+   } while (0);
+
+#endif
+
+
+/* generic PxQ multiplier */
+void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C)
+{
+   int       ix, iy, iz, tx, ty, pa;
+   fp_digit  c0, c1, c2, *tmpx, *tmpy;
+   fp_int    tmp, *dst;
+
+   COMBA_START;
+   COMBA_CLEAR;
+
+   /* get size of output and trim */
+   pa = A->used + B->used;
+   if (pa >= FP_SIZE) {
+      pa = FP_SIZE-1;
+   }
+
+   if (A == C || B == C) {
+      fp_zero(&tmp);
+      dst = &tmp;
+   } else {
+      fp_zero(C);
+      dst = C;
+   }
+
+   for (ix = 0; ix < pa; ix++) {
+      /* get offsets into the two bignums */
+      ty = MIN(ix, B->used-1);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = A->dp + tx;
+      tmpy = B->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially its
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(A->used-tx, ty+1);
+
+      /* execute loop */
+      COMBA_FORWARD;
+      for (iz = 0; iz < iy; ++iz) {
+          MULADD(*tmpx++, *tmpy--);
+      }
+
+      /* store term */
+      COMBA_STORE(dst->dp[ix]);
+  }
+  /* store final carry */
+  COMBA_STORE2(dst->dp[ix]);
+  COMBA_FINI;
+
+  dst->used = pa;
+  fp_clamp(dst);
+  dst->sign = dst->used ? A->sign ^ B->sign : FP_ZPOS;
+  fp_copy(dst, C);
+}
+
+void fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C)
+{
+   fp_digit c0, c1, c2, at[8];
+
+   memcpy(at, A->dp, 4 * sizeof(fp_digit));
+   memcpy(at+4, B->dp, 4 * sizeof(fp_digit));
+   COMBA_START;
+
+   COMBA_CLEAR;
+   /* 0 */
+   MULADD(at[0], at[4]);
+   COMBA_STORE(C->dp[0]);
+   /* 1 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[5]);    MULADD(at[1], at[4]);
+   COMBA_STORE(C->dp[1]);
+   /* 2 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[6]);    MULADD(at[1], at[5]);    MULADD(at[2], at[4]);
+   COMBA_STORE(C->dp[2]);
+   /* 3 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[7]);    MULADD(at[1], at[6]);    MULADD(at[2], at[5]);    MULADD(at[3], at[4]);
+   COMBA_STORE(C->dp[3]);
+   /* 4 */
+   COMBA_FORWARD;
+   MULADD(at[1], at[7]);    MULADD(at[2], at[6]);    MULADD(at[3], at[5]);
+   COMBA_STORE(C->dp[4]);
+   /* 5 */
+   COMBA_FORWARD;
+   MULADD(at[2], at[7]);    MULADD(at[3], at[6]);
+   COMBA_STORE(C->dp[5]);
+   /* 6 */
+   COMBA_FORWARD;
+   MULADD(at[3], at[7]);
+   COMBA_STORE(C->dp[6]);
+   COMBA_STORE2(C->dp[7]);
+   C->used = 8;
+   C->sign = A->sign ^ B->sign;
+   fp_clamp(C);
+   COMBA_FINI;
+}
+
+
+void fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C)
+{
+   fp_digit c0, c1, c2, at[16];
+
+   memcpy(at, A->dp, 8 * sizeof(fp_digit));
+   memcpy(at+8, B->dp, 8 * sizeof(fp_digit));
+   COMBA_START;
+
+   COMBA_CLEAR;
+   /* 0 */
+   MULADD(at[0], at[8]);
+   COMBA_STORE(C->dp[0]);
+   /* 1 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[9]);    MULADD(at[1], at[8]);
+   COMBA_STORE(C->dp[1]);
+   /* 2 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[10]);    MULADD(at[1], at[9]);    MULADD(at[2], at[8]);
+   COMBA_STORE(C->dp[2]);
+   /* 3 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[11]);    MULADD(at[1], at[10]);    MULADD(at[2], at[9]);    MULADD(at[3], at[8]);
+   COMBA_STORE(C->dp[3]);
+   /* 4 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[12]);    MULADD(at[1], at[11]);    MULADD(at[2], at[10]);    MULADD(at[3], at[9]);    MULADD(at[4], at[8]);
+   COMBA_STORE(C->dp[4]);
+   /* 5 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[13]);    MULADD(at[1], at[12]);    MULADD(at[2], at[11]);    MULADD(at[3], at[10]);    MULADD(at[4], at[9]);    MULADD(at[5], at[8]);
+   COMBA_STORE(C->dp[5]);
+   /* 6 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[14]);    MULADD(at[1], at[13]);    MULADD(at[2], at[12]);    MULADD(at[3], at[11]);    MULADD(at[4], at[10]);    MULADD(at[5], at[9]);    MULADD(at[6], at[8]);
+   COMBA_STORE(C->dp[6]);
+   /* 7 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[15]);    MULADD(at[1], at[14]);    MULADD(at[2], at[13]);    MULADD(at[3], at[12]);    MULADD(at[4], at[11]);    MULADD(at[5], at[10]);    MULADD(at[6], at[9]);    MULADD(at[7], at[8]);
+   COMBA_STORE(C->dp[7]);
+   /* 8 */
+   COMBA_FORWARD;
+   MULADD(at[1], at[15]);    MULADD(at[2], at[14]);    MULADD(at[3], at[13]);    MULADD(at[4], at[12]);    MULADD(at[5], at[11]);    MULADD(at[6], at[10]);    MULADD(at[7], at[9]);
+   COMBA_STORE(C->dp[8]);
+   /* 9 */
+   COMBA_FORWARD;
+   MULADD(at[2], at[15]);    MULADD(at[3], at[14]);    MULADD(at[4], at[13]);    MULADD(at[5], at[12]);    MULADD(at[6], at[11]);    MULADD(at[7], at[10]);
+   COMBA_STORE(C->dp[9]);
+   /* 10 */
+   COMBA_FORWARD;
+   MULADD(at[3], at[15]);    MULADD(at[4], at[14]);    MULADD(at[5], at[13]);    MULADD(at[6], at[12]);    MULADD(at[7], at[11]);
+   COMBA_STORE(C->dp[10]);
+   /* 11 */
+   COMBA_FORWARD;
+   MULADD(at[4], at[15]);    MULADD(at[5], at[14]);    MULADD(at[6], at[13]);    MULADD(at[7], at[12]);
+   COMBA_STORE(C->dp[11]);
+   /* 12 */
+   COMBA_FORWARD;
+   MULADD(at[5], at[15]);    MULADD(at[6], at[14]);    MULADD(at[7], at[13]);
+   COMBA_STORE(C->dp[12]);
+   /* 13 */
+   COMBA_FORWARD;
+   MULADD(at[6], at[15]);    MULADD(at[7], at[14]);
+   COMBA_STORE(C->dp[13]);
+   /* 14 */
+   COMBA_FORWARD;
+   MULADD(at[7], at[15]);
+   COMBA_STORE(C->dp[14]);
+   COMBA_STORE2(C->dp[15]);
+   C->used = 16;
+   C->sign = A->sign ^ B->sign;
+   fp_clamp(C);
+   COMBA_FINI;
+}
+
+#if defined(TFM_LARGE)
+
+void fp_mul_comba16(fp_int *A, fp_int *B, fp_int *C)
+{
+   fp_digit c0, c1, c2, at[32];
+
+   memcpy(at, A->dp, 16 * sizeof(fp_digit));
+   memcpy(at+16, B->dp, 16 * sizeof(fp_digit));
+   COMBA_START;
+
+   COMBA_CLEAR;
+   /* 0 */
+   MULADD(at[0], at[16]);
+   COMBA_STORE(C->dp[0]);
+   /* 1 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[17]);    MULADD(at[1], at[16]);
+   COMBA_STORE(C->dp[1]);
+   /* 2 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[18]);    MULADD(at[1], at[17]);    MULADD(at[2], at[16]);
+   COMBA_STORE(C->dp[2]);
+   /* 3 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[19]);    MULADD(at[1], at[18]);    MULADD(at[2], at[17]);    MULADD(at[3], at[16]);
+   COMBA_STORE(C->dp[3]);
+   /* 4 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[20]);    MULADD(at[1], at[19]);    MULADD(at[2], at[18]);    MULADD(at[3], at[17]);    MULADD(at[4], at[16]);
+   COMBA_STORE(C->dp[4]);
+   /* 5 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[21]);    MULADD(at[1], at[20]);    MULADD(at[2], at[19]);    MULADD(at[3], at[18]);    MULADD(at[4], at[17]);    MULADD(at[5], at[16]);
+   COMBA_STORE(C->dp[5]);
+   /* 6 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[22]);    MULADD(at[1], at[21]);    MULADD(at[2], at[20]);    MULADD(at[3], at[19]);    MULADD(at[4], at[18]);    MULADD(at[5], at[17]);    MULADD(at[6], at[16]);
+   COMBA_STORE(C->dp[6]);
+   /* 7 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[23]);    MULADD(at[1], at[22]);    MULADD(at[2], at[21]);    MULADD(at[3], at[20]);    MULADD(at[4], at[19]);    MULADD(at[5], at[18]);    MULADD(at[6], at[17]);    MULADD(at[7], at[16]);
+   COMBA_STORE(C->dp[7]);
+   /* 8 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[24]);    MULADD(at[1], at[23]);    MULADD(at[2], at[22]);    MULADD(at[3], at[21]);    MULADD(at[4], at[20]);    MULADD(at[5], at[19]);    MULADD(at[6], at[18]);    MULADD(at[7], at[17]);    MULADD(at[8], at[16]);
+   COMBA_STORE(C->dp[8]);
+   /* 9 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[25]);    MULADD(at[1], at[24]);    MULADD(at[2], at[23]);    MULADD(at[3], at[22]);    MULADD(at[4], at[21]);    MULADD(at[5], at[20]);    MULADD(at[6], at[19]);    MULADD(at[7], at[18]);    MULADD(at[8], at[17]);    MULADD(at[9], at[16]);
+   COMBA_STORE(C->dp[9]);
+   /* 10 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[26]);    MULADD(at[1], at[25]);    MULADD(at[2], at[24]);    MULADD(at[3], at[23]);    MULADD(at[4], at[22]);    MULADD(at[5], at[21]);    MULADD(at[6], at[20]);    MULADD(at[7], at[19]);    MULADD(at[8], at[18]);    MULADD(at[9], at[17]);    MULADD(at[10], at[16]);
+   COMBA_STORE(C->dp[10]);
+   /* 11 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[27]);    MULADD(at[1], at[26]);    MULADD(at[2], at[25]);    MULADD(at[3], at[24]);    MULADD(at[4], at[23]);    MULADD(at[5], at[22]);    MULADD(at[6], at[21]);    MULADD(at[7], at[20]);    MULADD(at[8], at[19]);    MULADD(at[9], at[18]);    MULADD(at[10], at[17]);    MULADD(at[11], at[16]);
+   COMBA_STORE(C->dp[11]);
+   /* 12 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[28]);    MULADD(at[1], at[27]);    MULADD(at[2], at[26]);    MULADD(at[3], at[25]);    MULADD(at[4], at[24]);    MULADD(at[5], at[23]);    MULADD(at[6], at[22]);    MULADD(at[7], at[21]);    MULADD(at[8], at[20]);    MULADD(at[9], at[19]);    MULADD(at[10], at[18]);    MULADD(at[11], at[17]);    MULADD(at[12], at[16]);
+   COMBA_STORE(C->dp[12]);
+   /* 13 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[29]);    MULADD(at[1], at[28]);    MULADD(at[2], at[27]);    MULADD(at[3], at[26]);    MULADD(at[4], at[25]);    MULADD(at[5], at[24]);    MULADD(at[6], at[23]);    MULADD(at[7], at[22]);    MULADD(at[8], at[21]);    MULADD(at[9], at[20]);    MULADD(at[10], at[19]);    MULADD(at[11], at[18]);    MULADD(at[12], at[17]);    MULADD(at[13], at[16]);
+   COMBA_STORE(C->dp[13]);
+   /* 14 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[30]);    MULADD(at[1], at[29]);    MULADD(at[2], at[28]);    MULADD(at[3], at[27]);    MULADD(at[4], at[26]);    MULADD(at[5], at[25]);    MULADD(at[6], at[24]);    MULADD(at[7], at[23]);    MULADD(at[8], at[22]);    MULADD(at[9], at[21]);    MULADD(at[10], at[20]);    MULADD(at[11], at[19]);    MULADD(at[12], at[18]);    MULADD(at[13], at[17]);    MULADD(at[14], at[16]);
+   COMBA_STORE(C->dp[14]);
+   /* 15 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[31]);    MULADD(at[1], at[30]);    MULADD(at[2], at[29]);    MULADD(at[3], at[28]);    MULADD(at[4], at[27]);    MULADD(at[5], at[26]);    MULADD(at[6], at[25]);    MULADD(at[7], at[24]);    MULADD(at[8], at[23]);    MULADD(at[9], at[22]);    MULADD(at[10], at[21]);    MULADD(at[11], at[20]);    MULADD(at[12], at[19]);    MULADD(at[13], at[18]);    MULADD(at[14], at[17]);    MULADD(at[15], at[16]);
+   COMBA_STORE(C->dp[15]);
+   /* 16 */
+   COMBA_FORWARD;
+   MULADD(at[1], at[31]);    MULADD(at[2], at[30]);    MULADD(at[3], at[29]);    MULADD(at[4], at[28]);    MULADD(at[5], at[27]);    MULADD(at[6], at[26]);    MULADD(at[7], at[25]);    MULADD(at[8], at[24]);    MULADD(at[9], at[23]);    MULADD(at[10], at[22]);    MULADD(at[11], at[21]);    MULADD(at[12], at[20]);    MULADD(at[13], at[19]);    MULADD(at[14], at[18]);    MULADD(at[15], at[17]);
+   COMBA_STORE(C->dp[16]);
+   /* 17 */
+   COMBA_FORWARD;
+   MULADD(at[2], at[31]);    MULADD(at[3], at[30]);    MULADD(at[4], at[29]);    MULADD(at[5], at[28]);    MULADD(at[6], at[27]);    MULADD(at[7], at[26]);    MULADD(at[8], at[25]);    MULADD(at[9], at[24]);    MULADD(at[10], at[23]);    MULADD(at[11], at[22]);    MULADD(at[12], at[21]);    MULADD(at[13], at[20]);    MULADD(at[14], at[19]);    MULADD(at[15], at[18]);
+   COMBA_STORE(C->dp[17]);
+   /* 18 */
+   COMBA_FORWARD;
+   MULADD(at[3], at[31]);    MULADD(at[4], at[30]);    MULADD(at[5], at[29]);    MULADD(at[6], at[28]);    MULADD(at[7], at[27]);    MULADD(at[8], at[26]);    MULADD(at[9], at[25]);    MULADD(at[10], at[24]);    MULADD(at[11], at[23]);    MULADD(at[12], at[22]);    MULADD(at[13], at[21]);    MULADD(at[14], at[20]);    MULADD(at[15], at[19]);
+   COMBA_STORE(C->dp[18]);
+   /* 19 */
+   COMBA_FORWARD;
+   MULADD(at[4], at[31]);    MULADD(at[5], at[30]);    MULADD(at[6], at[29]);    MULADD(at[7], at[28]);    MULADD(at[8], at[27]);    MULADD(at[9], at[26]);    MULADD(at[10], at[25]);    MULADD(at[11], at[24]);    MULADD(at[12], at[23]);    MULADD(at[13], at[22]);    MULADD(at[14], at[21]);    MULADD(at[15], at[20]);
+   COMBA_STORE(C->dp[19]);
+   /* 20 */
+   COMBA_FORWARD;
+   MULADD(at[5], at[31]);    MULADD(at[6], at[30]);    MULADD(at[7], at[29]);    MULADD(at[8], at[28]);    MULADD(at[9], at[27]);    MULADD(at[10], at[26]);    MULADD(at[11], at[25]);    MULADD(at[12], at[24]);    MULADD(at[13], at[23]);    MULADD(at[14], at[22]);    MULADD(at[15], at[21]);
+   COMBA_STORE(C->dp[20]);
+   /* 21 */
+   COMBA_FORWARD;
+   MULADD(at[6], at[31]);    MULADD(at[7], at[30]);    MULADD(at[8], at[29]);    MULADD(at[9], at[28]);    MULADD(at[10], at[27]);    MULADD(at[11], at[26]);    MULADD(at[12], at[25]);    MULADD(at[13], at[24]);    MULADD(at[14], at[23]);    MULADD(at[15], at[22]);
+   COMBA_STORE(C->dp[21]);
+   /* 22 */
+   COMBA_FORWARD;
+   MULADD(at[7], at[31]);    MULADD(at[8], at[30]);    MULADD(at[9], at[29]);    MULADD(at[10], at[28]);    MULADD(at[11], at[27]);    MULADD(at[12], at[26]);    MULADD(at[13], at[25]);    MULADD(at[14], at[24]);    MULADD(at[15], at[23]);
+   COMBA_STORE(C->dp[22]);
+   /* 23 */
+   COMBA_FORWARD;
+   MULADD(at[8], at[31]);    MULADD(at[9], at[30]);    MULADD(at[10], at[29]);    MULADD(at[11], at[28]);    MULADD(at[12], at[27]);    MULADD(at[13], at[26]);    MULADD(at[14], at[25]);    MULADD(at[15], at[24]);
+   COMBA_STORE(C->dp[23]);
+   /* 24 */
+   COMBA_FORWARD;
+   MULADD(at[9], at[31]);    MULADD(at[10], at[30]);    MULADD(at[11], at[29]);    MULADD(at[12], at[28]);    MULADD(at[13], at[27]);    MULADD(at[14], at[26]);    MULADD(at[15], at[25]);
+   COMBA_STORE(C->dp[24]);
+   /* 25 */
+   COMBA_FORWARD;
+   MULADD(at[10], at[31]);    MULADD(at[11], at[30]);    MULADD(at[12], at[29]);    MULADD(at[13], at[28]);    MULADD(at[14], at[27]);    MULADD(at[15], at[26]);
+   COMBA_STORE(C->dp[25]);
+   /* 26 */
+   COMBA_FORWARD;
+   MULADD(at[11], at[31]);    MULADD(at[12], at[30]);    MULADD(at[13], at[29]);    MULADD(at[14], at[28]);    MULADD(at[15], at[27]);
+   COMBA_STORE(C->dp[26]);
+   /* 27 */
+   COMBA_FORWARD;
+   MULADD(at[12], at[31]);    MULADD(at[13], at[30]);    MULADD(at[14], at[29]);    MULADD(at[15], at[28]);
+   COMBA_STORE(C->dp[27]);
+   /* 28 */
+   COMBA_FORWARD;
+   MULADD(at[13], at[31]);    MULADD(at[14], at[30]);    MULADD(at[15], at[29]);
+   COMBA_STORE(C->dp[28]);
+   /* 29 */
+   COMBA_FORWARD;
+   MULADD(at[14], at[31]);    MULADD(at[15], at[30]);
+   COMBA_STORE(C->dp[29]);
+   /* 30 */
+   COMBA_FORWARD;
+   MULADD(at[15], at[31]);
+   COMBA_STORE(C->dp[30]);
+   COMBA_STORE2(C->dp[31]);
+   C->used = 32;
+   C->sign = A->sign ^ B->sign;
+   fp_clamp(C);
+   COMBA_FINI;
+}
+
+#endif /* TFM_LARGE */
+
+#ifdef TFM_HUGE
+
+void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C)
+{
+   fp_digit c0, c1, c2, at[64];
+
+   memcpy(at, A->dp, 32 * sizeof(fp_digit));
+   memcpy(at+32, B->dp, 32 * sizeof(fp_digit));
+   COMBA_START;
+
+   COMBA_CLEAR;
+   /* 0 */
+   MULADD(at[0], at[32]);
+   COMBA_STORE(C->dp[0]);
+   /* 1 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[33]);    MULADD(at[1], at[32]);
+   COMBA_STORE(C->dp[1]);
+   /* 2 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[34]);    MULADD(at[1], at[33]);    MULADD(at[2], at[32]);
+   COMBA_STORE(C->dp[2]);
+   /* 3 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[35]);    MULADD(at[1], at[34]);    MULADD(at[2], at[33]);    MULADD(at[3], at[32]);
+   COMBA_STORE(C->dp[3]);
+   /* 4 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[36]);    MULADD(at[1], at[35]);    MULADD(at[2], at[34]);    MULADD(at[3], at[33]);    MULADD(at[4], at[32]);
+   COMBA_STORE(C->dp[4]);
+   /* 5 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[37]);    MULADD(at[1], at[36]);    MULADD(at[2], at[35]);    MULADD(at[3], at[34]);    MULADD(at[4], at[33]);    MULADD(at[5], at[32]);
+   COMBA_STORE(C->dp[5]);
+   /* 6 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[38]);    MULADD(at[1], at[37]);    MULADD(at[2], at[36]);    MULADD(at[3], at[35]);    MULADD(at[4], at[34]);    MULADD(at[5], at[33]);    MULADD(at[6], at[32]);
+   COMBA_STORE(C->dp[6]);
+   /* 7 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[39]);    MULADD(at[1], at[38]);    MULADD(at[2], at[37]);    MULADD(at[3], at[36]);    MULADD(at[4], at[35]);    MULADD(at[5], at[34]);    MULADD(at[6], at[33]);    MULADD(at[7], at[32]);
+   COMBA_STORE(C->dp[7]);
+   /* 8 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[40]);    MULADD(at[1], at[39]);    MULADD(at[2], at[38]);    MULADD(at[3], at[37]);    MULADD(at[4], at[36]);    MULADD(at[5], at[35]);    MULADD(at[6], at[34]);    MULADD(at[7], at[33]);    MULADD(at[8], at[32]);
+   COMBA_STORE(C->dp[8]);
+   /* 9 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[41]);    MULADD(at[1], at[40]);    MULADD(at[2], at[39]);    MULADD(at[3], at[38]);    MULADD(at[4], at[37]);    MULADD(at[5], at[36]);    MULADD(at[6], at[35]);    MULADD(at[7], at[34]);    MULADD(at[8], at[33]);    MULADD(at[9], at[32]);
+   COMBA_STORE(C->dp[9]);
+   /* 10 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[42]);    MULADD(at[1], at[41]);    MULADD(at[2], at[40]);    MULADD(at[3], at[39]);    MULADD(at[4], at[38]);    MULADD(at[5], at[37]);    MULADD(at[6], at[36]);    MULADD(at[7], at[35]);    MULADD(at[8], at[34]);    MULADD(at[9], at[33]);    MULADD(at[10], at[32]);
+   COMBA_STORE(C->dp[10]);
+   /* 11 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[43]);    MULADD(at[1], at[42]);    MULADD(at[2], at[41]);    MULADD(at[3], at[40]);    MULADD(at[4], at[39]);    MULADD(at[5], at[38]);    MULADD(at[6], at[37]);    MULADD(at[7], at[36]);    MULADD(at[8], at[35]);    MULADD(at[9], at[34]);    MULADD(at[10], at[33]);    MULADD(at[11], at[32]);
+   COMBA_STORE(C->dp[11]);
+   /* 12 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[44]);    MULADD(at[1], at[43]);    MULADD(at[2], at[42]);    MULADD(at[3], at[41]);    MULADD(at[4], at[40]);    MULADD(at[5], at[39]);    MULADD(at[6], at[38]);    MULADD(at[7], at[37]);    MULADD(at[8], at[36]);    MULADD(at[9], at[35]);    MULADD(at[10], at[34]);    MULADD(at[11], at[33]);    MULADD(at[12], at[32]);
+   COMBA_STORE(C->dp[12]);
+   /* 13 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[45]);    MULADD(at[1], at[44]);    MULADD(at[2], at[43]);    MULADD(at[3], at[42]);    MULADD(at[4], at[41]);    MULADD(at[5], at[40]);    MULADD(at[6], at[39]);    MULADD(at[7], at[38]);    MULADD(at[8], at[37]);    MULADD(at[9], at[36]);    MULADD(at[10], at[35]);    MULADD(at[11], at[34]);    MULADD(at[12], at[33]);    MULADD(at[13], at[32]);
+   COMBA_STORE(C->dp[13]);
+   /* 14 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[46]);    MULADD(at[1], at[45]);    MULADD(at[2], at[44]);    MULADD(at[3], at[43]);    MULADD(at[4], at[42]);    MULADD(at[5], at[41]);    MULADD(at[6], at[40]);    MULADD(at[7], at[39]);    MULADD(at[8], at[38]);    MULADD(at[9], at[37]);    MULADD(at[10], at[36]);    MULADD(at[11], at[35]);    MULADD(at[12], at[34]);    MULADD(at[13], at[33]);    MULADD(at[14], at[32]);
+   COMBA_STORE(C->dp[14]);
+   /* 15 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[47]);    MULADD(at[1], at[46]);    MULADD(at[2], at[45]);    MULADD(at[3], at[44]);    MULADD(at[4], at[43]);    MULADD(at[5], at[42]);    MULADD(at[6], at[41]);    MULADD(at[7], at[40]);    MULADD(at[8], at[39]);    MULADD(at[9], at[38]);    MULADD(at[10], at[37]);    MULADD(at[11], at[36]);    MULADD(at[12], at[35]);    MULADD(at[13], at[34]);    MULADD(at[14], at[33]);    MULADD(at[15], at[32]);
+   COMBA_STORE(C->dp[15]);
+   /* 16 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[48]);    MULADD(at[1], at[47]);    MULADD(at[2], at[46]);    MULADD(at[3], at[45]);    MULADD(at[4], at[44]);    MULADD(at[5], at[43]);    MULADD(at[6], at[42]);    MULADD(at[7], at[41]);    MULADD(at[8], at[40]);    MULADD(at[9], at[39]);    MULADD(at[10], at[38]);    MULADD(at[11], at[37]);    MULADD(at[12], at[36]);    MULADD(at[13], at[35]);    MULADD(at[14], at[34]);    MULADD(at[15], at[33]);    MULADD(at[16], at[32]);
+   COMBA_STORE(C->dp[16]);
+   /* 17 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[49]);    MULADD(at[1], at[48]);    MULADD(at[2], at[47]);    MULADD(at[3], at[46]);    MULADD(at[4], at[45]);    MULADD(at[5], at[44]);    MULADD(at[6], at[43]);    MULADD(at[7], at[42]);    MULADD(at[8], at[41]);    MULADD(at[9], at[40]);    MULADD(at[10], at[39]);    MULADD(at[11], at[38]);    MULADD(at[12], at[37]);    MULADD(at[13], at[36]);    MULADD(at[14], at[35]);    MULADD(at[15], at[34]);    MULADD(at[16], at[33]);    MULADD(at[17], at[32]);
+   COMBA_STORE(C->dp[17]);
+   /* 18 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[50]);    MULADD(at[1], at[49]);    MULADD(at[2], at[48]);    MULADD(at[3], at[47]);    MULADD(at[4], at[46]);    MULADD(at[5], at[45]);    MULADD(at[6], at[44]);    MULADD(at[7], at[43]);    MULADD(at[8], at[42]);    MULADD(at[9], at[41]);    MULADD(at[10], at[40]);    MULADD(at[11], at[39]);    MULADD(at[12], at[38]);    MULADD(at[13], at[37]);    MULADD(at[14], at[36]);    MULADD(at[15], at[35]);    MULADD(at[16], at[34]);    MULADD(at[17], at[33]);    MULADD(at[18], at[32]);
+   COMBA_STORE(C->dp[18]);
+   /* 19 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[51]);    MULADD(at[1], at[50]);    MULADD(at[2], at[49]);    MULADD(at[3], at[48]);    MULADD(at[4], at[47]);    MULADD(at[5], at[46]);    MULADD(at[6], at[45]);    MULADD(at[7], at[44]);    MULADD(at[8], at[43]);    MULADD(at[9], at[42]);    MULADD(at[10], at[41]);    MULADD(at[11], at[40]);    MULADD(at[12], at[39]);    MULADD(at[13], at[38]);    MULADD(at[14], at[37]);    MULADD(at[15], at[36]);    MULADD(at[16], at[35]);    MULADD(at[17], at[34]);    MULADD(at[18], at[33]);    MULADD(at[19], at[32]);
+   COMBA_STORE(C->dp[19]);
+   /* 20 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[52]);    MULADD(at[1], at[51]);    MULADD(at[2], at[50]);    MULADD(at[3], at[49]);    MULADD(at[4], at[48]);    MULADD(at[5], at[47]);    MULADD(at[6], at[46]);    MULADD(at[7], at[45]);    MULADD(at[8], at[44]);    MULADD(at[9], at[43]);    MULADD(at[10], at[42]);    MULADD(at[11], at[41]);    MULADD(at[12], at[40]);    MULADD(at[13], at[39]);    MULADD(at[14], at[38]);    MULADD(at[15], at[37]);    MULADD(at[16], at[36]);    MULADD(at[17], at[35]);    MULADD(at[18], at[34]);    MULADD(at[19], at[33]);    MULADD(at[20], at[32]);
+   COMBA_STORE(C->dp[20]);
+   /* 21 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[53]);    MULADD(at[1], at[52]);    MULADD(at[2], at[51]);    MULADD(at[3], at[50]);    MULADD(at[4], at[49]);    MULADD(at[5], at[48]);    MULADD(at[6], at[47]);    MULADD(at[7], at[46]);    MULADD(at[8], at[45]);    MULADD(at[9], at[44]);    MULADD(at[10], at[43]);    MULADD(at[11], at[42]);    MULADD(at[12], at[41]);    MULADD(at[13], at[40]);    MULADD(at[14], at[39]);    MULADD(at[15], at[38]);    MULADD(at[16], at[37]);    MULADD(at[17], at[36]);    MULADD(at[18], at[35]);    MULADD(at[19], at[34]);    MULADD(at[20], at[33]);    MULADD(at[21], at[32]);
+   COMBA_STORE(C->dp[21]);
+   /* 22 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[54]);    MULADD(at[1], at[53]);    MULADD(at[2], at[52]);    MULADD(at[3], at[51]);    MULADD(at[4], at[50]);    MULADD(at[5], at[49]);    MULADD(at[6], at[48]);    MULADD(at[7], at[47]);    MULADD(at[8], at[46]);    MULADD(at[9], at[45]);    MULADD(at[10], at[44]);    MULADD(at[11], at[43]);    MULADD(at[12], at[42]);    MULADD(at[13], at[41]);    MULADD(at[14], at[40]);    MULADD(at[15], at[39]);    MULADD(at[16], at[38]);    MULADD(at[17], at[37]);    MULADD(at[18], at[36]);    MULADD(at[19], at[35]);    MULADD(at[20], at[34]);    MULADD(at[21], at[33]);    MULADD(at[22], at[32]);
+   COMBA_STORE(C->dp[22]);
+   /* 23 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[55]);    MULADD(at[1], at[54]);    MULADD(at[2], at[53]);    MULADD(at[3], at[52]);    MULADD(at[4], at[51]);    MULADD(at[5], at[50]);    MULADD(at[6], at[49]);    MULADD(at[7], at[48]);    MULADD(at[8], at[47]);    MULADD(at[9], at[46]);    MULADD(at[10], at[45]);    MULADD(at[11], at[44]);    MULADD(at[12], at[43]);    MULADD(at[13], at[42]);    MULADD(at[14], at[41]);    MULADD(at[15], at[40]);    MULADD(at[16], at[39]);    MULADD(at[17], at[38]);    MULADD(at[18], at[37]);    MULADD(at[19], at[36]);    MULADD(at[20], at[35]);    MULADD(at[21], at[34]);    MULADD(at[22], at[33]);    MULADD(at[23], at[32]);
+   COMBA_STORE(C->dp[23]);
+   /* 24 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[56]);    MULADD(at[1], at[55]);    MULADD(at[2], at[54]);    MULADD(at[3], at[53]);    MULADD(at[4], at[52]);    MULADD(at[5], at[51]);    MULADD(at[6], at[50]);    MULADD(at[7], at[49]);    MULADD(at[8], at[48]);    MULADD(at[9], at[47]);    MULADD(at[10], at[46]);    MULADD(at[11], at[45]);    MULADD(at[12], at[44]);    MULADD(at[13], at[43]);    MULADD(at[14], at[42]);    MULADD(at[15], at[41]);    MULADD(at[16], at[40]);    MULADD(at[17], at[39]);    MULADD(at[18], at[38]);    MULADD(at[19], at[37]);    MULADD(at[20], at[36]);    MULADD(at[21], at[35]);    MULADD(at[22], at[34]);    MULADD(at[23], at[33]);    MULADD(at[24], at[32]);
+   COMBA_STORE(C->dp[24]);
+   /* 25 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[57]);    MULADD(at[1], at[56]);    MULADD(at[2], at[55]);    MULADD(at[3], at[54]);    MULADD(at[4], at[53]);    MULADD(at[5], at[52]);    MULADD(at[6], at[51]);    MULADD(at[7], at[50]);    MULADD(at[8], at[49]);    MULADD(at[9], at[48]);    MULADD(at[10], at[47]);    MULADD(at[11], at[46]);    MULADD(at[12], at[45]);    MULADD(at[13], at[44]);    MULADD(at[14], at[43]);    MULADD(at[15], at[42]);    MULADD(at[16], at[41]);    MULADD(at[17], at[40]);    MULADD(at[18], at[39]);    MULADD(at[19], at[38]);    MULADD(at[20], at[37]);    MULADD(at[21], at[36]);    MULADD(at[22], at[35]);    MULADD(at[23], at[34]);    MULADD(at[24], at[33]);    MULADD(at[25], at[32]);
+   COMBA_STORE(C->dp[25]);
+   /* 26 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[58]);    MULADD(at[1], at[57]);    MULADD(at[2], at[56]);    MULADD(at[3], at[55]);    MULADD(at[4], at[54]);    MULADD(at[5], at[53]);    MULADD(at[6], at[52]);    MULADD(at[7], at[51]);    MULADD(at[8], at[50]);    MULADD(at[9], at[49]);    MULADD(at[10], at[48]);    MULADD(at[11], at[47]);    MULADD(at[12], at[46]);    MULADD(at[13], at[45]);    MULADD(at[14], at[44]);    MULADD(at[15], at[43]);    MULADD(at[16], at[42]);    MULADD(at[17], at[41]);    MULADD(at[18], at[40]);    MULADD(at[19], at[39]);    MULADD(at[20], at[38]);    MULADD(at[21], at[37]);    MULADD(at[22], at[36]);    MULADD(at[23], at[35]);    MULADD(at[24], at[34]);    MULADD(at[25], at[33]);    MULADD(at[26], at[32]);
+   COMBA_STORE(C->dp[26]);
+   /* 27 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[59]);    MULADD(at[1], at[58]);    MULADD(at[2], at[57]);    MULADD(at[3], at[56]);    MULADD(at[4], at[55]);    MULADD(at[5], at[54]);    MULADD(at[6], at[53]);    MULADD(at[7], at[52]);    MULADD(at[8], at[51]);    MULADD(at[9], at[50]);    MULADD(at[10], at[49]);    MULADD(at[11], at[48]);    MULADD(at[12], at[47]);    MULADD(at[13], at[46]);    MULADD(at[14], at[45]);    MULADD(at[15], at[44]);    MULADD(at[16], at[43]);    MULADD(at[17], at[42]);    MULADD(at[18], at[41]);    MULADD(at[19], at[40]);    MULADD(at[20], at[39]);    MULADD(at[21], at[38]);    MULADD(at[22], at[37]);    MULADD(at[23], at[36]);    MULADD(at[24], at[35]);    MULADD(at[25], at[34]);    MULADD(at[26], at[33]);    MULADD(at[27], at[32]);
+   COMBA_STORE(C->dp[27]);
+   /* 28 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[60]);    MULADD(at[1], at[59]);    MULADD(at[2], at[58]);    MULADD(at[3], at[57]);    MULADD(at[4], at[56]);    MULADD(at[5], at[55]);    MULADD(at[6], at[54]);    MULADD(at[7], at[53]);    MULADD(at[8], at[52]);    MULADD(at[9], at[51]);    MULADD(at[10], at[50]);    MULADD(at[11], at[49]);    MULADD(at[12], at[48]);    MULADD(at[13], at[47]);    MULADD(at[14], at[46]);    MULADD(at[15], at[45]);    MULADD(at[16], at[44]);    MULADD(at[17], at[43]);    MULADD(at[18], at[42]);    MULADD(at[19], at[41]);    MULADD(at[20], at[40]);    MULADD(at[21], at[39]);    MULADD(at[22], at[38]);    MULADD(at[23], at[37]);    MULADD(at[24], at[36]);    MULADD(at[25], at[35]);    MULADD(at[26], at[34]);    MULADD(at[27], at[33]);    MULADD(at[28], at[32]);
+   COMBA_STORE(C->dp[28]);
+   /* 29 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[61]);    MULADD(at[1], at[60]);    MULADD(at[2], at[59]);    MULADD(at[3], at[58]);    MULADD(at[4], at[57]);    MULADD(at[5], at[56]);    MULADD(at[6], at[55]);    MULADD(at[7], at[54]);    MULADD(at[8], at[53]);    MULADD(at[9], at[52]);    MULADD(at[10], at[51]);    MULADD(at[11], at[50]);    MULADD(at[12], at[49]);    MULADD(at[13], at[48]);    MULADD(at[14], at[47]);    MULADD(at[15], at[46]);    MULADD(at[16], at[45]);    MULADD(at[17], at[44]);    MULADD(at[18], at[43]);    MULADD(at[19], at[42]);    MULADD(at[20], at[41]);    MULADD(at[21], at[40]);    MULADD(at[22], at[39]);    MULADD(at[23], at[38]);    MULADD(at[24], at[37]);    MULADD(at[25], at[36]);    MULADD(at[26], at[35]);    MULADD(at[27], at[34]);    MULADD(at[28], at[33]);    MULADD(at[29], at[32]);
+   COMBA_STORE(C->dp[29]);
+   /* 30 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[62]);    MULADD(at[1], at[61]);    MULADD(at[2], at[60]);    MULADD(at[3], at[59]);    MULADD(at[4], at[58]);    MULADD(at[5], at[57]);    MULADD(at[6], at[56]);    MULADD(at[7], at[55]);    MULADD(at[8], at[54]);    MULADD(at[9], at[53]);    MULADD(at[10], at[52]);    MULADD(at[11], at[51]);    MULADD(at[12], at[50]);    MULADD(at[13], at[49]);    MULADD(at[14], at[48]);    MULADD(at[15], at[47]);    MULADD(at[16], at[46]);    MULADD(at[17], at[45]);    MULADD(at[18], at[44]);    MULADD(at[19], at[43]);    MULADD(at[20], at[42]);    MULADD(at[21], at[41]);    MULADD(at[22], at[40]);    MULADD(at[23], at[39]);    MULADD(at[24], at[38]);    MULADD(at[25], at[37]);    MULADD(at[26], at[36]);    MULADD(at[27], at[35]);    MULADD(at[28], at[34]);    MULADD(at[29], at[33]);    MULADD(at[30], at[32]);
+   COMBA_STORE(C->dp[30]);
+   /* 31 */
+   COMBA_FORWARD;
+   MULADD(at[0], at[63]);    MULADD(at[1], at[62]);    MULADD(at[2], at[61]);    MULADD(at[3], at[60]);    MULADD(at[4], at[59]);    MULADD(at[5], at[58]);    MULADD(at[6], at[57]);    MULADD(at[7], at[56]);    MULADD(at[8], at[55]);    MULADD(at[9], at[54]);    MULADD(at[10], at[53]);    MULADD(at[11], at[52]);    MULADD(at[12], at[51]);    MULADD(at[13], at[50]);    MULADD(at[14], at[49]);    MULADD(at[15], at[48]);    MULADD(at[16], at[47]);    MULADD(at[17], at[46]);    MULADD(at[18], at[45]);    MULADD(at[19], at[44]);    MULADD(at[20], at[43]);    MULADD(at[21], at[42]);    MULADD(at[22], at[41]);    MULADD(at[23], at[40]);    MULADD(at[24], at[39]);    MULADD(at[25], at[38]);    MULADD(at[26], at[37]);    MULADD(at[27], at[36]);    MULADD(at[28], at[35]);    MULADD(at[29], at[34]);    MULADD(at[30], at[33]);    MULADD(at[31], at[32]);
+   COMBA_STORE(C->dp[31]);
+   /* 32 */
+   COMBA_FORWARD;
+   MULADD(at[1], at[63]);    MULADD(at[2], at[62]);    MULADD(at[3], at[61]);    MULADD(at[4], at[60]);    MULADD(at[5], at[59]);    MULADD(at[6], at[58]);    MULADD(at[7], at[57]);    MULADD(at[8], at[56]);    MULADD(at[9], at[55]);    MULADD(at[10], at[54]);    MULADD(at[11], at[53]);    MULADD(at[12], at[52]);    MULADD(at[13], at[51]);    MULADD(at[14], at[50]);    MULADD(at[15], at[49]);    MULADD(at[16], at[48]);    MULADD(at[17], at[47]);    MULADD(at[18], at[46]);    MULADD(at[19], at[45]);    MULADD(at[20], at[44]);    MULADD(at[21], at[43]);    MULADD(at[22], at[42]);    MULADD(at[23], at[41]);    MULADD(at[24], at[40]);    MULADD(at[25], at[39]);    MULADD(at[26], at[38]);    MULADD(at[27], at[37]);    MULADD(at[28], at[36]);    MULADD(at[29], at[35]);    MULADD(at[30], at[34]);    MULADD(at[31], at[33]);
+   COMBA_STORE(C->dp[32]);
+   /* 33 */
+   COMBA_FORWARD;
+   MULADD(at[2], at[63]);    MULADD(at[3], at[62]);    MULADD(at[4], at[61]);    MULADD(at[5], at[60]);    MULADD(at[6], at[59]);    MULADD(at[7], at[58]);    MULADD(at[8], at[57]);    MULADD(at[9], at[56]);    MULADD(at[10], at[55]);    MULADD(at[11], at[54]);    MULADD(at[12], at[53]);    MULADD(at[13], at[52]);    MULADD(at[14], at[51]);    MULADD(at[15], at[50]);    MULADD(at[16], at[49]);    MULADD(at[17], at[48]);    MULADD(at[18], at[47]);    MULADD(at[19], at[46]);    MULADD(at[20], at[45]);    MULADD(at[21], at[44]);    MULADD(at[22], at[43]);    MULADD(at[23], at[42]);    MULADD(at[24], at[41]);    MULADD(at[25], at[40]);    MULADD(at[26], at[39]);    MULADD(at[27], at[38]);    MULADD(at[28], at[37]);    MULADD(at[29], at[36]);    MULADD(at[30], at[35]);    MULADD(at[31], at[34]);
+   COMBA_STORE(C->dp[33]);
+   /* 34 */
+   COMBA_FORWARD;
+   MULADD(at[3], at[63]);    MULADD(at[4], at[62]);    MULADD(at[5], at[61]);    MULADD(at[6], at[60]);    MULADD(at[7], at[59]);    MULADD(at[8], at[58]);    MULADD(at[9], at[57]);    MULADD(at[10], at[56]);    MULADD(at[11], at[55]);    MULADD(at[12], at[54]);    MULADD(at[13], at[53]);    MULADD(at[14], at[52]);    MULADD(at[15], at[51]);    MULADD(at[16], at[50]);    MULADD(at[17], at[49]);    MULADD(at[18], at[48]);    MULADD(at[19], at[47]);    MULADD(at[20], at[46]);    MULADD(at[21], at[45]);    MULADD(at[22], at[44]);    MULADD(at[23], at[43]);    MULADD(at[24], at[42]);    MULADD(at[25], at[41]);    MULADD(at[26], at[40]);    MULADD(at[27], at[39]);    MULADD(at[28], at[38]);    MULADD(at[29], at[37]);    MULADD(at[30], at[36]);    MULADD(at[31], at[35]);
+   COMBA_STORE(C->dp[34]);
+   /* 35 */
+   COMBA_FORWARD;
+   MULADD(at[4], at[63]);    MULADD(at[5], at[62]);    MULADD(at[6], at[61]);    MULADD(at[7], at[60]);    MULADD(at[8], at[59]);    MULADD(at[9], at[58]);    MULADD(at[10], at[57]);    MULADD(at[11], at[56]);    MULADD(at[12], at[55]);    MULADD(at[13], at[54]);    MULADD(at[14], at[53]);    MULADD(at[15], at[52]);    MULADD(at[16], at[51]);    MULADD(at[17], at[50]);    MULADD(at[18], at[49]);    MULADD(at[19], at[48]);    MULADD(at[20], at[47]);    MULADD(at[21], at[46]);    MULADD(at[22], at[45]);    MULADD(at[23], at[44]);    MULADD(at[24], at[43]);    MULADD(at[25], at[42]);    MULADD(at[26], at[41]);    MULADD(at[27], at[40]);    MULADD(at[28], at[39]);    MULADD(at[29], at[38]);    MULADD(at[30], at[37]);    MULADD(at[31], at[36]);
+   COMBA_STORE(C->dp[35]);
+   /* 36 */
+   COMBA_FORWARD;
+   MULADD(at[5], at[63]);    MULADD(at[6], at[62]);    MULADD(at[7], at[61]);    MULADD(at[8], at[60]);    MULADD(at[9], at[59]);    MULADD(at[10], at[58]);    MULADD(at[11], at[57]);    MULADD(at[12], at[56]);    MULADD(at[13], at[55]);    MULADD(at[14], at[54]);    MULADD(at[15], at[53]);    MULADD(at[16], at[52]);    MULADD(at[17], at[51]);    MULADD(at[18], at[50]);    MULADD(at[19], at[49]);    MULADD(at[20], at[48]);    MULADD(at[21], at[47]);    MULADD(at[22], at[46]);    MULADD(at[23], at[45]);    MULADD(at[24], at[44]);    MULADD(at[25], at[43]);    MULADD(at[26], at[42]);    MULADD(at[27], at[41]);    MULADD(at[28], at[40]);    MULADD(at[29], at[39]);    MULADD(at[30], at[38]);    MULADD(at[31], at[37]);
+   COMBA_STORE(C->dp[36]);
+   /* 37 */
+   COMBA_FORWARD;
+   MULADD(at[6], at[63]);    MULADD(at[7], at[62]);    MULADD(at[8], at[61]);    MULADD(at[9], at[60]);    MULADD(at[10], at[59]);    MULADD(at[11], at[58]);    MULADD(at[12], at[57]);    MULADD(at[13], at[56]);    MULADD(at[14], at[55]);    MULADD(at[15], at[54]);    MULADD(at[16], at[53]);    MULADD(at[17], at[52]);    MULADD(at[18], at[51]);    MULADD(at[19], at[50]);    MULADD(at[20], at[49]);    MULADD(at[21], at[48]);    MULADD(at[22], at[47]);    MULADD(at[23], at[46]);    MULADD(at[24], at[45]);    MULADD(at[25], at[44]);    MULADD(at[26], at[43]);    MULADD(at[27], at[42]);    MULADD(at[28], at[41]);    MULADD(at[29], at[40]);    MULADD(at[30], at[39]);    MULADD(at[31], at[38]);
+   COMBA_STORE(C->dp[37]);
+   /* 38 */
+   COMBA_FORWARD;
+   MULADD(at[7], at[63]);    MULADD(at[8], at[62]);    MULADD(at[9], at[61]);    MULADD(at[10], at[60]);    MULADD(at[11], at[59]);    MULADD(at[12], at[58]);    MULADD(at[13], at[57]);    MULADD(at[14], at[56]);    MULADD(at[15], at[55]);    MULADD(at[16], at[54]);    MULADD(at[17], at[53]);    MULADD(at[18], at[52]);    MULADD(at[19], at[51]);    MULADD(at[20], at[50]);    MULADD(at[21], at[49]);    MULADD(at[22], at[48]);    MULADD(at[23], at[47]);    MULADD(at[24], at[46]);    MULADD(at[25], at[45]);    MULADD(at[26], at[44]);    MULADD(at[27], at[43]);    MULADD(at[28], at[42]);    MULADD(at[29], at[41]);    MULADD(at[30], at[40]);    MULADD(at[31], at[39]);
+   COMBA_STORE(C->dp[38]);
+   /* 39 */
+   COMBA_FORWARD;
+   MULADD(at[8], at[63]);    MULADD(at[9], at[62]);    MULADD(at[10], at[61]);    MULADD(at[11], at[60]);    MULADD(at[12], at[59]);    MULADD(at[13], at[58]);    MULADD(at[14], at[57]);    MULADD(at[15], at[56]);    MULADD(at[16], at[55]);    MULADD(at[17], at[54]);    MULADD(at[18], at[53]);    MULADD(at[19], at[52]);    MULADD(at[20], at[51]);    MULADD(at[21], at[50]);    MULADD(at[22], at[49]);    MULADD(at[23], at[48]);    MULADD(at[24], at[47]);    MULADD(at[25], at[46]);    MULADD(at[26], at[45]);    MULADD(at[27], at[44]);    MULADD(at[28], at[43]);    MULADD(at[29], at[42]);    MULADD(at[30], at[41]);    MULADD(at[31], at[40]);
+   COMBA_STORE(C->dp[39]);
+   /* 40 */
+   COMBA_FORWARD;
+   MULADD(at[9], at[63]);    MULADD(at[10], at[62]);    MULADD(at[11], at[61]);    MULADD(at[12], at[60]);    MULADD(at[13], at[59]);    MULADD(at[14], at[58]);    MULADD(at[15], at[57]);    MULADD(at[16], at[56]);    MULADD(at[17], at[55]);    MULADD(at[18], at[54]);    MULADD(at[19], at[53]);    MULADD(at[20], at[52]);    MULADD(at[21], at[51]);    MULADD(at[22], at[50]);    MULADD(at[23], at[49]);    MULADD(at[24], at[48]);    MULADD(at[25], at[47]);    MULADD(at[26], at[46]);    MULADD(at[27], at[45]);    MULADD(at[28], at[44]);    MULADD(at[29], at[43]);    MULADD(at[30], at[42]);    MULADD(at[31], at[41]);
+   COMBA_STORE(C->dp[40]);
+   /* 41 */
+   COMBA_FORWARD;
+   MULADD(at[10], at[63]);    MULADD(at[11], at[62]);    MULADD(at[12], at[61]);    MULADD(at[13], at[60]);    MULADD(at[14], at[59]);    MULADD(at[15], at[58]);    MULADD(at[16], at[57]);    MULADD(at[17], at[56]);    MULADD(at[18], at[55]);    MULADD(at[19], at[54]);    MULADD(at[20], at[53]);    MULADD(at[21], at[52]);    MULADD(at[22], at[51]);    MULADD(at[23], at[50]);    MULADD(at[24], at[49]);    MULADD(at[25], at[48]);    MULADD(at[26], at[47]);    MULADD(at[27], at[46]);    MULADD(at[28], at[45]);    MULADD(at[29], at[44]);    MULADD(at[30], at[43]);    MULADD(at[31], at[42]);
+   COMBA_STORE(C->dp[41]);
+   /* 42 */
+   COMBA_FORWARD;
+   MULADD(at[11], at[63]);    MULADD(at[12], at[62]);    MULADD(at[13], at[61]);    MULADD(at[14], at[60]);    MULADD(at[15], at[59]);    MULADD(at[16], at[58]);    MULADD(at[17], at[57]);    MULADD(at[18], at[56]);    MULADD(at[19], at[55]);    MULADD(at[20], at[54]);    MULADD(at[21], at[53]);    MULADD(at[22], at[52]);    MULADD(at[23], at[51]);    MULADD(at[24], at[50]);    MULADD(at[25], at[49]);    MULADD(at[26], at[48]);    MULADD(at[27], at[47]);    MULADD(at[28], at[46]);    MULADD(at[29], at[45]);    MULADD(at[30], at[44]);    MULADD(at[31], at[43]);
+   COMBA_STORE(C->dp[42]);
+   /* 43 */
+   COMBA_FORWARD;
+   MULADD(at[12], at[63]);    MULADD(at[13], at[62]);    MULADD(at[14], at[61]);    MULADD(at[15], at[60]);    MULADD(at[16], at[59]);    MULADD(at[17], at[58]);    MULADD(at[18], at[57]);    MULADD(at[19], at[56]);    MULADD(at[20], at[55]);    MULADD(at[21], at[54]);    MULADD(at[22], at[53]);    MULADD(at[23], at[52]);    MULADD(at[24], at[51]);    MULADD(at[25], at[50]);    MULADD(at[26], at[49]);    MULADD(at[27], at[48]);    MULADD(at[28], at[47]);    MULADD(at[29], at[46]);    MULADD(at[30], at[45]);    MULADD(at[31], at[44]);
+   COMBA_STORE(C->dp[43]);
+   /* 44 */
+   COMBA_FORWARD;
+   MULADD(at[13], at[63]);    MULADD(at[14], at[62]);    MULADD(at[15], at[61]);    MULADD(at[16], at[60]);    MULADD(at[17], at[59]);    MULADD(at[18], at[58]);    MULADD(at[19], at[57]);    MULADD(at[20], at[56]);    MULADD(at[21], at[55]);    MULADD(at[22], at[54]);    MULADD(at[23], at[53]);    MULADD(at[24], at[52]);    MULADD(at[25], at[51]);    MULADD(at[26], at[50]);    MULADD(at[27], at[49]);    MULADD(at[28], at[48]);    MULADD(at[29], at[47]);    MULADD(at[30], at[46]);    MULADD(at[31], at[45]);
+   COMBA_STORE(C->dp[44]);
+   /* 45 */
+   COMBA_FORWARD;
+   MULADD(at[14], at[63]);    MULADD(at[15], at[62]);    MULADD(at[16], at[61]);    MULADD(at[17], at[60]);    MULADD(at[18], at[59]);    MULADD(at[19], at[58]);    MULADD(at[20], at[57]);    MULADD(at[21], at[56]);    MULADD(at[22], at[55]);    MULADD(at[23], at[54]);    MULADD(at[24], at[53]);    MULADD(at[25], at[52]);    MULADD(at[26], at[51]);    MULADD(at[27], at[50]);    MULADD(at[28], at[49]);    MULADD(at[29], at[48]);    MULADD(at[30], at[47]);    MULADD(at[31], at[46]);
+   COMBA_STORE(C->dp[45]);
+   /* 46 */
+   COMBA_FORWARD;
+   MULADD(at[15], at[63]);    MULADD(at[16], at[62]);    MULADD(at[17], at[61]);    MULADD(at[18], at[60]);    MULADD(at[19], at[59]);    MULADD(at[20], at[58]);    MULADD(at[21], at[57]);    MULADD(at[22], at[56]);    MULADD(at[23], at[55]);    MULADD(at[24], at[54]);    MULADD(at[25], at[53]);    MULADD(at[26], at[52]);    MULADD(at[27], at[51]);    MULADD(at[28], at[50]);    MULADD(at[29], at[49]);    MULADD(at[30], at[48]);    MULADD(at[31], at[47]);
+   COMBA_STORE(C->dp[46]);
+   /* 47 */
+   COMBA_FORWARD;
+   MULADD(at[16], at[63]);    MULADD(at[17], at[62]);    MULADD(at[18], at[61]);    MULADD(at[19], at[60]);    MULADD(at[20], at[59]);    MULADD(at[21], at[58]);    MULADD(at[22], at[57]);    MULADD(at[23], at[56]);    MULADD(at[24], at[55]);    MULADD(at[25], at[54]);    MULADD(at[26], at[53]);    MULADD(at[27], at[52]);    MULADD(at[28], at[51]);    MULADD(at[29], at[50]);    MULADD(at[30], at[49]);    MULADD(at[31], at[48]);
+   COMBA_STORE(C->dp[47]);
+   /* 48 */
+   COMBA_FORWARD;
+   MULADD(at[17], at[63]);    MULADD(at[18], at[62]);    MULADD(at[19], at[61]);    MULADD(at[20], at[60]);    MULADD(at[21], at[59]);    MULADD(at[22], at[58]);    MULADD(at[23], at[57]);    MULADD(at[24], at[56]);    MULADD(at[25], at[55]);    MULADD(at[26], at[54]);    MULADD(at[27], at[53]);    MULADD(at[28], at[52]);    MULADD(at[29], at[51]);    MULADD(at[30], at[50]);    MULADD(at[31], at[49]);
+   COMBA_STORE(C->dp[48]);
+   /* 49 */
+   COMBA_FORWARD;
+   MULADD(at[18], at[63]);    MULADD(at[19], at[62]);    MULADD(at[20], at[61]);    MULADD(at[21], at[60]);    MULADD(at[22], at[59]);    MULADD(at[23], at[58]);    MULADD(at[24], at[57]);    MULADD(at[25], at[56]);    MULADD(at[26], at[55]);    MULADD(at[27], at[54]);    MULADD(at[28], at[53]);    MULADD(at[29], at[52]);    MULADD(at[30], at[51]);    MULADD(at[31], at[50]);
+   COMBA_STORE(C->dp[49]);
+   /* 50 */
+   COMBA_FORWARD;
+   MULADD(at[19], at[63]);    MULADD(at[20], at[62]);    MULADD(at[21], at[61]);    MULADD(at[22], at[60]);    MULADD(at[23], at[59]);    MULADD(at[24], at[58]);    MULADD(at[25], at[57]);    MULADD(at[26], at[56]);    MULADD(at[27], at[55]);    MULADD(at[28], at[54]);    MULADD(at[29], at[53]);    MULADD(at[30], at[52]);    MULADD(at[31], at[51]);
+   COMBA_STORE(C->dp[50]);
+   /* 51 */
+   COMBA_FORWARD;
+   MULADD(at[20], at[63]);    MULADD(at[21], at[62]);    MULADD(at[22], at[61]);    MULADD(at[23], at[60]);    MULADD(at[24], at[59]);    MULADD(at[25], at[58]);    MULADD(at[26], at[57]);    MULADD(at[27], at[56]);    MULADD(at[28], at[55]);    MULADD(at[29], at[54]);    MULADD(at[30], at[53]);    MULADD(at[31], at[52]);
+   COMBA_STORE(C->dp[51]);
+   /* 52 */
+   COMBA_FORWARD;
+   MULADD(at[21], at[63]);    MULADD(at[22], at[62]);    MULADD(at[23], at[61]);    MULADD(at[24], at[60]);    MULADD(at[25], at[59]);    MULADD(at[26], at[58]);    MULADD(at[27], at[57]);    MULADD(at[28], at[56]);    MULADD(at[29], at[55]);    MULADD(at[30], at[54]);    MULADD(at[31], at[53]);
+   COMBA_STORE(C->dp[52]);
+   /* 53 */
+   COMBA_FORWARD;
+   MULADD(at[22], at[63]);    MULADD(at[23], at[62]);    MULADD(at[24], at[61]);    MULADD(at[25], at[60]);    MULADD(at[26], at[59]);    MULADD(at[27], at[58]);    MULADD(at[28], at[57]);    MULADD(at[29], at[56]);    MULADD(at[30], at[55]);    MULADD(at[31], at[54]);
+   COMBA_STORE(C->dp[53]);
+   /* 54 */
+   COMBA_FORWARD;
+   MULADD(at[23], at[63]);    MULADD(at[24], at[62]);    MULADD(at[25], at[61]);    MULADD(at[26], at[60]);    MULADD(at[27], at[59]);    MULADD(at[28], at[58]);    MULADD(at[29], at[57]);    MULADD(at[30], at[56]);    MULADD(at[31], at[55]);
+   COMBA_STORE(C->dp[54]);
+   /* 55 */
+   COMBA_FORWARD;
+   MULADD(at[24], at[63]);    MULADD(at[25], at[62]);    MULADD(at[26], at[61]);    MULADD(at[27], at[60]);    MULADD(at[28], at[59]);    MULADD(at[29], at[58]);    MULADD(at[30], at[57]);    MULADD(at[31], at[56]);
+   COMBA_STORE(C->dp[55]);
+   /* 56 */
+   COMBA_FORWARD;
+   MULADD(at[25], at[63]);    MULADD(at[26], at[62]);    MULADD(at[27], at[61]);    MULADD(at[28], at[60]);    MULADD(at[29], at[59]);    MULADD(at[30], at[58]);    MULADD(at[31], at[57]);
+   COMBA_STORE(C->dp[56]);
+   /* 57 */
+   COMBA_FORWARD;
+   MULADD(at[26], at[63]);    MULADD(at[27], at[62]);    MULADD(at[28], at[61]);    MULADD(at[29], at[60]);    MULADD(at[30], at[59]);    MULADD(at[31], at[58]);
+   COMBA_STORE(C->dp[57]);
+   /* 58 */
+   COMBA_FORWARD;
+   MULADD(at[27], at[63]);    MULADD(at[28], at[62]);    MULADD(at[29], at[61]);    MULADD(at[30], at[60]);    MULADD(at[31], at[59]);
+   COMBA_STORE(C->dp[58]);
+   /* 59 */
+   COMBA_FORWARD;
+   MULADD(at[28], at[63]);    MULADD(at[29], at[62]);    MULADD(at[30], at[61]);    MULADD(at[31], at[60]);
+   COMBA_STORE(C->dp[59]);
+   /* 60 */
+   COMBA_FORWARD;
+   MULADD(at[29], at[63]);    MULADD(at[30], at[62]);    MULADD(at[31], at[61]);
+   COMBA_STORE(C->dp[60]);
+   /* 61 */
+   COMBA_FORWARD;
+   MULADD(at[30], at[63]);    MULADD(at[31], at[62]);
+   COMBA_STORE(C->dp[61]);
+   /* 62 */
+   COMBA_FORWARD;
+   MULADD(at[31], at[63]);
+   COMBA_STORE(C->dp[62]);
+   COMBA_STORE2(C->dp[63]);
+   C->used = 64;
+   C->sign = A->sign ^ B->sign;
+   fp_clamp(C);
+   COMBA_FINI;
+}
+
+#endif
+
+/* End: fp_mul_comba.c */
+
+/* Start: fp_mul_d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a * b */
+void fp_mul_d(fp_int *a, fp_digit b, fp_int *c)
+{
+   fp_word  w;
+   int      x, oldused;
+
+   oldused = c->used;
+   c->used = a->used;
+   c->sign = a->sign;
+   w       = 0;
+   for (x = 0; x < a->used; x++) {
+       w         = ((fp_word)a->dp[x]) * ((fp_word)b) + w;
+       c->dp[x]  = (fp_digit)w;
+       w         = w >> DIGIT_BIT;
+   }
+   if (w != 0 && (a->used != FP_SIZE)) {
+      c->dp[c->used++] = w;
+      ++x;
+   }
+   for (; x < oldused; x++) {
+      c->dp[x] = 0;
+   }
+   fp_clamp(c);
+}
+
+
+/* End: fp_mul_d.c */
+
+/* Start: fp_mulmod.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+/* d = a * b (mod c) */
+int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
+{
+  fp_int tmp;
+  fp_zero(&tmp);
+  fp_mul(a, b, &tmp);
+  return fp_mod(&tmp, c, d);
+}
+
+/* End: fp_mulmod.c */
+
+/* Start: fp_prime_miller_rabin.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* Miller-Rabin test of "a" to the base of "b" as described in
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often
+ * very much lower.
+ */
+void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
+{
+  fp_int  n1, y, r;
+  int     s, j;
+
+  /* default */
+  *result = FP_NO;
+
+  /* ensure b > 1 */
+  if (fp_cmp_d(b, 1) != FP_GT) {
+     return;
+  }
+
+  /* get n1 = a - 1 */
+  fp_init_copy(&n1, a);
+  fp_sub_d(&n1, 1, &n1);
+
+  /* set 2**s * r = n1 */
+  fp_init_copy(&r, &n1);
+
+  /* count the number of least significant bits
+   * which are zero
+   */
+  s = fp_cnt_lsb(&r);
+
+  /* now divide n - 1 by 2**s */
+  fp_div_2d (&r, s, &r, NULL);
+
+  /* compute y = b**r mod a */
+  fp_init(&y);
+  fp_exptmod(b, &r, a, &y);
+
+  /* if y != 1 and y != n1 do */
+  if (fp_cmp_d (&y, 1) != FP_EQ && fp_cmp (&y, &n1) != FP_EQ) {
+    j = 1;
+    /* while j <= s-1 and y != n1 */
+    while ((j <= (s - 1)) && fp_cmp (&y, &n1) != FP_EQ) {
+      fp_sqrmod (&y, a, &y);
+
+      /* if y == 1 then composite */
+      if (fp_cmp_d (&y, 1) == FP_EQ) {
+         return;
+      }
+      ++j;
+    }
+
+    /* if y != n1 then composite */
+    if (fp_cmp (&y, &n1) != FP_EQ) {
+       return;
+    }
+  }
+
+  /* probably prime now */
+  *result = FP_YES;
+}
+
+/* End: fp_prime_miller_rabin.c */
+
+/* Start: fp_prime_random_ex.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat)
+{
+   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+   int res, err, bsize, maskOR_msb_offset;
+
+   /* sanity check the input */
+   if (size <= 1 || t <= 0) {
+      return FP_VAL;
+   }
+
+   /* TFM_PRIME_SAFE implies TFM_PRIME_BBS */
+   if (flags & TFM_PRIME_SAFE) {
+      flags |= TFM_PRIME_BBS;
+   }
+
+   /* calc the byte size */
+   bsize = (size>>3)+(size&7?1:0);
+
+   /* we need a buffer of bsize bytes */
+   tmp = malloc(bsize);
+   if (tmp == NULL) {
+      return FP_MEM;
+   }
+
+   /* calc the maskAND value for the MSbyte*/
+   maskAND = 0xFF >> (8 - (size & 7));
+
+   /* calc the maskOR_msb */
+   maskOR_msb        = 0;
+   maskOR_msb_offset = (size - 2) >> 3;
+   if (flags & TFM_PRIME_2MSB_ON) {
+      maskOR_msb     |= 1 << ((size - 2) & 7);
+   } else if (flags & TFM_PRIME_2MSB_OFF) {
+      maskAND        &= ~(1 << ((size - 2) & 7));
+   }
+
+   /* get the maskOR_lsb */
+   maskOR_lsb         = 1;
+   if (flags & TFM_PRIME_BBS) {
+      maskOR_lsb     |= 3;
+   }
+
+   do {
+      /* read the bytes */
+      if (cb(tmp, bsize, dat) != bsize) {
+         err = FP_VAL;
+         goto error;
+      }
+
+      /* work over the MSbyte */
+      tmp[0]    &= maskAND;
+      tmp[0]    |= 1 << ((size - 1) & 7);
+
+      /* mix in the maskORs */
+      tmp[maskOR_msb_offset]   |= maskOR_msb;
+      tmp[bsize-1]             |= maskOR_lsb;
+
+      /* read it in */
+      fp_read_unsigned_bin(a, tmp, bsize);
+
+      /* is it prime? */
+      res = fp_isprime(a);
+      if (res == FP_NO) continue;
+
+      if (flags & TFM_PRIME_SAFE) {
+         /* see if (a-1)/2 is prime */
+         fp_sub_d(a, 1, a);
+         fp_div_2(a, a);
+
+         /* is it prime? */
+         res = fp_isprime(a);
+      }
+   } while (res == FP_NO);
+
+   if (flags & TFM_PRIME_SAFE) {
+      /* restore a to the original value */
+      fp_mul_2(a, a);
+      fp_add_d(a, 1, a);
+   }
+
+   err = FP_OKAY;
+error:
+   free(tmp);
+   return err;
+}
+
+/* End: fp_prime_random_ex.c */
+
+/* Start: fp_radix_size.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+int fp_radix_size(fp_int *a, int radix, int *size)
+{
+  int     digs;
+  fp_int  t;
+  fp_digit d;
+
+  *size = 0;
+
+  /* check range of the radix */
+  if (radix < 2 || radix > 64) {
+    return FP_VAL;
+  }
+
+  /* quick out if its zero */
+  if (fp_iszero(a) == 1) {
+     *size = 2;
+     return FP_OKAY;
+  }
+
+  fp_init_copy(&t, a);
+
+  /* if it is negative output a - */
+  if (t.sign == FP_NEG) {
+    *size++;
+    t.sign = FP_ZPOS;
+  }
+
+  digs = 0;
+  while (fp_iszero (&t) == FP_NO) {
+    fp_div_d (&t, (fp_digit) radix, &t, &d);
+    *size++;
+  }
+
+  /* append a NULL so the string is properly terminated */
+  *size++;
+  return FP_OKAY;
+
+}
+
+/* End: fp_radix_size.c */
+
+/* Start: fp_read_radix.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+int fp_read_radix(fp_int *a, char *str, int radix)
+{
+  int     y, neg;
+  char    ch;
+
+  /* make sure the radix is ok */
+  if (radix < 2 || radix > 64) {
+    return FP_VAL;
+  }
+
+  /* if the leading digit is a
+   * minus set the sign to negative.
+   */
+  if (*str == '-') {
+    ++str;
+    neg = FP_NEG;
+  } else {
+    neg = FP_ZPOS;
+  }
+
+  /* set the integer to the default of zero */
+  fp_zero (a);
+
+  /* process each digit of the string */
+  while (*str) {
+    /* if the radix < 36 the conversion is case insensitive
+     * this allows numbers like 1AB and 1ab to represent the same  value
+     * [e.g. in hex]
+     */
+    ch = (char) ((radix < 36) ? toupper (*str) : *str);
+    for (y = 0; y < 64; y++) {
+      if (ch == fp_s_rmap[y]) {
+         break;
+      }
+    }
+
+    /* if the char was found in the map
+     * and is less than the given radix add it
+     * to the number, otherwise exit the loop.
+     */
+    if (y < radix) {
+      fp_mul_d (a, (fp_digit) radix, a);
+      fp_add_d (a, (fp_digit) y, a);
+    } else {
+      break;
+    }
+    ++str;
+  }
+
+  /* set the sign only if a != 0 */
+  if (fp_iszero(a) != FP_YES) {
+     a->sign = neg;
+  }
+  return FP_OKAY;
+}
+
+/* End: fp_read_radix.c */
+
+/* Start: fp_read_signed_bin.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_read_signed_bin(fp_int *a, unsigned char *b, int c)
+{
+  /* read magnitude */
+  fp_read_unsigned_bin (a, b + 1, c - 1);
+
+  /* first byte is 0 for positive, non-zero for negative */
+  if (b[0] == 0) {
+     a->sign = FP_ZPOS;
+  } else {
+     a->sign = FP_NEG;
+  }
+}
+
+/* End: fp_read_signed_bin.c */
+
+/* Start: fp_read_unsigned_bin.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c)
+{
+  /* zero the int */
+  fp_zero (a);
+
+  /* read the bytes in */
+  for (; c > 0; c--) {
+    fp_mul_2d (a, 8, a);
+    a->dp[0] |= *b++;
+    a->used += 1;
+  }
+  fp_clamp (a);
+}
+
+/* End: fp_read_unsigned_bin.c */
+
+/* Start: fp_reverse.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* reverse an array, used for radix code */
+void bn_reverse (unsigned char *s, int len)
+{
+  int     ix, iy;
+  unsigned char t;
+
+  ix = 0;
+  iy = len - 1;
+  while (ix < iy) {
+    t     = s[ix];
+    s[ix] = s[iy];
+    s[iy] = t;
+    ++ix;
+    --iy;
+  }
+}
+
+/* End: fp_reverse.c */
+
+/* Start: fp_rshd.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_rshd(fp_int *a, int x)
+{
+  int y;
+
+  /* too many digits just zero and return */
+  if (x >= a->used) {
+     fp_zero(a);
+     return;
+  }
+
+   /* shift */
+   for (y = 0; y < a->used - x; y++) {
+      a->dp[y] = a->dp[y+x];
+   }
+
+   /* zero rest */
+   for (; y < a->used; y++) {
+      a->dp[y] = 0;
+   }
+
+   /* decrement count */
+   a->used -= x;
+   fp_clamp(a);
+}
+
+
+/* End: fp_rshd.c */
+
+/* Start: fp_s_rmap.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* chars used in radix conversions */
+const char *fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+/* End: fp_s_rmap.c */
+
+/* Start: fp_set.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_set(fp_int *a, fp_digit b)
+{
+   fp_zero(a);
+   a->dp[0] = b;
+   a->used  = b ? 1 : 0;
+}
+
+/* End: fp_set.c */
+
+/* Start: fp_signed_bin_size.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+int fp_signed_bin_size(fp_int *a)
+{
+  return 1 + fp_unsigned_bin_size (a);
+}
+
+/* End: fp_signed_bin_size.c */
+
+/* Start: fp_sqr.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* b = a*a  */
+void fp_sqr(fp_int *A, fp_int *B)
+{
+    int    r, y, s;
+    fp_int aa, bb, comp, amb, t1;
+
+    y = A->used;
+    if (y <= 64) {
+        if (y <= 4) {
+           fp_sqr_comba4(A,B);
+        } else if (y <= 8) {
+           fp_sqr_comba8(A,B);
+#if defined(TFM_LARGE)
+        } else if (y <= 16 && y >= 12) {
+           fp_sqr_comba16(A,B);
+#endif
+#if defined(TFM_HUGE)
+        } else if (y <= 32 && y >= 20) {
+           fp_sqr_comba32(A,B);
+        } else if (y <= 64 && y >= 48) {
+           fp_sqr_comba64(A,B);
+#endif
+        } else {
+           fp_sqr_comba(A, B);
+        }
+
+    } else {
+        /* do the karatsuba action
+
+           if A = ab ||a|| = r we need to solve
+
+           a^2*r^2 + (-(a-b)^2 + a^2 + b^2)*r + b^2
+
+           So we solve for the three products then we form the final result with careful shifting
+           and addition.
+
+Obvious points of optimization
+
+- "ac" parts can be memcpy'ed with an offset [all you have to do is zero upto the next 8 digits]
+- Similarly the "bd" parts can be memcpy'ed and zeroed to 8
+-
+
+        */
+        /* get our value of r */
+        r = y >> 1;
+
+        /* now solve for ac */
+//        fp_copy(A, &t1); fp_rshd(&t1, r);
+        for (s = 0; s < A->used - r; s++) {
+            t1.dp[s] = A->dp[s+r];
+        }
+        for (; s < FP_SIZE; s++) {
+            t1.dp[s] = 0;
+        }
+        if (A->used >= r) {
+           t1.used = A->used - r;
+        } else {
+           t1.used = 0;
+        }
+        t1.sign = A->sign;
+        fp_copy(&t1, &amb);
+        fp_zero(&aa);
+        fp_sqr(&t1, &aa);
+
+        /* now solve for bd */
+//        fp_mod_2d(A, r * DIGIT_BIT, &t1);
+        for (s = 0; s < r; s++) {
+            t1.dp[s] = A->dp[s];
+        }
+        for (; s < FP_SIZE; s++) {
+            t1.dp[s]   = 0;
+        }
+        t1.used = r;
+        fp_clamp(&t1);
+
+        fp_sub(&amb, &t1, &amb);
+        fp_zero(&bb);
+        fp_sqr(&t1, &bb);
+
+        /* now get the (a-b) term */
+        fp_zero(&comp);
+        fp_sqr(&amb, &comp);
+
+        /* now solve the system, do the middle term first */
+        comp.sign ^= 1;
+        fp_add(&comp, &aa, &comp);
+        fp_add(&comp, &bb, &comp);
+        fp_lshd(&comp, r);
+
+        /* leading term */
+        fp_lshd(&aa, r+r);
+
+        /* now sum them together */
+        fp_zero(B);
+        fp_add(&aa, &comp, B);
+        fp_add(&bb, B, B);
+        B->sign = FP_ZPOS;
+    }
+}
+
+
+/* End: fp_sqr.c */
+
+/* Start: fp_sqr_comba.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* About this file...
+*/
+
+#if defined(TFM_X86)
+
+/* x86-32 optimized */
+
+#define COMBA_START
+
+#define CLEAR_CARRY \
+   c0 = c1 = c2 = 0;
+
+#define COMBA_STORE(x) \
+   x = c0;
+
+#define COMBA_STORE2(x) \
+   x = c1;
+
+#define CARRY_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+#define COMBA_FINI
+
+#define SQRADD(i, j)                                      \
+asm volatile (                                            \
+     "movl  %6,%%eax     \n\t"                            \
+     "mull  %%eax        \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","%cc");
+
+#define SQRADD2(i, j)                                     \
+asm volatile (                                            \
+     "movl  %6,%%eax     \n\t"                            \
+     "mull  %7           \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","%edx","%cc");
+
+#define SQRADDSC(i, j)                                    \
+asm (                                                     \
+     "movl  %6,%%eax     \n\t"                            \
+     "mull  %7           \n\t"                            \
+     "movl  %%eax,%0     \n\t"                            \
+     "movl  %%edx,%1     \n\t"                            \
+     "xorl  %2,%2        \n\t"                            \
+     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc");
+
+#define SQRADDAC(i, j)                                    \
+asm (                                                     \
+     "movl  %6,%%eax     \n\t"                            \
+     "mull  %7           \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","%cc");
+
+#define SQRADDDB                                          \
+asm (                                                     \
+     "addl %3,%0         \n\t"                            \
+     "adcl %4,%1         \n\t"                            \
+     "adcl %5,%2         \n\t"                            \
+     "addl %3,%0         \n\t"                            \
+     "adcl %4,%1         \n\t"                            \
+     "adcl %5,%2         \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2), "=g"(sc0), "=g"(sc1), "=g"(sc2) : "0"(c0), "1"(c1), "2"(c2), "3"(sc0), "4"(sc1), "5"(sc2) : "%cc");
+
+#elif defined(TFM_X86_64)
+/* x86-64 optimized */
+
+#define COMBA_START
+
+#define CLEAR_CARRY \
+   c0 = c1 = c2 = 0;
+
+#define COMBA_STORE(x) \
+   x = c0;
+
+#define COMBA_STORE2(x) \
+   x = c1;
+
+#define CARRY_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+#define COMBA_FINI
+
+#define SQRADD(i, j)                                      \
+asm (                                                     \
+     "movq  %6,%%rax     \n\t"                            \
+     "mulq  %%rax        \n\t"                            \
+     "addq  %%rax,%0     \n\t"                            \
+     "adcq  %%rdx,%1     \n\t"                            \
+     "adcq  $0,%2        \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","%cc");
+
+#define SQRADD2(i, j)                                     \
+asm (                                                     \
+     "movq  %6,%%rax     \n\t"                            \
+     "mulq  %7           \n\t"                            \
+     "addq  %%rax,%0     \n\t"                            \
+     "adcq  %%rdx,%1     \n\t"                            \
+     "adcq  $0,%2        \n\t"                            \
+     "addq  %%rax,%0     \n\t"                            \
+     "adcq  %%rdx,%1     \n\t"                            \
+     "adcq  $0,%2        \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j)  :"%rax","%rdx","%cc");
+
+#define SQRADDSC(i, j)                                    \
+asm (                                                     \
+     "movq  %6,%%rax     \n\t"                            \
+     "mulq  %7           \n\t"                            \
+     "movq  %%rax,%0     \n\t"                            \
+     "movq  %%rdx,%1     \n\t"                            \
+     "xorq  %2,%2        \n\t"                            \
+     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","%cc");
+
+#define SQRADDAC(i, j)                                                         \
+asm (                                                     \
+     "movq  %6,%%rax     \n\t"                            \
+     "mulq  %7           \n\t"                            \
+     "addq  %%rax,%0     \n\t"                            \
+     "adcq  %%rdx,%1     \n\t"                            \
+     "adcq  $0,%2        \n\t"                            \
+     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","%cc");
+
+#define SQRADDDB                                                               \
+asm (                                                     \
+     "addq %3,%0         \n\t"                            \
+     "adcq %4,%1         \n\t"                            \
+     "adcq %5,%2         \n\t"                            \
+     "addq %3,%0         \n\t"                            \
+     "adcq %4,%1         \n\t"                            \
+     "adcq %5,%2         \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2), "=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(c0), "1"(c1), "2"(c2), "3"(sc0), "4"(sc1), "5"(sc2) : "%cc");
+
+#elif defined(TFM_SSE2)
+
+/* SSE2 Optimized */
+#define COMBA_START
+
+#define CLEAR_CARRY \
+   c0 = c1 = c2 = 0;
+
+#define COMBA_STORE(x) \
+   x = c0;
+
+#define COMBA_STORE2(x) \
+   x = c1;
+
+#define CARRY_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+#define COMBA_FINI \
+   asm("emms");
+
+#define SQRADD(i, j)                                      \
+asm volatile (                                            \
+     "movd  %6,%%mm0     \n\t"                            \
+     "pmuludq %%mm0,%%mm0\n\t"                            \
+     "movd  %%mm0,%%eax  \n\t"                            \
+     "psrlq $32,%%mm0    \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "movd  %%mm0,%%eax  \n\t"                            \
+     "adcl  %%eax,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%cc");
+
+#define SQRADD2(i, j)                                     \
+asm volatile (                                            \
+     "movd  %6,%%mm0     \n\t"                            \
+     "movd  %7,%%mm1     \n\t"                            \
+     "pmuludq %%mm1,%%mm0\n\t"                            \
+     "movd  %%mm0,%%eax  \n\t"                            \
+     "psrlq $32,%%mm0    \n\t"                            \
+     "movd  %%mm0,%%edx  \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j)  :"%eax","%edx","%cc");
+
+#define SQRADDSC(i, j)                                                         \
+asm volatile (                                            \
+     "movd  %6,%%mm0     \n\t"                            \
+     "pmuludq %%mm0,%%mm0\n\t"                            \
+     "movd  %%mm0,%%eax  \n\t"                            \
+     "psrlq $32,%%mm0    \n\t"                            \
+     "movl  %%eax,%0     \n\t"                            \
+     "movd  %%mm0,%%eax  \n\t"                            \
+     "movl  %%eax,%1     \n\t"                            \
+     "xorl  %2,%2        \n\t"                            \
+     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "m"(i) :"%eax","%cc");
+
+#define SQRADDAC(i, j)                                                         \
+asm volatile (                                            \
+     "movd  %6,%%mm0     \n\t"                            \
+     "movd  %7,%%mm1     \n\t"                            \
+     "pmuludq %%mm1,%%mm0\n\t"                            \
+     "movd  %%mm0,%%eax  \n\t"                            \
+     "psrlq $32,%%mm0    \n\t"                            \
+     "movd  %%mm0,%%edx  \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     "addl  %%eax,%0     \n\t"                            \
+     "adcl  %%edx,%1     \n\t"                            \
+     "adcl  $0,%2        \n\t"                            \
+     :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "m"(i), "m"(j)  :"%eax","%edx","%cc");
+
+#define SQRADDDB                                                               \
+asm (                                                     \
+     "addl %3,%0         \n\t"                            \
+     "adcl %4,%1         \n\t"                            \
+     "adcl %5,%2         \n\t"                            \
+     "addl %3,%0         \n\t"                            \
+     "adcl %4,%1         \n\t"                            \
+     "adcl %5,%2         \n\t"                            \
+     :"=r"(c0), "=r"(c1), "=r"(c2), "=g"(sc0), "=g"(sc1), "=g"(sc2) : "0"(c0), "1"(c1), "2"(c2), "3"(sc0), "4"(sc1), "5"(sc2) : "%cc");
+
+#elif defined(TFM_ARM)
+
+/* ARM code */
+
+#define COMBA_START
+
+#define CLEAR_CARRY \
+   c0 = c1 = c2 = 0;
+
+#define COMBA_STORE(x) \
+   x = c0;
+
+#define COMBA_STORE2(x) \
+   x = c1;
+
+#define CARRY_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+#define COMBA_FINI
+
+/* multiplies point i and j, updates carry "c1" and digit c2 */
+#define SQRADD(i, j)                                             \
+asm(                                                             \
+"  UMULL  r0,r1,%6,%6              \n\t"                         \
+"  ADDS   %0,%0,r0                 \n\t"                         \
+"  ADCS   %1,%1,r1                 \n\t"                         \
+"  ADC    %2,%2,#0                 \n\t"                         \
+:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "%cc");
+
+/* for squaring some of the terms are doubled... */
+#define SQRADD2(i, j)                                            \
+asm(                                                             \
+"  UMULL  r0,r1,%6,%7              \n\t"                         \
+"  ADDS   %0,%0,r0                 \n\t"                         \
+"  ADCS   %1,%1,r1                 \n\t"                         \
+"  ADC    %2,%2,#0                 \n\t"                         \
+"  ADDS   %0,%0,r0                 \n\t"                         \
+"  ADCS   %1,%1,r1                 \n\t"                         \
+"  ADC    %2,%2,#0                 \n\t"                         \
+:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "%cc");
+
+#define SQRADDSC(i, j)                                           \
+asm(                                                             \
+"  UMULL  %0,%1,%6,%7              \n\t"                         \
+"  SUB    %2,%2,%2                 \n\t"                         \
+:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "%cc");
+
+#define SQRADDAC(i, j)                                           \
+asm(                                                             \
+"  UMULL  r0,r1,%6,%7              \n\t"                         \
+"  ADDS   %0,%0,r0                 \n\t"                         \
+"  ADCS   %1,%1,r1                 \n\t"                         \
+"  ADC    %2,%2,#0                 \n\t"                         \
+:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "%cc");
+
+#define SQRADDDB                                                 \
+asm(                                                             \
+"  ADDS  %3,%0                     \n\t"                         \
+"  ADCS  %4,%1                     \n\t"                         \
+"  ADC   %5,%2                     \n\t"                         \
+"  ADDS  %3,%0                     \n\t"                         \
+"  ADCS  %4,%1                     \n\t"                         \
+"  ADC   %5,%2                     \n\t"                         \
+:"=r"(sc0), "=r"(sc1), "=r"(sc2), "=r"(c0), "=r"(c1), "=r"(c2) : "0"(sc0), "1"(sc1), "2"(sc2), "3"(c0), "4"(c1), "5"(c2) : "%cc");
+
+#else
+
+/* ISO C portable code */
+
+#define COMBA_START \
+   { fp_word tt;
+
+#define CLEAR_CARRY \
+   c0 = c1 = c2 = 0;
+
+#define COMBA_STORE(x) \
+   x = c0;
+
+#define COMBA_STORE2(x) \
+   x = c1;
+
+#define CARRY_FORWARD \
+   do { c0 = c1; c1 = c2; c2 = 0; } while (0);
+
+#define COMBA_FINI \
+   }
+
+/* multiplies point i and j, updates carry "c1" and digit c2 */
+#define SQRADD(i, j)                                 \
+   do { fp_word t;                                   \
+   t = c0 + ((fp_word)i) * ((fp_word)j);  c0 = t;    \
+   t = c1 + (t >> DIGIT_BIT);             c1 = t; c2 += t >> DIGIT_BIT; \
+   } while (0);
+
+
+/* for squaring some of the terms are doubled... */
+#define SQRADD2(i, j)                                                 \
+   do { fp_word t;                                                    \
+   t  = ((fp_word)i) * ((fp_word)j);                                  \
+   tt = (fp_word)c0 + t;                 c0 = tt;                              \
+   tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = tt; c2 += tt >> DIGIT_BIT;       \
+   tt = (fp_word)c0 + t;                 c0 = tt;                              \
+   tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = tt; c2 += tt >> DIGIT_BIT;       \
+   } while (0);
+
+#define SQRADDSC(i, j)                                                         \
+   do { fp_word t;                                                             \
+      t =  ((fp_word)i) * ((fp_word)j);                                        \
+      sc0 = (fp_digit)t; sc1 = (t >> DIGIT_BIT); sc2 = 0;                      \
+   } while (0);
+
+#define SQRADDAC(i, j)                                                         \
+   do { fp_word t;                                                             \
+   t = sc0 + ((fp_word)i) * ((fp_word)j);  sc0 = t;                            \
+   t = sc1 + (t >> DIGIT_BIT);             sc1 = t; sc2 += t >> DIGIT_BIT;     \
+   } while (0);
+
+#define SQRADDDB                                                               \
+   do { fp_word t;                                                             \
+   t = ((fp_word)sc0) + ((fp_word)sc0) + c0; c0 = t;                                                 \
+   t = ((fp_word)sc1) + ((fp_word)sc1) + c1 + (t >> DIGIT_BIT); c1 = t;                              \
+   c2 = c2 + ((fp_word)sc2) + ((fp_word)sc2) + (t >> DIGIT_BIT);                                     \
+   } while (0);
+
+#endif
+
+#include "fp_sqr_comba_generic.c"
+void fp_sqr_comba4(fp_int *A, fp_int *B)
+{
+   fp_digit *a, b[8], c0, c1, c2, sc0, sc1, sc2;
+
+   a = A->dp;
+   COMBA_START;
+
+   /* clear carries */
+   CLEAR_CARRY;
+
+   /* output 0 */
+   SQRADD(a[0],a[0]);
+   COMBA_STORE(b[0]);
+
+   /* output 1 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[1]);
+   COMBA_STORE(b[1]);
+
+   /* output 2 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
+   COMBA_STORE(b[2]);
+
+   /* output 3 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
+   COMBA_STORE(b[3]);
+
+   /* output 4 */
+   CARRY_FORWARD;
+   SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
+   COMBA_STORE(b[4]);
+
+   /* output 5 */
+   CARRY_FORWARD;
+   SQRADD2(a[2], a[3]);
+   COMBA_STORE(b[5]);
+
+   /* output 6 */
+   CARRY_FORWARD;
+   SQRADD(a[3], a[3]);
+   COMBA_STORE(b[6]);
+   COMBA_STORE2(b[7]);
+   COMBA_FINI;
+
+   B->used = 8;
+   B->sign = FP_ZPOS;
+   memcpy(B->dp, b, 8 * sizeof(fp_digit));
+   fp_clamp(B);
+}
+
+
+void fp_sqr_comba8(fp_int *A, fp_int *B)
+{
+   fp_digit *a, b[16], c0, c1, c2, sc0, sc1, sc2;
+
+   a = A->dp;
+   COMBA_START;
+
+   /* clear carries */
+   CLEAR_CARRY;
+
+   /* output 0 */
+   SQRADD(a[0],a[0]);
+   COMBA_STORE(b[0]);
+
+   /* output 1 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[1]);
+   COMBA_STORE(b[1]);
+
+   /* output 2 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
+   COMBA_STORE(b[2]);
+
+   /* output 3 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
+   COMBA_STORE(b[3]);
+
+   /* output 4 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
+   COMBA_STORE(b[4]);
+
+   /* output 5 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
+   COMBA_STORE(b[5]);
+
+   /* output 6 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
+   COMBA_STORE(b[6]);
+
+   /* output 7 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
+   COMBA_STORE(b[7]);
+
+   /* output 8 */
+   CARRY_FORWARD;
+   SQRADDSC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
+   COMBA_STORE(b[8]);
+
+   /* output 9 */
+   CARRY_FORWARD;
+   SQRADDSC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
+   COMBA_STORE(b[9]);
+
+   /* output 10 */
+   CARRY_FORWARD;
+   SQRADD2(a[3], a[7]); SQRADD2(a[4], a[6]); SQRADD(a[5], a[5]);
+   COMBA_STORE(b[10]);
+
+   /* output 11 */
+   CARRY_FORWARD;
+   SQRADD2(a[4], a[7]); SQRADD2(a[5], a[6]);
+   COMBA_STORE(b[11]);
+
+   /* output 12 */
+   CARRY_FORWARD;
+   SQRADD2(a[5], a[7]); SQRADD(a[6], a[6]);
+   COMBA_STORE(b[12]);
+
+   /* output 13 */
+   CARRY_FORWARD;
+   SQRADD2(a[6], a[7]);
+   COMBA_STORE(b[13]);
+
+   /* output 14 */
+   CARRY_FORWARD;
+   SQRADD(a[7], a[7]);
+   COMBA_STORE(b[14]);
+   COMBA_STORE2(b[15]);
+   COMBA_FINI;
+
+   B->used = 16;
+   B->sign = FP_ZPOS;
+   memcpy(B->dp, b, 16 * sizeof(fp_digit));
+   fp_clamp(B);
+}
+
+
+#ifdef TFM_LARGE
+void fp_sqr_comba16(fp_int *A, fp_int *B)
+{
+   fp_digit *a, b[32], c0, c1, c2, sc0, sc1, sc2;
+
+   a = A->dp;
+   COMBA_START;
+
+   /* clear carries */
+   CLEAR_CARRY;
+
+   /* output 0 */
+   SQRADD(a[0],a[0]);
+   COMBA_STORE(b[0]);
+
+   /* output 1 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[1]);
+   COMBA_STORE(b[1]);
+
+   /* output 2 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
+   COMBA_STORE(b[2]);
+
+   /* output 3 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
+   COMBA_STORE(b[3]);
+
+   /* output 4 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
+   COMBA_STORE(b[4]);
+
+   /* output 5 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
+   COMBA_STORE(b[5]);
+
+   /* output 6 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
+   COMBA_STORE(b[6]);
+
+   /* output 7 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
+   COMBA_STORE(b[7]);
+
+   /* output 8 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
+   COMBA_STORE(b[8]);
+
+   /* output 9 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
+   COMBA_STORE(b[9]);
+
+   /* output 10 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
+   COMBA_STORE(b[10]);
+
+   /* output 11 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
+   COMBA_STORE(b[11]);
+
+   /* output 12 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
+   COMBA_STORE(b[12]);
+
+   /* output 13 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
+   COMBA_STORE(b[13]);
+
+   /* output 14 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
+   COMBA_STORE(b[14]);
+
+   /* output 15 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
+   COMBA_STORE(b[15]);
+
+   /* output 16 */
+   CARRY_FORWARD;
+   SQRADDSC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
+   COMBA_STORE(b[16]);
+
+   /* output 17 */
+   CARRY_FORWARD;
+   SQRADDSC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
+   COMBA_STORE(b[17]);
+
+   /* output 18 */
+   CARRY_FORWARD;
+   SQRADDSC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
+   COMBA_STORE(b[18]);
+
+   /* output 19 */
+   CARRY_FORWARD;
+   SQRADDSC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
+   COMBA_STORE(b[19]);
+
+   /* output 20 */
+   CARRY_FORWARD;
+   SQRADDSC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
+   COMBA_STORE(b[20]);
+
+   /* output 21 */
+   CARRY_FORWARD;
+   SQRADDSC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
+   COMBA_STORE(b[21]);
+
+   /* output 22 */
+   CARRY_FORWARD;
+   SQRADDSC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
+   COMBA_STORE(b[22]);
+
+   /* output 23 */
+   CARRY_FORWARD;
+   SQRADDSC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
+   COMBA_STORE(b[23]);
+
+   /* output 24 */
+   CARRY_FORWARD;
+   SQRADDSC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
+   COMBA_STORE(b[24]);
+
+   /* output 25 */
+   CARRY_FORWARD;
+   SQRADDSC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
+   COMBA_STORE(b[25]);
+
+   /* output 26 */
+   CARRY_FORWARD;
+   SQRADD2(a[11], a[15]); SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]);
+   COMBA_STORE(b[26]);
+
+   /* output 27 */
+   CARRY_FORWARD;
+   SQRADD2(a[12], a[15]); SQRADD2(a[13], a[14]);
+   COMBA_STORE(b[27]);
+
+   /* output 28 */
+   CARRY_FORWARD;
+   SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]);
+   COMBA_STORE(b[28]);
+
+   /* output 29 */
+   CARRY_FORWARD;
+   SQRADD2(a[14], a[15]);
+   COMBA_STORE(b[29]);
+
+   /* output 30 */
+   CARRY_FORWARD;
+   SQRADD(a[15], a[15]);
+   COMBA_STORE(b[30]);
+   COMBA_STORE2(b[31]);
+   COMBA_FINI;
+
+   B->used = 32;
+   B->sign = FP_ZPOS;
+   memcpy(B->dp, b, 32 * sizeof(fp_digit));
+   fp_clamp(B);
+}
+
+
+#endif
+#ifdef TFM_HUGE
+void fp_sqr_comba32(fp_int *A, fp_int *B)
+{
+   fp_digit *a, b[64], c0, c1, c2, sc0, sc1, sc2;
+
+   a = A->dp;
+   COMBA_START;
+
+   /* clear carries */
+   CLEAR_CARRY;
+
+   /* output 0 */
+   SQRADD(a[0],a[0]);
+   COMBA_STORE(b[0]);
+
+   /* output 1 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[1]);
+   COMBA_STORE(b[1]);
+
+   /* output 2 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
+   COMBA_STORE(b[2]);
+
+   /* output 3 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
+   COMBA_STORE(b[3]);
+
+   /* output 4 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
+   COMBA_STORE(b[4]);
+
+   /* output 5 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
+   COMBA_STORE(b[5]);
+
+   /* output 6 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
+   COMBA_STORE(b[6]);
+
+   /* output 7 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
+   COMBA_STORE(b[7]);
+
+   /* output 8 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
+   COMBA_STORE(b[8]);
+
+   /* output 9 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
+   COMBA_STORE(b[9]);
+
+   /* output 10 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
+   COMBA_STORE(b[10]);
+
+   /* output 11 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
+   COMBA_STORE(b[11]);
+
+   /* output 12 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
+   COMBA_STORE(b[12]);
+
+   /* output 13 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
+   COMBA_STORE(b[13]);
+
+   /* output 14 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
+   COMBA_STORE(b[14]);
+
+   /* output 15 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
+   COMBA_STORE(b[15]);
+
+   /* output 16 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
+   COMBA_STORE(b[16]);
+
+   /* output 17 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
+   COMBA_STORE(b[17]);
+
+   /* output 18 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
+   COMBA_STORE(b[18]);
+
+   /* output 19 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
+   COMBA_STORE(b[19]);
+
+   /* output 20 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
+   COMBA_STORE(b[20]);
+
+   /* output 21 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
+   COMBA_STORE(b[21]);
+
+   /* output 22 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
+   COMBA_STORE(b[22]);
+
+   /* output 23 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
+   COMBA_STORE(b[23]);
+
+   /* output 24 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
+   COMBA_STORE(b[24]);
+
+   /* output 25 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
+   COMBA_STORE(b[25]);
+
+   /* output 26 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
+   COMBA_STORE(b[26]);
+
+   /* output 27 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
+   COMBA_STORE(b[27]);
+
+   /* output 28 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
+   COMBA_STORE(b[28]);
+
+   /* output 29 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
+   COMBA_STORE(b[29]);
+
+   /* output 30 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
+   COMBA_STORE(b[30]);
+
+   /* output 31 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
+   COMBA_STORE(b[31]);
+
+   /* output 32 */
+   CARRY_FORWARD;
+   SQRADDSC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
+   COMBA_STORE(b[32]);
+
+   /* output 33 */
+   CARRY_FORWARD;
+   SQRADDSC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
+   COMBA_STORE(b[33]);
+
+   /* output 34 */
+   CARRY_FORWARD;
+   SQRADDSC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
+   COMBA_STORE(b[34]);
+
+   /* output 35 */
+   CARRY_FORWARD;
+   SQRADDSC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
+   COMBA_STORE(b[35]);
+
+   /* output 36 */
+   CARRY_FORWARD;
+   SQRADDSC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
+   COMBA_STORE(b[36]);
+
+   /* output 37 */
+   CARRY_FORWARD;
+   SQRADDSC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
+   COMBA_STORE(b[37]);
+
+   /* output 38 */
+   CARRY_FORWARD;
+   SQRADDSC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
+   COMBA_STORE(b[38]);
+
+   /* output 39 */
+   CARRY_FORWARD;
+   SQRADDSC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
+   COMBA_STORE(b[39]);
+
+   /* output 40 */
+   CARRY_FORWARD;
+   SQRADDSC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
+   COMBA_STORE(b[40]);
+
+   /* output 41 */
+   CARRY_FORWARD;
+   SQRADDSC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
+   COMBA_STORE(b[41]);
+
+   /* output 42 */
+   CARRY_FORWARD;
+   SQRADDSC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]);
+   COMBA_STORE(b[42]);
+
+   /* output 43 */
+   CARRY_FORWARD;
+   SQRADDSC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB;
+   COMBA_STORE(b[43]);
+
+   /* output 44 */
+   CARRY_FORWARD;
+   SQRADDSC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]);
+   COMBA_STORE(b[44]);
+
+   /* output 45 */
+   CARRY_FORWARD;
+   SQRADDSC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB;
+   COMBA_STORE(b[45]);
+
+   /* output 46 */
+   CARRY_FORWARD;
+   SQRADDSC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]);
+   COMBA_STORE(b[46]);
+
+   /* output 47 */
+   CARRY_FORWARD;
+   SQRADDSC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB;
+   COMBA_STORE(b[47]);
+
+   /* output 48 */
+   CARRY_FORWARD;
+   SQRADDSC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]);
+   COMBA_STORE(b[48]);
+
+   /* output 49 */
+   CARRY_FORWARD;
+   SQRADDSC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB;
+   COMBA_STORE(b[49]);
+
+   /* output 50 */
+   CARRY_FORWARD;
+   SQRADDSC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]);
+   COMBA_STORE(b[50]);
+
+   /* output 51 */
+   CARRY_FORWARD;
+   SQRADDSC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB;
+   COMBA_STORE(b[51]);
+
+   /* output 52 */
+   CARRY_FORWARD;
+   SQRADDSC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]);
+   COMBA_STORE(b[52]);
+
+   /* output 53 */
+   CARRY_FORWARD;
+   SQRADDSC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB;
+   COMBA_STORE(b[53]);
+
+   /* output 54 */
+   CARRY_FORWARD;
+   SQRADDSC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]);
+   COMBA_STORE(b[54]);
+
+   /* output 55 */
+   CARRY_FORWARD;
+   SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB;
+   COMBA_STORE(b[55]);
+
+   /* output 56 */
+   CARRY_FORWARD;
+   SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]);
+   COMBA_STORE(b[56]);
+
+   /* output 57 */
+   CARRY_FORWARD;
+   SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB;
+   COMBA_STORE(b[57]);
+
+   /* output 58 */
+   CARRY_FORWARD;
+   SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]);
+   COMBA_STORE(b[58]);
+
+   /* output 59 */
+   CARRY_FORWARD;
+   SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]);
+   COMBA_STORE(b[59]);
+
+   /* output 60 */
+   CARRY_FORWARD;
+   SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]);
+   COMBA_STORE(b[60]);
+
+   /* output 61 */
+   CARRY_FORWARD;
+   SQRADD2(a[30], a[31]);
+   COMBA_STORE(b[61]);
+
+   /* output 62 */
+   CARRY_FORWARD;
+   SQRADD(a[31], a[31]);
+   COMBA_STORE(b[62]);
+   COMBA_STORE2(b[63]);
+   COMBA_FINI;
+
+   B->used = 64;
+   B->sign = FP_ZPOS;
+   memcpy(B->dp, b, 64 * sizeof(fp_digit));
+   fp_clamp(B);
+}
+
+
+#endif
+
+#ifdef TFM_HUGE
+void fp_sqr_comba64(fp_int *A, fp_int *B)
+{
+   fp_digit *a, b[128], c0, c1, c2, sc0, sc1, sc2;
+
+   a = A->dp;
+   COMBA_START;
+
+   /* clear carries */
+   CLEAR_CARRY;
+
+   /* output 0 */
+   SQRADD(a[0],a[0]);
+   COMBA_STORE(b[0]);
+
+   /* output 1 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[1]);
+   COMBA_STORE(b[1]);
+
+   /* output 2 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]);
+   COMBA_STORE(b[2]);
+
+   /* output 3 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]);
+   COMBA_STORE(b[3]);
+
+   /* output 4 */
+   CARRY_FORWARD;
+   SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]);
+   COMBA_STORE(b[4]);
+
+   /* output 5 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB;
+   COMBA_STORE(b[5]);
+
+   /* output 6 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]);
+   COMBA_STORE(b[6]);
+
+   /* output 7 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB;
+   COMBA_STORE(b[7]);
+
+   /* output 8 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]);
+   COMBA_STORE(b[8]);
+
+   /* output 9 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB;
+   COMBA_STORE(b[9]);
+
+   /* output 10 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]);
+   COMBA_STORE(b[10]);
+
+   /* output 11 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB;
+   COMBA_STORE(b[11]);
+
+   /* output 12 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]);
+   COMBA_STORE(b[12]);
+
+   /* output 13 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB;
+   COMBA_STORE(b[13]);
+
+   /* output 14 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]);
+   COMBA_STORE(b[14]);
+
+   /* output 15 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB;
+   COMBA_STORE(b[15]);
+
+   /* output 16 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]);
+   COMBA_STORE(b[16]);
+
+   /* output 17 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB;
+   COMBA_STORE(b[17]);
+
+   /* output 18 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]);
+   COMBA_STORE(b[18]);
+
+   /* output 19 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB;
+   COMBA_STORE(b[19]);
+
+   /* output 20 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]);
+   COMBA_STORE(b[20]);
+
+   /* output 21 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB;
+   COMBA_STORE(b[21]);
+
+   /* output 22 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]);
+   COMBA_STORE(b[22]);
+
+   /* output 23 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB;
+   COMBA_STORE(b[23]);
+
+   /* output 24 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]);
+   COMBA_STORE(b[24]);
+
+   /* output 25 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB;
+   COMBA_STORE(b[25]);
+
+   /* output 26 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]);
+   COMBA_STORE(b[26]);
+
+   /* output 27 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB;
+   COMBA_STORE(b[27]);
+
+   /* output 28 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]);
+   COMBA_STORE(b[28]);
+
+   /* output 29 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB;
+   COMBA_STORE(b[29]);
+
+   /* output 30 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]);
+   COMBA_STORE(b[30]);
+
+   /* output 31 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB;
+   COMBA_STORE(b[31]);
+
+   /* output 32 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[32]); SQRADDAC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]);
+   COMBA_STORE(b[32]);
+
+   /* output 33 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[33]); SQRADDAC(a[1], a[32]); SQRADDAC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB;
+   COMBA_STORE(b[33]);
+
+   /* output 34 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[34]); SQRADDAC(a[1], a[33]); SQRADDAC(a[2], a[32]); SQRADDAC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]);
+   COMBA_STORE(b[34]);
+
+   /* output 35 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[35]); SQRADDAC(a[1], a[34]); SQRADDAC(a[2], a[33]); SQRADDAC(a[3], a[32]); SQRADDAC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB;
+   COMBA_STORE(b[35]);
+
+   /* output 36 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[36]); SQRADDAC(a[1], a[35]); SQRADDAC(a[2], a[34]); SQRADDAC(a[3], a[33]); SQRADDAC(a[4], a[32]); SQRADDAC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]);
+   COMBA_STORE(b[36]);
+
+   /* output 37 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[37]); SQRADDAC(a[1], a[36]); SQRADDAC(a[2], a[35]); SQRADDAC(a[3], a[34]); SQRADDAC(a[4], a[33]); SQRADDAC(a[5], a[32]); SQRADDAC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB;
+   COMBA_STORE(b[37]);
+
+   /* output 38 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[38]); SQRADDAC(a[1], a[37]); SQRADDAC(a[2], a[36]); SQRADDAC(a[3], a[35]); SQRADDAC(a[4], a[34]); SQRADDAC(a[5], a[33]); SQRADDAC(a[6], a[32]); SQRADDAC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]);
+   COMBA_STORE(b[38]);
+
+   /* output 39 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[39]); SQRADDAC(a[1], a[38]); SQRADDAC(a[2], a[37]); SQRADDAC(a[3], a[36]); SQRADDAC(a[4], a[35]); SQRADDAC(a[5], a[34]); SQRADDAC(a[6], a[33]); SQRADDAC(a[7], a[32]); SQRADDAC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB;
+   COMBA_STORE(b[39]);
+
+   /* output 40 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[40]); SQRADDAC(a[1], a[39]); SQRADDAC(a[2], a[38]); SQRADDAC(a[3], a[37]); SQRADDAC(a[4], a[36]); SQRADDAC(a[5], a[35]); SQRADDAC(a[6], a[34]); SQRADDAC(a[7], a[33]); SQRADDAC(a[8], a[32]); SQRADDAC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]);
+   COMBA_STORE(b[40]);
+
+   /* output 41 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[41]); SQRADDAC(a[1], a[40]); SQRADDAC(a[2], a[39]); SQRADDAC(a[3], a[38]); SQRADDAC(a[4], a[37]); SQRADDAC(a[5], a[36]); SQRADDAC(a[6], a[35]); SQRADDAC(a[7], a[34]); SQRADDAC(a[8], a[33]); SQRADDAC(a[9], a[32]); SQRADDAC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB;
+   COMBA_STORE(b[41]);
+
+   /* output 42 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[42]); SQRADDAC(a[1], a[41]); SQRADDAC(a[2], a[40]); SQRADDAC(a[3], a[39]); SQRADDAC(a[4], a[38]); SQRADDAC(a[5], a[37]); SQRADDAC(a[6], a[36]); SQRADDAC(a[7], a[35]); SQRADDAC(a[8], a[34]); SQRADDAC(a[9], a[33]); SQRADDAC(a[10], a[32]); SQRADDAC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]);
+   COMBA_STORE(b[42]);
+
+   /* output 43 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[43]); SQRADDAC(a[1], a[42]); SQRADDAC(a[2], a[41]); SQRADDAC(a[3], a[40]); SQRADDAC(a[4], a[39]); SQRADDAC(a[5], a[38]); SQRADDAC(a[6], a[37]); SQRADDAC(a[7], a[36]); SQRADDAC(a[8], a[35]); SQRADDAC(a[9], a[34]); SQRADDAC(a[10], a[33]); SQRADDAC(a[11], a[32]); SQRADDAC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB;
+   COMBA_STORE(b[43]);
+
+   /* output 44 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[44]); SQRADDAC(a[1], a[43]); SQRADDAC(a[2], a[42]); SQRADDAC(a[3], a[41]); SQRADDAC(a[4], a[40]); SQRADDAC(a[5], a[39]); SQRADDAC(a[6], a[38]); SQRADDAC(a[7], a[37]); SQRADDAC(a[8], a[36]); SQRADDAC(a[9], a[35]); SQRADDAC(a[10], a[34]); SQRADDAC(a[11], a[33]); SQRADDAC(a[12], a[32]); SQRADDAC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]);
+   COMBA_STORE(b[44]);
+
+   /* output 45 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[45]); SQRADDAC(a[1], a[44]); SQRADDAC(a[2], a[43]); SQRADDAC(a[3], a[42]); SQRADDAC(a[4], a[41]); SQRADDAC(a[5], a[40]); SQRADDAC(a[6], a[39]); SQRADDAC(a[7], a[38]); SQRADDAC(a[8], a[37]); SQRADDAC(a[9], a[36]); SQRADDAC(a[10], a[35]); SQRADDAC(a[11], a[34]); SQRADDAC(a[12], a[33]); SQRADDAC(a[13], a[32]); SQRADDAC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB;
+   COMBA_STORE(b[45]);
+
+   /* output 46 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[46]); SQRADDAC(a[1], a[45]); SQRADDAC(a[2], a[44]); SQRADDAC(a[3], a[43]); SQRADDAC(a[4], a[42]); SQRADDAC(a[5], a[41]); SQRADDAC(a[6], a[40]); SQRADDAC(a[7], a[39]); SQRADDAC(a[8], a[38]); SQRADDAC(a[9], a[37]); SQRADDAC(a[10], a[36]); SQRADDAC(a[11], a[35]); SQRADDAC(a[12], a[34]); SQRADDAC(a[13], a[33]); SQRADDAC(a[14], a[32]); SQRADDAC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]);
+   COMBA_STORE(b[46]);
+
+   /* output 47 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[47]); SQRADDAC(a[1], a[46]); SQRADDAC(a[2], a[45]); SQRADDAC(a[3], a[44]); SQRADDAC(a[4], a[43]); SQRADDAC(a[5], a[42]); SQRADDAC(a[6], a[41]); SQRADDAC(a[7], a[40]); SQRADDAC(a[8], a[39]); SQRADDAC(a[9], a[38]); SQRADDAC(a[10], a[37]); SQRADDAC(a[11], a[36]); SQRADDAC(a[12], a[35]); SQRADDAC(a[13], a[34]); SQRADDAC(a[14], a[33]); SQRADDAC(a[15], a[32]); SQRADDAC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB;
+   COMBA_STORE(b[47]);
+
+   /* output 48 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[48]); SQRADDAC(a[1], a[47]); SQRADDAC(a[2], a[46]); SQRADDAC(a[3], a[45]); SQRADDAC(a[4], a[44]); SQRADDAC(a[5], a[43]); SQRADDAC(a[6], a[42]); SQRADDAC(a[7], a[41]); SQRADDAC(a[8], a[40]); SQRADDAC(a[9], a[39]); SQRADDAC(a[10], a[38]); SQRADDAC(a[11], a[37]); SQRADDAC(a[12], a[36]); SQRADDAC(a[13], a[35]); SQRADDAC(a[14], a[34]); SQRADDAC(a[15], a[33]); SQRADDAC(a[16], a[32]); SQRADDAC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]);
+   COMBA_STORE(b[48]);
+
+   /* output 49 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[49]); SQRADDAC(a[1], a[48]); SQRADDAC(a[2], a[47]); SQRADDAC(a[3], a[46]); SQRADDAC(a[4], a[45]); SQRADDAC(a[5], a[44]); SQRADDAC(a[6], a[43]); SQRADDAC(a[7], a[42]); SQRADDAC(a[8], a[41]); SQRADDAC(a[9], a[40]); SQRADDAC(a[10], a[39]); SQRADDAC(a[11], a[38]); SQRADDAC(a[12], a[37]); SQRADDAC(a[13], a[36]); SQRADDAC(a[14], a[35]); SQRADDAC(a[15], a[34]); SQRADDAC(a[16], a[33]); SQRADDAC(a[17], a[32]); SQRADDAC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB;
+   COMBA_STORE(b[49]);
+
+   /* output 50 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[50]); SQRADDAC(a[1], a[49]); SQRADDAC(a[2], a[48]); SQRADDAC(a[3], a[47]); SQRADDAC(a[4], a[46]); SQRADDAC(a[5], a[45]); SQRADDAC(a[6], a[44]); SQRADDAC(a[7], a[43]); SQRADDAC(a[8], a[42]); SQRADDAC(a[9], a[41]); SQRADDAC(a[10], a[40]); SQRADDAC(a[11], a[39]); SQRADDAC(a[12], a[38]); SQRADDAC(a[13], a[37]); SQRADDAC(a[14], a[36]); SQRADDAC(a[15], a[35]); SQRADDAC(a[16], a[34]); SQRADDAC(a[17], a[33]); SQRADDAC(a[18], a[32]); SQRADDAC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]);
+   COMBA_STORE(b[50]);
+
+   /* output 51 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[51]); SQRADDAC(a[1], a[50]); SQRADDAC(a[2], a[49]); SQRADDAC(a[3], a[48]); SQRADDAC(a[4], a[47]); SQRADDAC(a[5], a[46]); SQRADDAC(a[6], a[45]); SQRADDAC(a[7], a[44]); SQRADDAC(a[8], a[43]); SQRADDAC(a[9], a[42]); SQRADDAC(a[10], a[41]); SQRADDAC(a[11], a[40]); SQRADDAC(a[12], a[39]); SQRADDAC(a[13], a[38]); SQRADDAC(a[14], a[37]); SQRADDAC(a[15], a[36]); SQRADDAC(a[16], a[35]); SQRADDAC(a[17], a[34]); SQRADDAC(a[18], a[33]); SQRADDAC(a[19], a[32]); SQRADDAC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB;
+   COMBA_STORE(b[51]);
+
+   /* output 52 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[52]); SQRADDAC(a[1], a[51]); SQRADDAC(a[2], a[50]); SQRADDAC(a[3], a[49]); SQRADDAC(a[4], a[48]); SQRADDAC(a[5], a[47]); SQRADDAC(a[6], a[46]); SQRADDAC(a[7], a[45]); SQRADDAC(a[8], a[44]); SQRADDAC(a[9], a[43]); SQRADDAC(a[10], a[42]); SQRADDAC(a[11], a[41]); SQRADDAC(a[12], a[40]); SQRADDAC(a[13], a[39]); SQRADDAC(a[14], a[38]); SQRADDAC(a[15], a[37]); SQRADDAC(a[16], a[36]); SQRADDAC(a[17], a[35]); SQRADDAC(a[18], a[34]); SQRADDAC(a[19], a[33]); SQRADDAC(a[20], a[32]); SQRADDAC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]);
+   COMBA_STORE(b[52]);
+
+   /* output 53 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[53]); SQRADDAC(a[1], a[52]); SQRADDAC(a[2], a[51]); SQRADDAC(a[3], a[50]); SQRADDAC(a[4], a[49]); SQRADDAC(a[5], a[48]); SQRADDAC(a[6], a[47]); SQRADDAC(a[7], a[46]); SQRADDAC(a[8], a[45]); SQRADDAC(a[9], a[44]); SQRADDAC(a[10], a[43]); SQRADDAC(a[11], a[42]); SQRADDAC(a[12], a[41]); SQRADDAC(a[13], a[40]); SQRADDAC(a[14], a[39]); SQRADDAC(a[15], a[38]); SQRADDAC(a[16], a[37]); SQRADDAC(a[17], a[36]); SQRADDAC(a[18], a[35]); SQRADDAC(a[19], a[34]); SQRADDAC(a[20], a[33]); SQRADDAC(a[21], a[32]); SQRADDAC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB;
+   COMBA_STORE(b[53]);
+
+   /* output 54 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[54]); SQRADDAC(a[1], a[53]); SQRADDAC(a[2], a[52]); SQRADDAC(a[3], a[51]); SQRADDAC(a[4], a[50]); SQRADDAC(a[5], a[49]); SQRADDAC(a[6], a[48]); SQRADDAC(a[7], a[47]); SQRADDAC(a[8], a[46]); SQRADDAC(a[9], a[45]); SQRADDAC(a[10], a[44]); SQRADDAC(a[11], a[43]); SQRADDAC(a[12], a[42]); SQRADDAC(a[13], a[41]); SQRADDAC(a[14], a[40]); SQRADDAC(a[15], a[39]); SQRADDAC(a[16], a[38]); SQRADDAC(a[17], a[37]); SQRADDAC(a[18], a[36]); SQRADDAC(a[19], a[35]); SQRADDAC(a[20], a[34]); SQRADDAC(a[21], a[33]); SQRADDAC(a[22], a[32]); SQRADDAC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]);
+   COMBA_STORE(b[54]);
+
+   /* output 55 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[55]); SQRADDAC(a[1], a[54]); SQRADDAC(a[2], a[53]); SQRADDAC(a[3], a[52]); SQRADDAC(a[4], a[51]); SQRADDAC(a[5], a[50]); SQRADDAC(a[6], a[49]); SQRADDAC(a[7], a[48]); SQRADDAC(a[8], a[47]); SQRADDAC(a[9], a[46]); SQRADDAC(a[10], a[45]); SQRADDAC(a[11], a[44]); SQRADDAC(a[12], a[43]); SQRADDAC(a[13], a[42]); SQRADDAC(a[14], a[41]); SQRADDAC(a[15], a[40]); SQRADDAC(a[16], a[39]); SQRADDAC(a[17], a[38]); SQRADDAC(a[18], a[37]); SQRADDAC(a[19], a[36]); SQRADDAC(a[20], a[35]); SQRADDAC(a[21], a[34]); SQRADDAC(a[22], a[33]); SQRADDAC(a[23], a[32]); SQRADDAC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB;
+   COMBA_STORE(b[55]);
+
+   /* output 56 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[56]); SQRADDAC(a[1], a[55]); SQRADDAC(a[2], a[54]); SQRADDAC(a[3], a[53]); SQRADDAC(a[4], a[52]); SQRADDAC(a[5], a[51]); SQRADDAC(a[6], a[50]); SQRADDAC(a[7], a[49]); SQRADDAC(a[8], a[48]); SQRADDAC(a[9], a[47]); SQRADDAC(a[10], a[46]); SQRADDAC(a[11], a[45]); SQRADDAC(a[12], a[44]); SQRADDAC(a[13], a[43]); SQRADDAC(a[14], a[42]); SQRADDAC(a[15], a[41]); SQRADDAC(a[16], a[40]); SQRADDAC(a[17], a[39]); SQRADDAC(a[18], a[38]); SQRADDAC(a[19], a[37]); SQRADDAC(a[20], a[36]); SQRADDAC(a[21], a[35]); SQRADDAC(a[22], a[34]); SQRADDAC(a[23], a[33]); SQRADDAC(a[24], a[32]); SQRADDAC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]);
+   COMBA_STORE(b[56]);
+
+   /* output 57 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[57]); SQRADDAC(a[1], a[56]); SQRADDAC(a[2], a[55]); SQRADDAC(a[3], a[54]); SQRADDAC(a[4], a[53]); SQRADDAC(a[5], a[52]); SQRADDAC(a[6], a[51]); SQRADDAC(a[7], a[50]); SQRADDAC(a[8], a[49]); SQRADDAC(a[9], a[48]); SQRADDAC(a[10], a[47]); SQRADDAC(a[11], a[46]); SQRADDAC(a[12], a[45]); SQRADDAC(a[13], a[44]); SQRADDAC(a[14], a[43]); SQRADDAC(a[15], a[42]); SQRADDAC(a[16], a[41]); SQRADDAC(a[17], a[40]); SQRADDAC(a[18], a[39]); SQRADDAC(a[19], a[38]); SQRADDAC(a[20], a[37]); SQRADDAC(a[21], a[36]); SQRADDAC(a[22], a[35]); SQRADDAC(a[23], a[34]); SQRADDAC(a[24], a[33]); SQRADDAC(a[25], a[32]); SQRADDAC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB;
+   COMBA_STORE(b[57]);
+
+   /* output 58 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[58]); SQRADDAC(a[1], a[57]); SQRADDAC(a[2], a[56]); SQRADDAC(a[3], a[55]); SQRADDAC(a[4], a[54]); SQRADDAC(a[5], a[53]); SQRADDAC(a[6], a[52]); SQRADDAC(a[7], a[51]); SQRADDAC(a[8], a[50]); SQRADDAC(a[9], a[49]); SQRADDAC(a[10], a[48]); SQRADDAC(a[11], a[47]); SQRADDAC(a[12], a[46]); SQRADDAC(a[13], a[45]); SQRADDAC(a[14], a[44]); SQRADDAC(a[15], a[43]); SQRADDAC(a[16], a[42]); SQRADDAC(a[17], a[41]); SQRADDAC(a[18], a[40]); SQRADDAC(a[19], a[39]); SQRADDAC(a[20], a[38]); SQRADDAC(a[21], a[37]); SQRADDAC(a[22], a[36]); SQRADDAC(a[23], a[35]); SQRADDAC(a[24], a[34]); SQRADDAC(a[25], a[33]); SQRADDAC(a[26], a[32]); SQRADDAC(a[27], a[31]); SQRADDAC(a[28], a[30]); SQRADDDB; SQRADD(a[29], a[29]);
+   COMBA_STORE(b[58]);
+
+   /* output 59 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[59]); SQRADDAC(a[1], a[58]); SQRADDAC(a[2], a[57]); SQRADDAC(a[3], a[56]); SQRADDAC(a[4], a[55]); SQRADDAC(a[5], a[54]); SQRADDAC(a[6], a[53]); SQRADDAC(a[7], a[52]); SQRADDAC(a[8], a[51]); SQRADDAC(a[9], a[50]); SQRADDAC(a[10], a[49]); SQRADDAC(a[11], a[48]); SQRADDAC(a[12], a[47]); SQRADDAC(a[13], a[46]); SQRADDAC(a[14], a[45]); SQRADDAC(a[15], a[44]); SQRADDAC(a[16], a[43]); SQRADDAC(a[17], a[42]); SQRADDAC(a[18], a[41]); SQRADDAC(a[19], a[40]); SQRADDAC(a[20], a[39]); SQRADDAC(a[21], a[38]); SQRADDAC(a[22], a[37]); SQRADDAC(a[23], a[36]); SQRADDAC(a[24], a[35]); SQRADDAC(a[25], a[34]); SQRADDAC(a[26], a[33]); SQRADDAC(a[27], a[32]); SQRADDAC(a[28], a[31]); SQRADDAC(a[29], a[30]); SQRADDDB;
+   COMBA_STORE(b[59]);
+
+   /* output 60 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[60]); SQRADDAC(a[1], a[59]); SQRADDAC(a[2], a[58]); SQRADDAC(a[3], a[57]); SQRADDAC(a[4], a[56]); SQRADDAC(a[5], a[55]); SQRADDAC(a[6], a[54]); SQRADDAC(a[7], a[53]); SQRADDAC(a[8], a[52]); SQRADDAC(a[9], a[51]); SQRADDAC(a[10], a[50]); SQRADDAC(a[11], a[49]); SQRADDAC(a[12], a[48]); SQRADDAC(a[13], a[47]); SQRADDAC(a[14], a[46]); SQRADDAC(a[15], a[45]); SQRADDAC(a[16], a[44]); SQRADDAC(a[17], a[43]); SQRADDAC(a[18], a[42]); SQRADDAC(a[19], a[41]); SQRADDAC(a[20], a[40]); SQRADDAC(a[21], a[39]); SQRADDAC(a[22], a[38]); SQRADDAC(a[23], a[37]); SQRADDAC(a[24], a[36]); SQRADDAC(a[25], a[35]); SQRADDAC(a[26], a[34]); SQRADDAC(a[27], a[33]); SQRADDAC(a[28], a[32]); SQRADDAC(a[29], a[31]); SQRADDDB; SQRADD(a[30], a[30]);
+   COMBA_STORE(b[60]);
+
+   /* output 61 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[61]); SQRADDAC(a[1], a[60]); SQRADDAC(a[2], a[59]); SQRADDAC(a[3], a[58]); SQRADDAC(a[4], a[57]); SQRADDAC(a[5], a[56]); SQRADDAC(a[6], a[55]); SQRADDAC(a[7], a[54]); SQRADDAC(a[8], a[53]); SQRADDAC(a[9], a[52]); SQRADDAC(a[10], a[51]); SQRADDAC(a[11], a[50]); SQRADDAC(a[12], a[49]); SQRADDAC(a[13], a[48]); SQRADDAC(a[14], a[47]); SQRADDAC(a[15], a[46]); SQRADDAC(a[16], a[45]); SQRADDAC(a[17], a[44]); SQRADDAC(a[18], a[43]); SQRADDAC(a[19], a[42]); SQRADDAC(a[20], a[41]); SQRADDAC(a[21], a[40]); SQRADDAC(a[22], a[39]); SQRADDAC(a[23], a[38]); SQRADDAC(a[24], a[37]); SQRADDAC(a[25], a[36]); SQRADDAC(a[26], a[35]); SQRADDAC(a[27], a[34]); SQRADDAC(a[28], a[33]); SQRADDAC(a[29], a[32]); SQRADDAC(a[30], a[31]); SQRADDDB;
+   COMBA_STORE(b[61]);
+
+   /* output 62 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[62]); SQRADDAC(a[1], a[61]); SQRADDAC(a[2], a[60]); SQRADDAC(a[3], a[59]); SQRADDAC(a[4], a[58]); SQRADDAC(a[5], a[57]); SQRADDAC(a[6], a[56]); SQRADDAC(a[7], a[55]); SQRADDAC(a[8], a[54]); SQRADDAC(a[9], a[53]); SQRADDAC(a[10], a[52]); SQRADDAC(a[11], a[51]); SQRADDAC(a[12], a[50]); SQRADDAC(a[13], a[49]); SQRADDAC(a[14], a[48]); SQRADDAC(a[15], a[47]); SQRADDAC(a[16], a[46]); SQRADDAC(a[17], a[45]); SQRADDAC(a[18], a[44]); SQRADDAC(a[19], a[43]); SQRADDAC(a[20], a[42]); SQRADDAC(a[21], a[41]); SQRADDAC(a[22], a[40]); SQRADDAC(a[23], a[39]); SQRADDAC(a[24], a[38]); SQRADDAC(a[25], a[37]); SQRADDAC(a[26], a[36]); SQRADDAC(a[27], a[35]); SQRADDAC(a[28], a[34]); SQRADDAC(a[29], a[33]); SQRADDAC(a[30], a[32]); SQRADDDB; SQRADD(a[31], a[31]);
+   COMBA_STORE(b[62]);
+
+   /* output 63 */
+   CARRY_FORWARD;
+   SQRADDSC(a[0], a[63]); SQRADDAC(a[1], a[62]); SQRADDAC(a[2], a[61]); SQRADDAC(a[3], a[60]); SQRADDAC(a[4], a[59]); SQRADDAC(a[5], a[58]); SQRADDAC(a[6], a[57]); SQRADDAC(a[7], a[56]); SQRADDAC(a[8], a[55]); SQRADDAC(a[9], a[54]); SQRADDAC(a[10], a[53]); SQRADDAC(a[11], a[52]); SQRADDAC(a[12], a[51]); SQRADDAC(a[13], a[50]); SQRADDAC(a[14], a[49]); SQRADDAC(a[15], a[48]); SQRADDAC(a[16], a[47]); SQRADDAC(a[17], a[46]); SQRADDAC(a[18], a[45]); SQRADDAC(a[19], a[44]); SQRADDAC(a[20], a[43]); SQRADDAC(a[21], a[42]); SQRADDAC(a[22], a[41]); SQRADDAC(a[23], a[40]); SQRADDAC(a[24], a[39]); SQRADDAC(a[25], a[38]); SQRADDAC(a[26], a[37]); SQRADDAC(a[27], a[36]); SQRADDAC(a[28], a[35]); SQRADDAC(a[29], a[34]); SQRADDAC(a[30], a[33]); SQRADDAC(a[31], a[32]); SQRADDDB;
+   COMBA_STORE(b[63]);
+
+   /* output 64 */
+   CARRY_FORWARD;
+   SQRADDSC(a[1], a[63]); SQRADDAC(a[2], a[62]); SQRADDAC(a[3], a[61]); SQRADDAC(a[4], a[60]); SQRADDAC(a[5], a[59]); SQRADDAC(a[6], a[58]); SQRADDAC(a[7], a[57]); SQRADDAC(a[8], a[56]); SQRADDAC(a[9], a[55]); SQRADDAC(a[10], a[54]); SQRADDAC(a[11], a[53]); SQRADDAC(a[12], a[52]); SQRADDAC(a[13], a[51]); SQRADDAC(a[14], a[50]); SQRADDAC(a[15], a[49]); SQRADDAC(a[16], a[48]); SQRADDAC(a[17], a[47]); SQRADDAC(a[18], a[46]); SQRADDAC(a[19], a[45]); SQRADDAC(a[20], a[44]); SQRADDAC(a[21], a[43]); SQRADDAC(a[22], a[42]); SQRADDAC(a[23], a[41]); SQRADDAC(a[24], a[40]); SQRADDAC(a[25], a[39]); SQRADDAC(a[26], a[38]); SQRADDAC(a[27], a[37]); SQRADDAC(a[28], a[36]); SQRADDAC(a[29], a[35]); SQRADDAC(a[30], a[34]); SQRADDAC(a[31], a[33]); SQRADDDB; SQRADD(a[32], a[32]);
+   COMBA_STORE(b[64]);
+
+   /* output 65 */
+   CARRY_FORWARD;
+   SQRADDSC(a[2], a[63]); SQRADDAC(a[3], a[62]); SQRADDAC(a[4], a[61]); SQRADDAC(a[5], a[60]); SQRADDAC(a[6], a[59]); SQRADDAC(a[7], a[58]); SQRADDAC(a[8], a[57]); SQRADDAC(a[9], a[56]); SQRADDAC(a[10], a[55]); SQRADDAC(a[11], a[54]); SQRADDAC(a[12], a[53]); SQRADDAC(a[13], a[52]); SQRADDAC(a[14], a[51]); SQRADDAC(a[15], a[50]); SQRADDAC(a[16], a[49]); SQRADDAC(a[17], a[48]); SQRADDAC(a[18], a[47]); SQRADDAC(a[19], a[46]); SQRADDAC(a[20], a[45]); SQRADDAC(a[21], a[44]); SQRADDAC(a[22], a[43]); SQRADDAC(a[23], a[42]); SQRADDAC(a[24], a[41]); SQRADDAC(a[25], a[40]); SQRADDAC(a[26], a[39]); SQRADDAC(a[27], a[38]); SQRADDAC(a[28], a[37]); SQRADDAC(a[29], a[36]); SQRADDAC(a[30], a[35]); SQRADDAC(a[31], a[34]); SQRADDAC(a[32], a[33]); SQRADDDB;
+   COMBA_STORE(b[65]);
+
+   /* output 66 */
+   CARRY_FORWARD;
+   SQRADDSC(a[3], a[63]); SQRADDAC(a[4], a[62]); SQRADDAC(a[5], a[61]); SQRADDAC(a[6], a[60]); SQRADDAC(a[7], a[59]); SQRADDAC(a[8], a[58]); SQRADDAC(a[9], a[57]); SQRADDAC(a[10], a[56]); SQRADDAC(a[11], a[55]); SQRADDAC(a[12], a[54]); SQRADDAC(a[13], a[53]); SQRADDAC(a[14], a[52]); SQRADDAC(a[15], a[51]); SQRADDAC(a[16], a[50]); SQRADDAC(a[17], a[49]); SQRADDAC(a[18], a[48]); SQRADDAC(a[19], a[47]); SQRADDAC(a[20], a[46]); SQRADDAC(a[21], a[45]); SQRADDAC(a[22], a[44]); SQRADDAC(a[23], a[43]); SQRADDAC(a[24], a[42]); SQRADDAC(a[25], a[41]); SQRADDAC(a[26], a[40]); SQRADDAC(a[27], a[39]); SQRADDAC(a[28], a[38]); SQRADDAC(a[29], a[37]); SQRADDAC(a[30], a[36]); SQRADDAC(a[31], a[35]); SQRADDAC(a[32], a[34]); SQRADDDB; SQRADD(a[33], a[33]);
+   COMBA_STORE(b[66]);
+
+   /* output 67 */
+   CARRY_FORWARD;
+   SQRADDSC(a[4], a[63]); SQRADDAC(a[5], a[62]); SQRADDAC(a[6], a[61]); SQRADDAC(a[7], a[60]); SQRADDAC(a[8], a[59]); SQRADDAC(a[9], a[58]); SQRADDAC(a[10], a[57]); SQRADDAC(a[11], a[56]); SQRADDAC(a[12], a[55]); SQRADDAC(a[13], a[54]); SQRADDAC(a[14], a[53]); SQRADDAC(a[15], a[52]); SQRADDAC(a[16], a[51]); SQRADDAC(a[17], a[50]); SQRADDAC(a[18], a[49]); SQRADDAC(a[19], a[48]); SQRADDAC(a[20], a[47]); SQRADDAC(a[21], a[46]); SQRADDAC(a[22], a[45]); SQRADDAC(a[23], a[44]); SQRADDAC(a[24], a[43]); SQRADDAC(a[25], a[42]); SQRADDAC(a[26], a[41]); SQRADDAC(a[27], a[40]); SQRADDAC(a[28], a[39]); SQRADDAC(a[29], a[38]); SQRADDAC(a[30], a[37]); SQRADDAC(a[31], a[36]); SQRADDAC(a[32], a[35]); SQRADDAC(a[33], a[34]); SQRADDDB;
+   COMBA_STORE(b[67]);
+
+   /* output 68 */
+   CARRY_FORWARD;
+   SQRADDSC(a[5], a[63]); SQRADDAC(a[6], a[62]); SQRADDAC(a[7], a[61]); SQRADDAC(a[8], a[60]); SQRADDAC(a[9], a[59]); SQRADDAC(a[10], a[58]); SQRADDAC(a[11], a[57]); SQRADDAC(a[12], a[56]); SQRADDAC(a[13], a[55]); SQRADDAC(a[14], a[54]); SQRADDAC(a[15], a[53]); SQRADDAC(a[16], a[52]); SQRADDAC(a[17], a[51]); SQRADDAC(a[18], a[50]); SQRADDAC(a[19], a[49]); SQRADDAC(a[20], a[48]); SQRADDAC(a[21], a[47]); SQRADDAC(a[22], a[46]); SQRADDAC(a[23], a[45]); SQRADDAC(a[24], a[44]); SQRADDAC(a[25], a[43]); SQRADDAC(a[26], a[42]); SQRADDAC(a[27], a[41]); SQRADDAC(a[28], a[40]); SQRADDAC(a[29], a[39]); SQRADDAC(a[30], a[38]); SQRADDAC(a[31], a[37]); SQRADDAC(a[32], a[36]); SQRADDAC(a[33], a[35]); SQRADDDB; SQRADD(a[34], a[34]);
+   COMBA_STORE(b[68]);
+
+   /* output 69 */
+   CARRY_FORWARD;
+   SQRADDSC(a[6], a[63]); SQRADDAC(a[7], a[62]); SQRADDAC(a[8], a[61]); SQRADDAC(a[9], a[60]); SQRADDAC(a[10], a[59]); SQRADDAC(a[11], a[58]); SQRADDAC(a[12], a[57]); SQRADDAC(a[13], a[56]); SQRADDAC(a[14], a[55]); SQRADDAC(a[15], a[54]); SQRADDAC(a[16], a[53]); SQRADDAC(a[17], a[52]); SQRADDAC(a[18], a[51]); SQRADDAC(a[19], a[50]); SQRADDAC(a[20], a[49]); SQRADDAC(a[21], a[48]); SQRADDAC(a[22], a[47]); SQRADDAC(a[23], a[46]); SQRADDAC(a[24], a[45]); SQRADDAC(a[25], a[44]); SQRADDAC(a[26], a[43]); SQRADDAC(a[27], a[42]); SQRADDAC(a[28], a[41]); SQRADDAC(a[29], a[40]); SQRADDAC(a[30], a[39]); SQRADDAC(a[31], a[38]); SQRADDAC(a[32], a[37]); SQRADDAC(a[33], a[36]); SQRADDAC(a[34], a[35]); SQRADDDB;
+   COMBA_STORE(b[69]);
+
+   /* output 70 */
+   CARRY_FORWARD;
+   SQRADDSC(a[7], a[63]); SQRADDAC(a[8], a[62]); SQRADDAC(a[9], a[61]); SQRADDAC(a[10], a[60]); SQRADDAC(a[11], a[59]); SQRADDAC(a[12], a[58]); SQRADDAC(a[13], a[57]); SQRADDAC(a[14], a[56]); SQRADDAC(a[15], a[55]); SQRADDAC(a[16], a[54]); SQRADDAC(a[17], a[53]); SQRADDAC(a[18], a[52]); SQRADDAC(a[19], a[51]); SQRADDAC(a[20], a[50]); SQRADDAC(a[21], a[49]); SQRADDAC(a[22], a[48]); SQRADDAC(a[23], a[47]); SQRADDAC(a[24], a[46]); SQRADDAC(a[25], a[45]); SQRADDAC(a[26], a[44]); SQRADDAC(a[27], a[43]); SQRADDAC(a[28], a[42]); SQRADDAC(a[29], a[41]); SQRADDAC(a[30], a[40]); SQRADDAC(a[31], a[39]); SQRADDAC(a[32], a[38]); SQRADDAC(a[33], a[37]); SQRADDAC(a[34], a[36]); SQRADDDB; SQRADD(a[35], a[35]);
+   COMBA_STORE(b[70]);
+
+   /* output 71 */
+   CARRY_FORWARD;
+   SQRADDSC(a[8], a[63]); SQRADDAC(a[9], a[62]); SQRADDAC(a[10], a[61]); SQRADDAC(a[11], a[60]); SQRADDAC(a[12], a[59]); SQRADDAC(a[13], a[58]); SQRADDAC(a[14], a[57]); SQRADDAC(a[15], a[56]); SQRADDAC(a[16], a[55]); SQRADDAC(a[17], a[54]); SQRADDAC(a[18], a[53]); SQRADDAC(a[19], a[52]); SQRADDAC(a[20], a[51]); SQRADDAC(a[21], a[50]); SQRADDAC(a[22], a[49]); SQRADDAC(a[23], a[48]); SQRADDAC(a[24], a[47]); SQRADDAC(a[25], a[46]); SQRADDAC(a[26], a[45]); SQRADDAC(a[27], a[44]); SQRADDAC(a[28], a[43]); SQRADDAC(a[29], a[42]); SQRADDAC(a[30], a[41]); SQRADDAC(a[31], a[40]); SQRADDAC(a[32], a[39]); SQRADDAC(a[33], a[38]); SQRADDAC(a[34], a[37]); SQRADDAC(a[35], a[36]); SQRADDDB;
+   COMBA_STORE(b[71]);
+
+   /* output 72 */
+   CARRY_FORWARD;
+   SQRADDSC(a[9], a[63]); SQRADDAC(a[10], a[62]); SQRADDAC(a[11], a[61]); SQRADDAC(a[12], a[60]); SQRADDAC(a[13], a[59]); SQRADDAC(a[14], a[58]); SQRADDAC(a[15], a[57]); SQRADDAC(a[16], a[56]); SQRADDAC(a[17], a[55]); SQRADDAC(a[18], a[54]); SQRADDAC(a[19], a[53]); SQRADDAC(a[20], a[52]); SQRADDAC(a[21], a[51]); SQRADDAC(a[22], a[50]); SQRADDAC(a[23], a[49]); SQRADDAC(a[24], a[48]); SQRADDAC(a[25], a[47]); SQRADDAC(a[26], a[46]); SQRADDAC(a[27], a[45]); SQRADDAC(a[28], a[44]); SQRADDAC(a[29], a[43]); SQRADDAC(a[30], a[42]); SQRADDAC(a[31], a[41]); SQRADDAC(a[32], a[40]); SQRADDAC(a[33], a[39]); SQRADDAC(a[34], a[38]); SQRADDAC(a[35], a[37]); SQRADDDB; SQRADD(a[36], a[36]);
+   COMBA_STORE(b[72]);
+
+   /* output 73 */
+   CARRY_FORWARD;
+   SQRADDSC(a[10], a[63]); SQRADDAC(a[11], a[62]); SQRADDAC(a[12], a[61]); SQRADDAC(a[13], a[60]); SQRADDAC(a[14], a[59]); SQRADDAC(a[15], a[58]); SQRADDAC(a[16], a[57]); SQRADDAC(a[17], a[56]); SQRADDAC(a[18], a[55]); SQRADDAC(a[19], a[54]); SQRADDAC(a[20], a[53]); SQRADDAC(a[21], a[52]); SQRADDAC(a[22], a[51]); SQRADDAC(a[23], a[50]); SQRADDAC(a[24], a[49]); SQRADDAC(a[25], a[48]); SQRADDAC(a[26], a[47]); SQRADDAC(a[27], a[46]); SQRADDAC(a[28], a[45]); SQRADDAC(a[29], a[44]); SQRADDAC(a[30], a[43]); SQRADDAC(a[31], a[42]); SQRADDAC(a[32], a[41]); SQRADDAC(a[33], a[40]); SQRADDAC(a[34], a[39]); SQRADDAC(a[35], a[38]); SQRADDAC(a[36], a[37]); SQRADDDB;
+   COMBA_STORE(b[73]);
+
+   /* output 74 */
+   CARRY_FORWARD;
+   SQRADDSC(a[11], a[63]); SQRADDAC(a[12], a[62]); SQRADDAC(a[13], a[61]); SQRADDAC(a[14], a[60]); SQRADDAC(a[15], a[59]); SQRADDAC(a[16], a[58]); SQRADDAC(a[17], a[57]); SQRADDAC(a[18], a[56]); SQRADDAC(a[19], a[55]); SQRADDAC(a[20], a[54]); SQRADDAC(a[21], a[53]); SQRADDAC(a[22], a[52]); SQRADDAC(a[23], a[51]); SQRADDAC(a[24], a[50]); SQRADDAC(a[25], a[49]); SQRADDAC(a[26], a[48]); SQRADDAC(a[27], a[47]); SQRADDAC(a[28], a[46]); SQRADDAC(a[29], a[45]); SQRADDAC(a[30], a[44]); SQRADDAC(a[31], a[43]); SQRADDAC(a[32], a[42]); SQRADDAC(a[33], a[41]); SQRADDAC(a[34], a[40]); SQRADDAC(a[35], a[39]); SQRADDAC(a[36], a[38]); SQRADDDB; SQRADD(a[37], a[37]);
+   COMBA_STORE(b[74]);
+
+   /* output 75 */
+   CARRY_FORWARD;
+   SQRADDSC(a[12], a[63]); SQRADDAC(a[13], a[62]); SQRADDAC(a[14], a[61]); SQRADDAC(a[15], a[60]); SQRADDAC(a[16], a[59]); SQRADDAC(a[17], a[58]); SQRADDAC(a[18], a[57]); SQRADDAC(a[19], a[56]); SQRADDAC(a[20], a[55]); SQRADDAC(a[21], a[54]); SQRADDAC(a[22], a[53]); SQRADDAC(a[23], a[52]); SQRADDAC(a[24], a[51]); SQRADDAC(a[25], a[50]); SQRADDAC(a[26], a[49]); SQRADDAC(a[27], a[48]); SQRADDAC(a[28], a[47]); SQRADDAC(a[29], a[46]); SQRADDAC(a[30], a[45]); SQRADDAC(a[31], a[44]); SQRADDAC(a[32], a[43]); SQRADDAC(a[33], a[42]); SQRADDAC(a[34], a[41]); SQRADDAC(a[35], a[40]); SQRADDAC(a[36], a[39]); SQRADDAC(a[37], a[38]); SQRADDDB;
+   COMBA_STORE(b[75]);
+
+   /* output 76 */
+   CARRY_FORWARD;
+   SQRADDSC(a[13], a[63]); SQRADDAC(a[14], a[62]); SQRADDAC(a[15], a[61]); SQRADDAC(a[16], a[60]); SQRADDAC(a[17], a[59]); SQRADDAC(a[18], a[58]); SQRADDAC(a[19], a[57]); SQRADDAC(a[20], a[56]); SQRADDAC(a[21], a[55]); SQRADDAC(a[22], a[54]); SQRADDAC(a[23], a[53]); SQRADDAC(a[24], a[52]); SQRADDAC(a[25], a[51]); SQRADDAC(a[26], a[50]); SQRADDAC(a[27], a[49]); SQRADDAC(a[28], a[48]); SQRADDAC(a[29], a[47]); SQRADDAC(a[30], a[46]); SQRADDAC(a[31], a[45]); SQRADDAC(a[32], a[44]); SQRADDAC(a[33], a[43]); SQRADDAC(a[34], a[42]); SQRADDAC(a[35], a[41]); SQRADDAC(a[36], a[40]); SQRADDAC(a[37], a[39]); SQRADDDB; SQRADD(a[38], a[38]);
+   COMBA_STORE(b[76]);
+
+   /* output 77 */
+   CARRY_FORWARD;
+   SQRADDSC(a[14], a[63]); SQRADDAC(a[15], a[62]); SQRADDAC(a[16], a[61]); SQRADDAC(a[17], a[60]); SQRADDAC(a[18], a[59]); SQRADDAC(a[19], a[58]); SQRADDAC(a[20], a[57]); SQRADDAC(a[21], a[56]); SQRADDAC(a[22], a[55]); SQRADDAC(a[23], a[54]); SQRADDAC(a[24], a[53]); SQRADDAC(a[25], a[52]); SQRADDAC(a[26], a[51]); SQRADDAC(a[27], a[50]); SQRADDAC(a[28], a[49]); SQRADDAC(a[29], a[48]); SQRADDAC(a[30], a[47]); SQRADDAC(a[31], a[46]); SQRADDAC(a[32], a[45]); SQRADDAC(a[33], a[44]); SQRADDAC(a[34], a[43]); SQRADDAC(a[35], a[42]); SQRADDAC(a[36], a[41]); SQRADDAC(a[37], a[40]); SQRADDAC(a[38], a[39]); SQRADDDB;
+   COMBA_STORE(b[77]);
+
+   /* output 78 */
+   CARRY_FORWARD;
+   SQRADDSC(a[15], a[63]); SQRADDAC(a[16], a[62]); SQRADDAC(a[17], a[61]); SQRADDAC(a[18], a[60]); SQRADDAC(a[19], a[59]); SQRADDAC(a[20], a[58]); SQRADDAC(a[21], a[57]); SQRADDAC(a[22], a[56]); SQRADDAC(a[23], a[55]); SQRADDAC(a[24], a[54]); SQRADDAC(a[25], a[53]); SQRADDAC(a[26], a[52]); SQRADDAC(a[27], a[51]); SQRADDAC(a[28], a[50]); SQRADDAC(a[29], a[49]); SQRADDAC(a[30], a[48]); SQRADDAC(a[31], a[47]); SQRADDAC(a[32], a[46]); SQRADDAC(a[33], a[45]); SQRADDAC(a[34], a[44]); SQRADDAC(a[35], a[43]); SQRADDAC(a[36], a[42]); SQRADDAC(a[37], a[41]); SQRADDAC(a[38], a[40]); SQRADDDB; SQRADD(a[39], a[39]);
+   COMBA_STORE(b[78]);
+
+   /* output 79 */
+   CARRY_FORWARD;
+   SQRADDSC(a[16], a[63]); SQRADDAC(a[17], a[62]); SQRADDAC(a[18], a[61]); SQRADDAC(a[19], a[60]); SQRADDAC(a[20], a[59]); SQRADDAC(a[21], a[58]); SQRADDAC(a[22], a[57]); SQRADDAC(a[23], a[56]); SQRADDAC(a[24], a[55]); SQRADDAC(a[25], a[54]); SQRADDAC(a[26], a[53]); SQRADDAC(a[27], a[52]); SQRADDAC(a[28], a[51]); SQRADDAC(a[29], a[50]); SQRADDAC(a[30], a[49]); SQRADDAC(a[31], a[48]); SQRADDAC(a[32], a[47]); SQRADDAC(a[33], a[46]); SQRADDAC(a[34], a[45]); SQRADDAC(a[35], a[44]); SQRADDAC(a[36], a[43]); SQRADDAC(a[37], a[42]); SQRADDAC(a[38], a[41]); SQRADDAC(a[39], a[40]); SQRADDDB;
+   COMBA_STORE(b[79]);
+
+   /* output 80 */
+   CARRY_FORWARD;
+   SQRADDSC(a[17], a[63]); SQRADDAC(a[18], a[62]); SQRADDAC(a[19], a[61]); SQRADDAC(a[20], a[60]); SQRADDAC(a[21], a[59]); SQRADDAC(a[22], a[58]); SQRADDAC(a[23], a[57]); SQRADDAC(a[24], a[56]); SQRADDAC(a[25], a[55]); SQRADDAC(a[26], a[54]); SQRADDAC(a[27], a[53]); SQRADDAC(a[28], a[52]); SQRADDAC(a[29], a[51]); SQRADDAC(a[30], a[50]); SQRADDAC(a[31], a[49]); SQRADDAC(a[32], a[48]); SQRADDAC(a[33], a[47]); SQRADDAC(a[34], a[46]); SQRADDAC(a[35], a[45]); SQRADDAC(a[36], a[44]); SQRADDAC(a[37], a[43]); SQRADDAC(a[38], a[42]); SQRADDAC(a[39], a[41]); SQRADDDB; SQRADD(a[40], a[40]);
+   COMBA_STORE(b[80]);
+
+   /* output 81 */
+   CARRY_FORWARD;
+   SQRADDSC(a[18], a[63]); SQRADDAC(a[19], a[62]); SQRADDAC(a[20], a[61]); SQRADDAC(a[21], a[60]); SQRADDAC(a[22], a[59]); SQRADDAC(a[23], a[58]); SQRADDAC(a[24], a[57]); SQRADDAC(a[25], a[56]); SQRADDAC(a[26], a[55]); SQRADDAC(a[27], a[54]); SQRADDAC(a[28], a[53]); SQRADDAC(a[29], a[52]); SQRADDAC(a[30], a[51]); SQRADDAC(a[31], a[50]); SQRADDAC(a[32], a[49]); SQRADDAC(a[33], a[48]); SQRADDAC(a[34], a[47]); SQRADDAC(a[35], a[46]); SQRADDAC(a[36], a[45]); SQRADDAC(a[37], a[44]); SQRADDAC(a[38], a[43]); SQRADDAC(a[39], a[42]); SQRADDAC(a[40], a[41]); SQRADDDB;
+   COMBA_STORE(b[81]);
+
+   /* output 82 */
+   CARRY_FORWARD;
+   SQRADDSC(a[19], a[63]); SQRADDAC(a[20], a[62]); SQRADDAC(a[21], a[61]); SQRADDAC(a[22], a[60]); SQRADDAC(a[23], a[59]); SQRADDAC(a[24], a[58]); SQRADDAC(a[25], a[57]); SQRADDAC(a[26], a[56]); SQRADDAC(a[27], a[55]); SQRADDAC(a[28], a[54]); SQRADDAC(a[29], a[53]); SQRADDAC(a[30], a[52]); SQRADDAC(a[31], a[51]); SQRADDAC(a[32], a[50]); SQRADDAC(a[33], a[49]); SQRADDAC(a[34], a[48]); SQRADDAC(a[35], a[47]); SQRADDAC(a[36], a[46]); SQRADDAC(a[37], a[45]); SQRADDAC(a[38], a[44]); SQRADDAC(a[39], a[43]); SQRADDAC(a[40], a[42]); SQRADDDB; SQRADD(a[41], a[41]);
+   COMBA_STORE(b[82]);
+
+   /* output 83 */
+   CARRY_FORWARD;
+   SQRADDSC(a[20], a[63]); SQRADDAC(a[21], a[62]); SQRADDAC(a[22], a[61]); SQRADDAC(a[23], a[60]); SQRADDAC(a[24], a[59]); SQRADDAC(a[25], a[58]); SQRADDAC(a[26], a[57]); SQRADDAC(a[27], a[56]); SQRADDAC(a[28], a[55]); SQRADDAC(a[29], a[54]); SQRADDAC(a[30], a[53]); SQRADDAC(a[31], a[52]); SQRADDAC(a[32], a[51]); SQRADDAC(a[33], a[50]); SQRADDAC(a[34], a[49]); SQRADDAC(a[35], a[48]); SQRADDAC(a[36], a[47]); SQRADDAC(a[37], a[46]); SQRADDAC(a[38], a[45]); SQRADDAC(a[39], a[44]); SQRADDAC(a[40], a[43]); SQRADDAC(a[41], a[42]); SQRADDDB;
+   COMBA_STORE(b[83]);
+
+   /* output 84 */
+   CARRY_FORWARD;
+   SQRADDSC(a[21], a[63]); SQRADDAC(a[22], a[62]); SQRADDAC(a[23], a[61]); SQRADDAC(a[24], a[60]); SQRADDAC(a[25], a[59]); SQRADDAC(a[26], a[58]); SQRADDAC(a[27], a[57]); SQRADDAC(a[28], a[56]); SQRADDAC(a[29], a[55]); SQRADDAC(a[30], a[54]); SQRADDAC(a[31], a[53]); SQRADDAC(a[32], a[52]); SQRADDAC(a[33], a[51]); SQRADDAC(a[34], a[50]); SQRADDAC(a[35], a[49]); SQRADDAC(a[36], a[48]); SQRADDAC(a[37], a[47]); SQRADDAC(a[38], a[46]); SQRADDAC(a[39], a[45]); SQRADDAC(a[40], a[44]); SQRADDAC(a[41], a[43]); SQRADDDB; SQRADD(a[42], a[42]);
+   COMBA_STORE(b[84]);
+
+   /* output 85 */
+   CARRY_FORWARD;
+   SQRADDSC(a[22], a[63]); SQRADDAC(a[23], a[62]); SQRADDAC(a[24], a[61]); SQRADDAC(a[25], a[60]); SQRADDAC(a[26], a[59]); SQRADDAC(a[27], a[58]); SQRADDAC(a[28], a[57]); SQRADDAC(a[29], a[56]); SQRADDAC(a[30], a[55]); SQRADDAC(a[31], a[54]); SQRADDAC(a[32], a[53]); SQRADDAC(a[33], a[52]); SQRADDAC(a[34], a[51]); SQRADDAC(a[35], a[50]); SQRADDAC(a[36], a[49]); SQRADDAC(a[37], a[48]); SQRADDAC(a[38], a[47]); SQRADDAC(a[39], a[46]); SQRADDAC(a[40], a[45]); SQRADDAC(a[41], a[44]); SQRADDAC(a[42], a[43]); SQRADDDB;
+   COMBA_STORE(b[85]);
+
+   /* output 86 */
+   CARRY_FORWARD;
+   SQRADDSC(a[23], a[63]); SQRADDAC(a[24], a[62]); SQRADDAC(a[25], a[61]); SQRADDAC(a[26], a[60]); SQRADDAC(a[27], a[59]); SQRADDAC(a[28], a[58]); SQRADDAC(a[29], a[57]); SQRADDAC(a[30], a[56]); SQRADDAC(a[31], a[55]); SQRADDAC(a[32], a[54]); SQRADDAC(a[33], a[53]); SQRADDAC(a[34], a[52]); SQRADDAC(a[35], a[51]); SQRADDAC(a[36], a[50]); SQRADDAC(a[37], a[49]); SQRADDAC(a[38], a[48]); SQRADDAC(a[39], a[47]); SQRADDAC(a[40], a[46]); SQRADDAC(a[41], a[45]); SQRADDAC(a[42], a[44]); SQRADDDB; SQRADD(a[43], a[43]);
+   COMBA_STORE(b[86]);
+
+   /* output 87 */
+   CARRY_FORWARD;
+   SQRADDSC(a[24], a[63]); SQRADDAC(a[25], a[62]); SQRADDAC(a[26], a[61]); SQRADDAC(a[27], a[60]); SQRADDAC(a[28], a[59]); SQRADDAC(a[29], a[58]); SQRADDAC(a[30], a[57]); SQRADDAC(a[31], a[56]); SQRADDAC(a[32], a[55]); SQRADDAC(a[33], a[54]); SQRADDAC(a[34], a[53]); SQRADDAC(a[35], a[52]); SQRADDAC(a[36], a[51]); SQRADDAC(a[37], a[50]); SQRADDAC(a[38], a[49]); SQRADDAC(a[39], a[48]); SQRADDAC(a[40], a[47]); SQRADDAC(a[41], a[46]); SQRADDAC(a[42], a[45]); SQRADDAC(a[43], a[44]); SQRADDDB;
+   COMBA_STORE(b[87]);
+
+   /* output 88 */
+   CARRY_FORWARD;
+   SQRADDSC(a[25], a[63]); SQRADDAC(a[26], a[62]); SQRADDAC(a[27], a[61]); SQRADDAC(a[28], a[60]); SQRADDAC(a[29], a[59]); SQRADDAC(a[30], a[58]); SQRADDAC(a[31], a[57]); SQRADDAC(a[32], a[56]); SQRADDAC(a[33], a[55]); SQRADDAC(a[34], a[54]); SQRADDAC(a[35], a[53]); SQRADDAC(a[36], a[52]); SQRADDAC(a[37], a[51]); SQRADDAC(a[38], a[50]); SQRADDAC(a[39], a[49]); SQRADDAC(a[40], a[48]); SQRADDAC(a[41], a[47]); SQRADDAC(a[42], a[46]); SQRADDAC(a[43], a[45]); SQRADDDB; SQRADD(a[44], a[44]);
+   COMBA_STORE(b[88]);
+
+   /* output 89 */
+   CARRY_FORWARD;
+   SQRADDSC(a[26], a[63]); SQRADDAC(a[27], a[62]); SQRADDAC(a[28], a[61]); SQRADDAC(a[29], a[60]); SQRADDAC(a[30], a[59]); SQRADDAC(a[31], a[58]); SQRADDAC(a[32], a[57]); SQRADDAC(a[33], a[56]); SQRADDAC(a[34], a[55]); SQRADDAC(a[35], a[54]); SQRADDAC(a[36], a[53]); SQRADDAC(a[37], a[52]); SQRADDAC(a[38], a[51]); SQRADDAC(a[39], a[50]); SQRADDAC(a[40], a[49]); SQRADDAC(a[41], a[48]); SQRADDAC(a[42], a[47]); SQRADDAC(a[43], a[46]); SQRADDAC(a[44], a[45]); SQRADDDB;
+   COMBA_STORE(b[89]);
+
+   /* output 90 */
+   CARRY_FORWARD;
+   SQRADDSC(a[27], a[63]); SQRADDAC(a[28], a[62]); SQRADDAC(a[29], a[61]); SQRADDAC(a[30], a[60]); SQRADDAC(a[31], a[59]); SQRADDAC(a[32], a[58]); SQRADDAC(a[33], a[57]); SQRADDAC(a[34], a[56]); SQRADDAC(a[35], a[55]); SQRADDAC(a[36], a[54]); SQRADDAC(a[37], a[53]); SQRADDAC(a[38], a[52]); SQRADDAC(a[39], a[51]); SQRADDAC(a[40], a[50]); SQRADDAC(a[41], a[49]); SQRADDAC(a[42], a[48]); SQRADDAC(a[43], a[47]); SQRADDAC(a[44], a[46]); SQRADDDB; SQRADD(a[45], a[45]);
+   COMBA_STORE(b[90]);
+
+   /* output 91 */
+   CARRY_FORWARD;
+   SQRADDSC(a[28], a[63]); SQRADDAC(a[29], a[62]); SQRADDAC(a[30], a[61]); SQRADDAC(a[31], a[60]); SQRADDAC(a[32], a[59]); SQRADDAC(a[33], a[58]); SQRADDAC(a[34], a[57]); SQRADDAC(a[35], a[56]); SQRADDAC(a[36], a[55]); SQRADDAC(a[37], a[54]); SQRADDAC(a[38], a[53]); SQRADDAC(a[39], a[52]); SQRADDAC(a[40], a[51]); SQRADDAC(a[41], a[50]); SQRADDAC(a[42], a[49]); SQRADDAC(a[43], a[48]); SQRADDAC(a[44], a[47]); SQRADDAC(a[45], a[46]); SQRADDDB;
+   COMBA_STORE(b[91]);
+
+   /* output 92 */
+   CARRY_FORWARD;
+   SQRADDSC(a[29], a[63]); SQRADDAC(a[30], a[62]); SQRADDAC(a[31], a[61]); SQRADDAC(a[32], a[60]); SQRADDAC(a[33], a[59]); SQRADDAC(a[34], a[58]); SQRADDAC(a[35], a[57]); SQRADDAC(a[36], a[56]); SQRADDAC(a[37], a[55]); SQRADDAC(a[38], a[54]); SQRADDAC(a[39], a[53]); SQRADDAC(a[40], a[52]); SQRADDAC(a[41], a[51]); SQRADDAC(a[42], a[50]); SQRADDAC(a[43], a[49]); SQRADDAC(a[44], a[48]); SQRADDAC(a[45], a[47]); SQRADDDB; SQRADD(a[46], a[46]);
+   COMBA_STORE(b[92]);
+
+   /* output 93 */
+   CARRY_FORWARD;
+   SQRADDSC(a[30], a[63]); SQRADDAC(a[31], a[62]); SQRADDAC(a[32], a[61]); SQRADDAC(a[33], a[60]); SQRADDAC(a[34], a[59]); SQRADDAC(a[35], a[58]); SQRADDAC(a[36], a[57]); SQRADDAC(a[37], a[56]); SQRADDAC(a[38], a[55]); SQRADDAC(a[39], a[54]); SQRADDAC(a[40], a[53]); SQRADDAC(a[41], a[52]); SQRADDAC(a[42], a[51]); SQRADDAC(a[43], a[50]); SQRADDAC(a[44], a[49]); SQRADDAC(a[45], a[48]); SQRADDAC(a[46], a[47]); SQRADDDB;
+   COMBA_STORE(b[93]);
+
+   /* output 94 */
+   CARRY_FORWARD;
+   SQRADDSC(a[31], a[63]); SQRADDAC(a[32], a[62]); SQRADDAC(a[33], a[61]); SQRADDAC(a[34], a[60]); SQRADDAC(a[35], a[59]); SQRADDAC(a[36], a[58]); SQRADDAC(a[37], a[57]); SQRADDAC(a[38], a[56]); SQRADDAC(a[39], a[55]); SQRADDAC(a[40], a[54]); SQRADDAC(a[41], a[53]); SQRADDAC(a[42], a[52]); SQRADDAC(a[43], a[51]); SQRADDAC(a[44], a[50]); SQRADDAC(a[45], a[49]); SQRADDAC(a[46], a[48]); SQRADDDB; SQRADD(a[47], a[47]);
+   COMBA_STORE(b[94]);
+
+   /* output 95 */
+   CARRY_FORWARD;
+   SQRADDSC(a[32], a[63]); SQRADDAC(a[33], a[62]); SQRADDAC(a[34], a[61]); SQRADDAC(a[35], a[60]); SQRADDAC(a[36], a[59]); SQRADDAC(a[37], a[58]); SQRADDAC(a[38], a[57]); SQRADDAC(a[39], a[56]); SQRADDAC(a[40], a[55]); SQRADDAC(a[41], a[54]); SQRADDAC(a[42], a[53]); SQRADDAC(a[43], a[52]); SQRADDAC(a[44], a[51]); SQRADDAC(a[45], a[50]); SQRADDAC(a[46], a[49]); SQRADDAC(a[47], a[48]); SQRADDDB;
+   COMBA_STORE(b[95]);
+
+   /* output 96 */
+   CARRY_FORWARD;
+   SQRADDSC(a[33], a[63]); SQRADDAC(a[34], a[62]); SQRADDAC(a[35], a[61]); SQRADDAC(a[36], a[60]); SQRADDAC(a[37], a[59]); SQRADDAC(a[38], a[58]); SQRADDAC(a[39], a[57]); SQRADDAC(a[40], a[56]); SQRADDAC(a[41], a[55]); SQRADDAC(a[42], a[54]); SQRADDAC(a[43], a[53]); SQRADDAC(a[44], a[52]); SQRADDAC(a[45], a[51]); SQRADDAC(a[46], a[50]); SQRADDAC(a[47], a[49]); SQRADDDB; SQRADD(a[48], a[48]);
+   COMBA_STORE(b[96]);
+
+   /* output 97 */
+   CARRY_FORWARD;
+   SQRADDSC(a[34], a[63]); SQRADDAC(a[35], a[62]); SQRADDAC(a[36], a[61]); SQRADDAC(a[37], a[60]); SQRADDAC(a[38], a[59]); SQRADDAC(a[39], a[58]); SQRADDAC(a[40], a[57]); SQRADDAC(a[41], a[56]); SQRADDAC(a[42], a[55]); SQRADDAC(a[43], a[54]); SQRADDAC(a[44], a[53]); SQRADDAC(a[45], a[52]); SQRADDAC(a[46], a[51]); SQRADDAC(a[47], a[50]); SQRADDAC(a[48], a[49]); SQRADDDB;
+   COMBA_STORE(b[97]);
+
+   /* output 98 */
+   CARRY_FORWARD;
+   SQRADDSC(a[35], a[63]); SQRADDAC(a[36], a[62]); SQRADDAC(a[37], a[61]); SQRADDAC(a[38], a[60]); SQRADDAC(a[39], a[59]); SQRADDAC(a[40], a[58]); SQRADDAC(a[41], a[57]); SQRADDAC(a[42], a[56]); SQRADDAC(a[43], a[55]); SQRADDAC(a[44], a[54]); SQRADDAC(a[45], a[53]); SQRADDAC(a[46], a[52]); SQRADDAC(a[47], a[51]); SQRADDAC(a[48], a[50]); SQRADDDB; SQRADD(a[49], a[49]);
+   COMBA_STORE(b[98]);
+
+   /* output 99 */
+   CARRY_FORWARD;
+   SQRADDSC(a[36], a[63]); SQRADDAC(a[37], a[62]); SQRADDAC(a[38], a[61]); SQRADDAC(a[39], a[60]); SQRADDAC(a[40], a[59]); SQRADDAC(a[41], a[58]); SQRADDAC(a[42], a[57]); SQRADDAC(a[43], a[56]); SQRADDAC(a[44], a[55]); SQRADDAC(a[45], a[54]); SQRADDAC(a[46], a[53]); SQRADDAC(a[47], a[52]); SQRADDAC(a[48], a[51]); SQRADDAC(a[49], a[50]); SQRADDDB;
+   COMBA_STORE(b[99]);
+
+   /* output 100 */
+   CARRY_FORWARD;
+   SQRADDSC(a[37], a[63]); SQRADDAC(a[38], a[62]); SQRADDAC(a[39], a[61]); SQRADDAC(a[40], a[60]); SQRADDAC(a[41], a[59]); SQRADDAC(a[42], a[58]); SQRADDAC(a[43], a[57]); SQRADDAC(a[44], a[56]); SQRADDAC(a[45], a[55]); SQRADDAC(a[46], a[54]); SQRADDAC(a[47], a[53]); SQRADDAC(a[48], a[52]); SQRADDAC(a[49], a[51]); SQRADDDB; SQRADD(a[50], a[50]);
+   COMBA_STORE(b[100]);
+
+   /* output 101 */
+   CARRY_FORWARD;
+   SQRADDSC(a[38], a[63]); SQRADDAC(a[39], a[62]); SQRADDAC(a[40], a[61]); SQRADDAC(a[41], a[60]); SQRADDAC(a[42], a[59]); SQRADDAC(a[43], a[58]); SQRADDAC(a[44], a[57]); SQRADDAC(a[45], a[56]); SQRADDAC(a[46], a[55]); SQRADDAC(a[47], a[54]); SQRADDAC(a[48], a[53]); SQRADDAC(a[49], a[52]); SQRADDAC(a[50], a[51]); SQRADDDB;
+   COMBA_STORE(b[101]);
+
+   /* output 102 */
+   CARRY_FORWARD;
+   SQRADDSC(a[39], a[63]); SQRADDAC(a[40], a[62]); SQRADDAC(a[41], a[61]); SQRADDAC(a[42], a[60]); SQRADDAC(a[43], a[59]); SQRADDAC(a[44], a[58]); SQRADDAC(a[45], a[57]); SQRADDAC(a[46], a[56]); SQRADDAC(a[47], a[55]); SQRADDAC(a[48], a[54]); SQRADDAC(a[49], a[53]); SQRADDAC(a[50], a[52]); SQRADDDB; SQRADD(a[51], a[51]);
+   COMBA_STORE(b[102]);
+
+   /* output 103 */
+   CARRY_FORWARD;
+   SQRADDSC(a[40], a[63]); SQRADDAC(a[41], a[62]); SQRADDAC(a[42], a[61]); SQRADDAC(a[43], a[60]); SQRADDAC(a[44], a[59]); SQRADDAC(a[45], a[58]); SQRADDAC(a[46], a[57]); SQRADDAC(a[47], a[56]); SQRADDAC(a[48], a[55]); SQRADDAC(a[49], a[54]); SQRADDAC(a[50], a[53]); SQRADDAC(a[51], a[52]); SQRADDDB;
+   COMBA_STORE(b[103]);
+
+   /* output 104 */
+   CARRY_FORWARD;
+   SQRADDSC(a[41], a[63]); SQRADDAC(a[42], a[62]); SQRADDAC(a[43], a[61]); SQRADDAC(a[44], a[60]); SQRADDAC(a[45], a[59]); SQRADDAC(a[46], a[58]); SQRADDAC(a[47], a[57]); SQRADDAC(a[48], a[56]); SQRADDAC(a[49], a[55]); SQRADDAC(a[50], a[54]); SQRADDAC(a[51], a[53]); SQRADDDB; SQRADD(a[52], a[52]);
+   COMBA_STORE(b[104]);
+
+   /* output 105 */
+   CARRY_FORWARD;
+   SQRADDSC(a[42], a[63]); SQRADDAC(a[43], a[62]); SQRADDAC(a[44], a[61]); SQRADDAC(a[45], a[60]); SQRADDAC(a[46], a[59]); SQRADDAC(a[47], a[58]); SQRADDAC(a[48], a[57]); SQRADDAC(a[49], a[56]); SQRADDAC(a[50], a[55]); SQRADDAC(a[51], a[54]); SQRADDAC(a[52], a[53]); SQRADDDB;
+   COMBA_STORE(b[105]);
+
+   /* output 106 */
+   CARRY_FORWARD;
+   SQRADDSC(a[43], a[63]); SQRADDAC(a[44], a[62]); SQRADDAC(a[45], a[61]); SQRADDAC(a[46], a[60]); SQRADDAC(a[47], a[59]); SQRADDAC(a[48], a[58]); SQRADDAC(a[49], a[57]); SQRADDAC(a[50], a[56]); SQRADDAC(a[51], a[55]); SQRADDAC(a[52], a[54]); SQRADDDB; SQRADD(a[53], a[53]);
+   COMBA_STORE(b[106]);
+
+   /* output 107 */
+   CARRY_FORWARD;
+   SQRADDSC(a[44], a[63]); SQRADDAC(a[45], a[62]); SQRADDAC(a[46], a[61]); SQRADDAC(a[47], a[60]); SQRADDAC(a[48], a[59]); SQRADDAC(a[49], a[58]); SQRADDAC(a[50], a[57]); SQRADDAC(a[51], a[56]); SQRADDAC(a[52], a[55]); SQRADDAC(a[53], a[54]); SQRADDDB;
+   COMBA_STORE(b[107]);
+
+   /* output 108 */
+   CARRY_FORWARD;
+   SQRADDSC(a[45], a[63]); SQRADDAC(a[46], a[62]); SQRADDAC(a[47], a[61]); SQRADDAC(a[48], a[60]); SQRADDAC(a[49], a[59]); SQRADDAC(a[50], a[58]); SQRADDAC(a[51], a[57]); SQRADDAC(a[52], a[56]); SQRADDAC(a[53], a[55]); SQRADDDB; SQRADD(a[54], a[54]);
+   COMBA_STORE(b[108]);
+
+   /* output 109 */
+   CARRY_FORWARD;
+   SQRADDSC(a[46], a[63]); SQRADDAC(a[47], a[62]); SQRADDAC(a[48], a[61]); SQRADDAC(a[49], a[60]); SQRADDAC(a[50], a[59]); SQRADDAC(a[51], a[58]); SQRADDAC(a[52], a[57]); SQRADDAC(a[53], a[56]); SQRADDAC(a[54], a[55]); SQRADDDB;
+   COMBA_STORE(b[109]);
+
+   /* output 110 */
+   CARRY_FORWARD;
+   SQRADDSC(a[47], a[63]); SQRADDAC(a[48], a[62]); SQRADDAC(a[49], a[61]); SQRADDAC(a[50], a[60]); SQRADDAC(a[51], a[59]); SQRADDAC(a[52], a[58]); SQRADDAC(a[53], a[57]); SQRADDAC(a[54], a[56]); SQRADDDB; SQRADD(a[55], a[55]);
+   COMBA_STORE(b[110]);
+
+   /* output 111 */
+   CARRY_FORWARD;
+   SQRADDSC(a[48], a[63]); SQRADDAC(a[49], a[62]); SQRADDAC(a[50], a[61]); SQRADDAC(a[51], a[60]); SQRADDAC(a[52], a[59]); SQRADDAC(a[53], a[58]); SQRADDAC(a[54], a[57]); SQRADDAC(a[55], a[56]); SQRADDDB;
+   COMBA_STORE(b[111]);
+
+   /* output 112 */
+   CARRY_FORWARD;
+   SQRADDSC(a[49], a[63]); SQRADDAC(a[50], a[62]); SQRADDAC(a[51], a[61]); SQRADDAC(a[52], a[60]); SQRADDAC(a[53], a[59]); SQRADDAC(a[54], a[58]); SQRADDAC(a[55], a[57]); SQRADDDB; SQRADD(a[56], a[56]);
+   COMBA_STORE(b[112]);
+
+   /* output 113 */
+   CARRY_FORWARD;
+   SQRADDSC(a[50], a[63]); SQRADDAC(a[51], a[62]); SQRADDAC(a[52], a[61]); SQRADDAC(a[53], a[60]); SQRADDAC(a[54], a[59]); SQRADDAC(a[55], a[58]); SQRADDAC(a[56], a[57]); SQRADDDB;
+   COMBA_STORE(b[113]);
+
+   /* output 114 */
+   CARRY_FORWARD;
+   SQRADDSC(a[51], a[63]); SQRADDAC(a[52], a[62]); SQRADDAC(a[53], a[61]); SQRADDAC(a[54], a[60]); SQRADDAC(a[55], a[59]); SQRADDAC(a[56], a[58]); SQRADDDB; SQRADD(a[57], a[57]);
+   COMBA_STORE(b[114]);
+
+   /* output 115 */
+   CARRY_FORWARD;
+   SQRADDSC(a[52], a[63]); SQRADDAC(a[53], a[62]); SQRADDAC(a[54], a[61]); SQRADDAC(a[55], a[60]); SQRADDAC(a[56], a[59]); SQRADDAC(a[57], a[58]); SQRADDDB;
+   COMBA_STORE(b[115]);
+
+   /* output 116 */
+   CARRY_FORWARD;
+   SQRADDSC(a[53], a[63]); SQRADDAC(a[54], a[62]); SQRADDAC(a[55], a[61]); SQRADDAC(a[56], a[60]); SQRADDAC(a[57], a[59]); SQRADDDB; SQRADD(a[58], a[58]);
+   COMBA_STORE(b[116]);
+
+   /* output 117 */
+   CARRY_FORWARD;
+   SQRADDSC(a[54], a[63]); SQRADDAC(a[55], a[62]); SQRADDAC(a[56], a[61]); SQRADDAC(a[57], a[60]); SQRADDAC(a[58], a[59]); SQRADDDB;
+   COMBA_STORE(b[117]);
+
+   /* output 118 */
+   CARRY_FORWARD;
+   SQRADDSC(a[55], a[63]); SQRADDAC(a[56], a[62]); SQRADDAC(a[57], a[61]); SQRADDAC(a[58], a[60]); SQRADDDB; SQRADD(a[59], a[59]);
+   COMBA_STORE(b[118]);
+
+   /* output 119 */
+   CARRY_FORWARD;
+   SQRADDSC(a[56], a[63]); SQRADDAC(a[57], a[62]); SQRADDAC(a[58], a[61]); SQRADDAC(a[59], a[60]); SQRADDDB;
+   COMBA_STORE(b[119]);
+
+   /* output 120 */
+   CARRY_FORWARD;
+   SQRADDSC(a[57], a[63]); SQRADDAC(a[58], a[62]); SQRADDAC(a[59], a[61]); SQRADDDB; SQRADD(a[60], a[60]);
+   COMBA_STORE(b[120]);
+
+   /* output 121 */
+   CARRY_FORWARD;
+   SQRADDSC(a[58], a[63]); SQRADDAC(a[59], a[62]); SQRADDAC(a[60], a[61]); SQRADDDB;
+   COMBA_STORE(b[121]);
+
+   /* output 122 */
+   CARRY_FORWARD;
+   SQRADD2(a[59], a[63]); SQRADD2(a[60], a[62]); SQRADD(a[61], a[61]);
+   COMBA_STORE(b[122]);
+
+   /* output 123 */
+   CARRY_FORWARD;
+   SQRADD2(a[60], a[63]); SQRADD2(a[61], a[62]);
+   COMBA_STORE(b[123]);
+
+   /* output 124 */
+   CARRY_FORWARD;
+   SQRADD2(a[61], a[63]); SQRADD(a[62], a[62]);
+   COMBA_STORE(b[124]);
+
+   /* output 125 */
+   CARRY_FORWARD;
+   SQRADD2(a[62], a[63]);
+   COMBA_STORE(b[125]);
+
+   /* output 126 */
+   CARRY_FORWARD;
+   SQRADD(a[63], a[63]);
+   COMBA_STORE(b[126]);
+   COMBA_STORE2(b[127]);
+   COMBA_FINI;
+
+   B->used = 128;
+   B->sign = FP_ZPOS;
+   memcpy(B->dp, b, 128 * sizeof(fp_digit));
+   fp_clamp(B);
+}
+
+
+#endif
+
+/* End: fp_sqr_comba.c */
+
+/* Start: fp_sqr_comba_generic.c */
+/* generic comba squarer */
+void fp_sqr_comba(fp_int *A, fp_int *B)
+{
+  int       pa, ix, iz;
+  fp_digit  c0, c1, c2;
+  fp_int    tmp, *dst;
+
+  /* get size of output and trim */
+  pa = A->used + A->used;
+  if (pa >= FP_SIZE) {
+     pa = FP_SIZE-1;
+  }
+
+  /* number of output digits to produce */
+  COMBA_START;
+  CLEAR_CARRY;
+
+  if (A == B) {
+     fp_zero(&tmp);
+     dst = &tmp;
+  } else {
+     fp_zero(B);
+     dst = B;
+  }
+
+  for (ix = 0; ix < pa; ix++) {
+      int      tx, ty, iy;
+      fp_digit *tmpy, *tmpx;
+
+      /* get offsets into the two bignums */
+      ty = MIN(A->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = A->dp + tx;
+      tmpy = A->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially its
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(A->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* forward carries */
+      CARRY_FORWARD;
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+          SQRADD2(*tmpx++, *tmpy--);
+      }
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+          SQRADD(A->dp[ix>>1], A->dp[ix>>1]);
+      }
+
+      /* store it */
+      COMBA_STORE(dst->dp[ix]);
+  }
+  COMBA_STORE2(dst->dp[ix]);
+
+  COMBA_FINI;
+
+  /* setup dest */
+  dst->used = pa;
+  fp_clamp (dst);
+  if (dst != B) {
+     fp_copy(dst, B);
+  }
+}
+
+/* End: fp_sqr_comba_generic.c */
+
+/* Start: fp_sqrmod.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a * a (mod b) */
+int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c)
+{
+  fp_int tmp;
+  fp_zero(&tmp);
+  fp_sqr(a, &tmp);
+  return fp_mod(&tmp, b, c);
+}
+
+/* End: fp_sqrmod.c */
+
+/* Start: fp_sub.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a - b */
+void fp_sub(fp_int *a, fp_int *b, fp_int *c)
+{
+  int     sa, sb;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    s_fp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (fp_cmp_mag (a, b) != FP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      s_fp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == FP_ZPOS) ? FP_NEG : FP_ZPOS;
+      /* The second has a larger magnitude */
+      s_fp_sub (b, a, c);
+    }
+  }
+}
+
+
+/* End: fp_sub.c */
+
+/* Start: fp_sub_d.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* c = a - b */
+void fp_sub_d(fp_int *a, fp_digit b, fp_int *c)
+{
+   fp_int tmp;
+   fp_set(&tmp, b);
+   fp_sub(a, &tmp, c);
+}
+
+/* End: fp_sub_d.c */
+
+/* Start: fp_submod.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* d = a - b (mod c) */
+int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d)
+{
+  fp_int tmp;
+  fp_zero(&tmp);
+  fp_sub(a, b, &tmp);
+  return fp_mod(&tmp, c, d);
+}
+
+
+/* End: fp_submod.c */
+
+/* Start: fp_to_signed_bin.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_to_signed_bin(fp_int *a, unsigned char *b)
+{
+  fp_to_unsigned_bin (a, b + 1);
+  b[0] = (unsigned char) ((a->sign == FP_ZPOS) ? 0 : 1);
+}
+
+/* End: fp_to_signed_bin.c */
+
+/* Start: fp_to_unsigned_bin.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+void fp_to_unsigned_bin(fp_int *a, unsigned char *b)
+{
+  int     x;
+  fp_int  t;
+
+  fp_init_copy(&t, a);
+
+  x = 0;
+  while (fp_iszero (&t) == FP_NO) {
+      b[x++] = (unsigned char) (t.dp[0] & 255);
+      fp_div_2d (&t, 8, &t, NULL);
+  }
+  bn_reverse (b, x);
+}
+
+/* End: fp_to_unsigned_bin.c */
+
+/* Start: fp_toradix.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+int fp_toradix(fp_int *a, char *str, int radix)
+{
+  int     digs;
+  fp_int  t;
+  fp_digit d;
+  char   *_s = str;
+
+  /* check range of the radix */
+  if (radix < 2 || radix > 64) {
+    return FP_VAL;
+  }
+
+  /* quick out if its zero */
+  if (fp_iszero(a) == 1) {
+     *str++ = '0';
+     *str = '\0';
+     return FP_OKAY;
+  }
+
+  fp_init_copy(&t, a);
+
+  /* if it is negative output a - */
+  if (t.sign == FP_NEG) {
+    ++_s;
+    *str++ = '-';
+    t.sign = FP_ZPOS;
+  }
+
+  digs = 0;
+  while (fp_iszero (&t) == FP_NO) {
+    fp_div_d (&t, (fp_digit) radix, &t, &d);
+    *str++ = fp_s_rmap[d];
+    ++digs;
+  }
+
+  /* reverse the digits of the string.  In this case _s points
+   * to the first digit [exluding the sign] of the number]
+   */
+  bn_reverse ((unsigned char *)_s, digs);
+
+  /* append a NULL so the string is properly terminated */
+  *str = '\0';
+  return FP_OKAY;
+}
+
+/* End: fp_toradix.c */
+
+/* Start: fp_unsigned_bin_size.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+int fp_unsigned_bin_size(fp_int *a)
+{
+  int     size = fp_count_bits (a);
+  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+
+/* End: fp_unsigned_bin_size.c */
+
+/* Start: s_fp_add.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* unsigned addition */
+void s_fp_add(fp_int *a, fp_int *b, fp_int *c)
+{
+  int      x, y, oldused;
+  fp_word  t;
+
+  y       = MAX(a->used, b->used);
+  oldused = c->used;
+  c->used = y;
+
+  t = 0;
+  for (x = 0; x < y; x++) {
+      t         += ((fp_word)a->dp[x]) + ((fp_word)b->dp[x]);
+      c->dp[x]   = (fp_digit)t;
+      t        >>= DIGIT_BIT;
+  }
+  if (t != 0 && x != FP_SIZE) {
+     c->dp[c->used++] = (fp_digit)t;
+     ++x;
+  }
+
+  for (; x < oldused; x++) {
+     c->dp[x] = 0;
+  }
+  fp_clamp(c);
+}
+
+/* End: s_fp_add.c */
+
+/* Start: s_fp_sub.c */
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#include <tfm.h>
+
+/* unsigned subtraction ||a|| >= ||b|| ALWAYS! */
+void s_fp_sub(fp_int *a, fp_int *b, fp_int *c)
+{
+  int      x, oldused;
+  fp_word  t;
+
+  oldused = c->used;
+  c->used = a->used;
+  t       = 0;
+  for (x = 0; x < a->used; x++) {
+      t         = ((fp_word)a->dp[x]) - (((fp_word)b->dp[x]) + t);
+      c->dp[x]  = (fp_digit)t;
+      t         = (t >> DIGIT_BIT) & 1;
+  }
+
+  for (; x < oldused; x++) {
+     c->dp[x] = 0;
+  }
+  fp_clamp(c);
+}
+
+/* End: s_fp_sub.c */
+
+
+/* EOF */
diff --git a/lib/silcmath/tfm.h b/lib/silcmath/tfm.h
new file mode 100644 (file)
index 0000000..677f288
--- /dev/null
@@ -0,0 +1,362 @@
+/* TomsFastMath, a fast ISO C bignum library.
+ *
+ * This project is meant to fill in where LibTomMath
+ * falls short.  That is speed ;-)
+ *
+ * This project is public domain and free for all purposes.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca
+ */
+#ifndef TFM_H_
+#define TFM_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+/* Assure these -Pekka */
+#undef CRYPT
+
+#undef MIN
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#undef MAX
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+/* do we want large code? */
+#define TFM_LARGE
+
+/* do we want huge code (implies large)?  The answer is, yes. */
+#define TFM_HUGE
+
+/* imply TFM_LARGE as required */
+#if defined(TFM_HUGE)
+   #if !defined(TFM_LARGE)
+      #define TFM_LARGE
+   #endif
+#endif
+
+/* Max size of any number in bits.  Basically the largest size you will be multiplying
+ * should be half [or smaller] of FP_MAX_SIZE-four_digit
+ *
+ * You can externally define this or it defaults to 4096-bits.
+ */
+#ifndef FP_MAX_SIZE
+/* For SILC -Pekka */
+   #define FP_MAX_SIZE           (8192+(4*DIGIT_BIT))
+/*   #define FP_MAX_SIZE           (4096+(4*DIGIT_BIT))*/
+#endif
+
+/* will this lib work? */
+#if (CHAR_BIT & 7)
+   #error CHAR_BIT must be a multiple of eight.
+#endif
+#if FP_MAX_SIZE % CHAR_BIT
+   #error FP_MAX_SIZE must be a multiple of CHAR_BIT
+#endif
+
+/* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */
+#if defined(__x86_64__)
+   #if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM)
+       #error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid!
+   #endif
+   #if !defined(TFM_X86_64) && !defined(TFM_NO_ASM)
+      #define TFM_X86_64
+   #endif
+#endif
+#if defined(TFM_X86_64)
+    #if !defined(FP_64BIT)
+       #define FP_64BIT
+    #endif
+#endif
+
+/* try to detect x86-32 */
+#if defined(__i386__) && !defined(TFM_SSE2)
+   #if defined(TFM_X86_64) || defined(TFM_ARM)
+       #error x86-32 detected, x86-64/ARM optimizations are not valid!
+   #endif
+   #if !defined(TFM_X86) && !defined(TFM_NO_ASM)
+      #define TFM_X86
+   #endif
+#endif
+
+/* make sure we're 32-bit for x86-32/sse/arm */
+#if (defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM)) && defined(FP_64BIT)
+   #warning x86-32, SSE2 and ARM optimizations require 32-bit digits (undefining)
+   #undef FP_64BIT
+#endif
+
+/* multi asms? */
+#ifdef TFM_X86
+   #define TFM_ASM
+#endif
+#ifdef TFM_X86_64
+   #ifdef TFM_ASM
+      #error TFM_ASM already defined!
+   #endif
+   #define TFM_ASM
+#endif
+#ifdef TFM_SSE2
+   #ifdef TFM_ASM
+      #error TFM_ASM already defined!
+   #endif
+   #define TFM_ASM
+#endif
+#ifdef TFM_ARM
+   #ifdef TFM_ASM
+      #error TFM_ASM already defined!
+   #endif
+   #define TFM_ASM
+#endif
+
+/* we want no asm? */
+#ifdef TFM_NO_ASM
+   #undef TFM_X86
+   #undef TFM_X86_64
+   #undef TFM_SSE2
+   #undef TFM_ARM
+   #undef TFM_ASM
+#endif
+
+/* some default configurations.
+ */
+#if defined(FP_64BIT)
+   /* for GCC only on supported platforms */
+#ifndef CRYPT
+   typedef unsigned long ulong64;
+#endif
+   typedef ulong64            fp_digit;
+   typedef unsigned long      fp_word __attribute__ ((mode(TI)));
+#else
+   /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+   #if defined(_MSC_VER) || defined(__BORLANDC__)
+      typedef unsigned __int64   ulong64;
+      typedef signed __int64     long64;
+   #else
+      typedef unsigned long long ulong64;
+      typedef signed long long   long64;
+   #endif
+#endif
+   typedef unsigned long      fp_digit;
+   typedef ulong64            fp_word;
+#endif
+
+/* # of digits this is */
+#define DIGIT_BIT  (int)((CHAR_BIT) * sizeof(fp_digit))
+#define FP_MASK    (fp_digit)(-1)
+#define FP_SIZE    (FP_MAX_SIZE/DIGIT_BIT)
+
+/* signs */
+#define FP_ZPOS     0
+#define FP_NEG      1
+
+/* return codes */
+#define FP_OKAY     0
+#define FP_VAL      1
+#define FP_MEM      2
+
+/* equalities */
+#define FP_LT        -1   /* less than */
+#define FP_EQ         0   /* equal to */
+#define FP_GT         1   /* greater than */
+
+/* replies */
+#define FP_YES        1   /* yes response */
+#define FP_NO         0   /* no response */
+
+/* a FP type */
+typedef struct {
+    fp_digit dp[FP_SIZE];
+    int      used,
+             sign;
+} fp_int;
+
+/* functions */
+
+/* returns a TFM ident string useful for debugging... */
+const char *fp_ident(void);
+
+/* initialize [or zero] an fp int */
+#define fp_init(a)  (void)memset((a), 0, sizeof(fp_int))
+#define fp_zero(a)  fp_init(a)
+
+/* zero/even/odd ? */
+#define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO)
+#define fp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO)
+#define fp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO)
+
+/* set to a small digit */
+void fp_set(fp_int *a, fp_digit b);
+
+/* copy from a to b */
+#define fp_copy(a, b)      (void)(((a) != (b)) && memcpy((b), (a), sizeof(fp_int)))
+#define fp_init_copy(a, b) fp_copy(b, a)
+
+/* negate and absolute */
+#define fp_neg(a, b)  { fp_copy(a, b); (b)->sign ^= 1; }
+#define fp_abs(a, b)  { fp_copy(a, b); (b)->sign  = 0; }
+
+/* clamp digits */
+#define fp_clamp(a)   { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; }
+
+/* right shift x digits */
+void fp_rshd(fp_int *a, int x);
+
+/* left shift x digits */
+void fp_lshd(fp_int *a, int x);
+
+/* signed comparison */
+int fp_cmp(fp_int *a, fp_int *b);
+
+/* unsigned comparison */
+int fp_cmp_mag(fp_int *a, fp_int *b);
+
+/* power of 2 operations */
+void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);
+void fp_mod_2d(fp_int *a, int b, fp_int *c);
+void fp_mul_2d(fp_int *a, int b, fp_int *c);
+void fp_2expt (fp_int *a, int b);
+void fp_mul_2(fp_int *a, fp_int *c);
+void fp_div_2(fp_int *a, fp_int *c);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int fp_cnt_lsb(fp_int *a);
+
+/* c = a + b */
+void fp_add(fp_int *a, fp_int *b, fp_int *c);
+
+/* c = a - b */
+void fp_sub(fp_int *a, fp_int *b, fp_int *c);
+
+/* c = a * b */
+void fp_mul(fp_int *a, fp_int *b, fp_int *c);
+
+/* b = a*a  */
+void fp_sqr(fp_int *a, fp_int *b);
+
+/* a/b => cb + d == a */
+int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
+
+/* c = a mod b, 0 <= c < b  */
+int fp_mod(fp_int *a, fp_int *b, fp_int *c);
+
+/* compare against a single digit */
+int fp_cmp_d(fp_int *a, fp_digit b);
+
+/* c = a + b */
+void fp_add_d(fp_int *a, fp_digit b, fp_int *c);
+
+/* c = a - b */
+void fp_sub_d(fp_int *a, fp_digit b, fp_int *c);
+
+/* c = a * b */
+void fp_mul_d(fp_int *a, fp_digit b, fp_int *c);
+
+/* a/b => cb + d == a */
+int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d);
+
+/* c = a mod b, 0 <= c < b  */
+int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c);
+
+/* ---> number theory <--- */
+/* d = a + b (mod c) */
+int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
+
+/* d = a - b (mod c) */
+int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
+
+/* d = a * b (mod c) */
+int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
+
+/* c = a * a (mod b) */
+int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c);
+
+/* c = 1/a (mod b) */
+int fp_invmod(fp_int *a, fp_int *b, fp_int *c);
+
+/* c = (a, b) */
+void fp_gcd(fp_int *a, fp_int *b, fp_int *c);
+
+/* c = [a, b] */
+void fp_lcm(fp_int *a, fp_int *b, fp_int *c);
+
+/* setups the montgomery reduction */
+int fp_montgomery_setup(fp_int *a, fp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+void fp_montgomery_calc_normalization(fp_int *a, fp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp);
+
+/* d = a**b (mod c) */
+int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);
+
+/* primality stuff */
+
+/* perform a Miller-Rabin test of a to the base b and store result in "result" */
+void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result);
+
+/* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime  */
+int fp_isprime(fp_int *a);
+
+/* Primality generation flags */
+#define TFM_PRIME_BBS      0x0001 /* BBS style prime */
+#define TFM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
+#define TFM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
+#define TFM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */
+
+/* callback for fp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat);
+
+#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat)
+
+int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);
+
+/* radix conersions */
+int fp_count_bits(fp_int *a);
+
+int fp_unsigned_bin_size(fp_int *a);
+void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c);
+void fp_to_unsigned_bin(fp_int *a, unsigned char *b);
+
+int fp_signed_bin_size(fp_int *a);
+void fp_read_signed_bin(fp_int *a, unsigned char *b, int c);
+void fp_to_signed_bin(fp_int *a, unsigned char *b);
+
+int fp_read_radix(fp_int *a, char *str, int radix);
+int fp_toradix(fp_int *a, char *str, int radix);
+int fp_toradix_n(fp_int * a, char *str, int radix, int maxlen);
+int fp_radix_size(fp_int *a, int radix, int *size);
+
+/* VARIOUS LOW LEVEL STUFFS */
+void s_fp_add(fp_int *a, fp_int *b, fp_int *c);
+void s_fp_sub(fp_int *a, fp_int *b, fp_int *c);
+void bn_reverse(unsigned char *s, int len);
+void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C);
+#ifdef TFM_HUGE
+void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C);
+#endif
+#ifdef TFM_LARGE
+void fp_mul_comba16(fp_int *A, fp_int *B, fp_int *C);
+#endif
+void fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C);
+void fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C);
+
+void fp_sqr_comba(fp_int *A, fp_int *B);
+void fp_sqr_comba4(fp_int *A, fp_int *B);
+void fp_sqr_comba8(fp_int *A, fp_int *B);
+#ifdef TFM_LARGE
+void fp_sqr_comba16(fp_int *A, fp_int *B);
+#endif
+#ifdef TFM_HUGE
+void fp_sqr_comba32(fp_int *A, fp_int *B);
+void fp_sqr_comba64(fp_int *A, fp_int *B);
+#endif
+extern const char *fp_s_rmap;
+
+#endif
diff --git a/lib/silcmath/tma.c b/lib/silcmath/tma.c
new file mode 100644 (file)
index 0000000..12f9d3f
--- /dev/null
@@ -0,0 +1,9048 @@
+/* Start: bn_error.c */
+#include "tma.h"
+#ifdef BN_ERROR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+static const struct {
+     int code;
+     char *msg;
+} msgs[] = {
+     { MP_OKAY, "Successful" },
+     { MP_MEM,  "Out of heap" },
+     { MP_VAL,  "Value out of range" }
+};
+
+/* return a char * string for a given code */
+char *mp_error_to_string(int code)
+{
+   int x;
+
+   /* scan the lookup table for the given message */
+   for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
+       if (msgs[x].code == code) {
+          return msgs[x].msg;
+       }
+   }
+
+   /* generic reply for invalid code */
+   return "Invalid error code";
+}
+
+#endif
+
+/* End: bn_error.c */
+
+/* Start: bn_fast_mp_invmod.c */
+#include "tma.h"
+#ifdef BN_FAST_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* computes the modular inverse via binary extended euclidean algorithm, 
+ * that is c = 1/a mod b 
+ *
+ * Based on slow invmod except this is optimized for the case where b is 
+ * odd as per HAC Note 14.64 on pp. 610
+ */
+int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, B, D;
+  int     res, neg;
+
+  /* 2. [modified] b must be odd   */
+  if (mp_iseven (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* init all our temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x == modulus, y == value to invert */
+  if ((res = mp_copy (b, &x)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* we need y = |a| */
+  if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if B is odd then */
+    if (mp_isodd (&B) == 1) {
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+    }
+    /* B = B/2 */
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if D is odd then */
+    if (mp_isodd (&D) == 1) {
+      /* D = (D-x)/2 */
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+        goto LBL_ERR;
+      }
+    }
+    /* D = D/2 */
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0) {
+    goto top;
+  }
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* b is now the inverse */
+  neg = a->sign;
+  while (D.sign == MP_NEG) {
+    if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+  mp_exch (&D, c);
+  c->sign = neg;
+  res = MP_OKAY;
+
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
+  return res;
+}
+#endif
+
+/* End: bn_fast_mp_invmod.c */
+
+/* Start: bn_fast_mp_montgomery_reduce.c */
+#include "tma.h"
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, olduse;
+  mp_word W[MP_WARRAY];
+
+  /* get old used count */
+  olduse = x->used;
+
+  /* grow a as required */
+  if (x->alloc < n->used + 1) {
+    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+  {
+    register mp_word *_W;
+    register mp_digit *tmpx;
+
+    /* alias for the W[] array */
+    _W   = W;
+
+    /* alias for the digits of  x*/
+    tmpx = x->dp;
+
+    /* copy the digits of a into W[0..a->used-1] */
+    for (ix = 0; ix < x->used; ix++) {
+      *_W++ = *tmpx++;
+    }
+
+    /* zero the high words of W[a->used..m->used*2] */
+    for (; ix < n->used * 2 + 1; ix++) {
+      *_W++ = 0;
+    }
+  }
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    register mp_digit mu;
+    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offseting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop.  The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    {
+      register int iy;
+      register mp_digit *tmpn;
+      register mp_word *_W;
+
+      /* alias for the digits of the modulus */
+      tmpn = n->dp;
+
+      /* Alias for the columns set by an offset of ix */
+      _W = W + ix;
+
+      /* inner loop */
+      for (iy = 0; iy < n->used; iy++) {
+          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+      }
+    }
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+  {
+    register mp_digit *tmpx;
+    register mp_word *_W, *_W1;
+
+    /* nox fix rest of carries */
+
+    /* alias for current word */
+    _W1 = W + ix;
+
+    /* alias for next word, where the carry goes */
+    _W = W + ++ix;
+
+    for (; ix <= n->used * 2 + 1; ix++) {
+      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+    }
+
+    /* copy out, A = A/b**n
+     *
+     * The result is A/b**n but instead of converting from an
+     * array of mp_word to mp_digit than calling mp_rshd
+     * we just copy them in the right order
+     */
+
+    /* alias for destination word */
+    tmpx = x->dp;
+
+    /* alias for shifted double precision result */
+    _W = W + n->used;
+
+    for (ix = 0; ix < n->used + 1; ix++) {
+      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+    }
+
+    /* zero oldused digits, if the input a was larger than
+     * m->used+1 we'll have to clear the digits
+     */
+    for (; ix < olduse; ix++) {
+      *tmpx++ = 0;
+    }
+  }
+
+  /* set the max used and clamp */
+  x->used = n->used + 1;
+  mp_clamp (x);
+
+  /* if A >= m then A = A - m */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_fast_mp_montgomery_reduce.c */
+
+/* Start: bn_fast_s_mp_mul_digs.c */
+#include "tma.h"
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier.  It is 
+ * designed to compute the columns of the product first 
+ * then handle the carries afterwards.  This has the effect 
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of 
+ * digits of output so if say only a half-product is required 
+ * you don't have to compute the upper half (a feature 
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  register mp_word  _W;
+
+  /* grow the destination as required */
+  if (c->alloc < digs) {
+    if ((res = mp_grow (c, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  pa = MIN(digs, a->used + b->used);
+
+  /* clear the carry */
+  _W = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty;
+      int      iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially 
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; ++iz) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* store final carry */
+  W[ix] = (mp_digit)(_W & MP_MASK);
+
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    register mp_digit *tmpc;
+    tmpc = c->dp;
+    for (ix = 0; ix < pa+1; ix++) {
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_fast_s_mp_mul_digs.c */
+
+/* Start: bn_fast_s_mp_mul_high_digs.c */
+#include "tma.h"
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* this is a modified version of fast_s_mul_digs that only produces
+ * output digits *above* digs.  See the comments for fast_s_mul_digs
+ * to see how it works.
+ *
+ * This is used in the Barrett reduction since for one of the multiplications
+ * only the higher digits were needed.  This essentially halves the work.
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ */
+int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  mp_word  _W;
+
+  /* grow the destination as required */
+  pa = a->used + b->used;
+  if (c->alloc < pa) {
+    if ((res = mp_grow (c, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  pa = a->used + b->used;
+  _W = 0;
+  for (ix = digs; ix < pa; ix++) { 
+      int      tx, ty, iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially its 
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+  }
+  
+  /* store final carry */
+  W[ix] = (mp_digit)(_W & MP_MASK);
+
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    register mp_digit *tmpc;
+
+    tmpc = c->dp + digs;
+    for (ix = digs; ix <= pa; ix++) {
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_fast_s_mp_mul_high_digs.c */
+
+/* Start: bn_fast_s_mp_sqr.c */
+#include "tma.h"
+#ifdef BN_FAST_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that 
+ * starts closer to zero] can't equal the offset of tmpy.  
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens.  You double all those 
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+int fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+  int       olduse, res, pa, ix, iz;
+  mp_digit   W[MP_WARRAY], *tmpx;
+  mp_word   W1;
+
+  /* grow the destination as required */
+  pa = a->used + a->used;
+  if (b->alloc < pa) {
+    if ((res = mp_grow (b, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  W1 = 0;
+  for (ix = 0; ix < pa; ix++) { 
+      int      tx, ty, iy;
+      mp_word  _W;
+      mp_digit *tmpy;
+
+      /* clear counter */
+      _W = 0;
+
+      /* get offsets into the two bignums */
+      ty = MIN(a->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = a->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty 
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* double the inner product and add carry */
+      _W = _W + _W + W1;
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+      }
+
+      /* store it */
+      W[ix] = (mp_digit)(_W & MP_MASK);
+
+      /* make next carry */
+      W1 = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* setup dest */
+  olduse  = b->used;
+  b->used = a->used+a->used;
+
+  {
+    mp_digit *tmpb;
+    tmpb = b->dp;
+    for (ix = 0; ix < pa; ix++) {
+      *tmpb++ = W[ix] & MP_MASK;
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpb++ = 0;
+    }
+  }
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_fast_s_mp_sqr.c */
+
+/* Start: bn_mp_2expt.c */
+#include "tma.h"
+#ifdef BN_MP_2EXPT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* computes a = 2**b 
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+int
+mp_2expt (mp_int * a, int b)
+{
+  int     res;
+
+  /* zero a as per default */
+  mp_zero (a);
+
+  /* grow a to accomodate the single bit */
+  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set the used count of where the bit will go */
+  a->used = b / DIGIT_BIT + 1;
+
+  /* put the single bit in its place */
+  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_2expt.c */
+
+/* Start: bn_mp_abs.c */
+#include "tma.h"
+#ifdef BN_MP_ABS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* b = |a| 
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+int
+mp_abs (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_abs.c */
+
+/* Start: bn_mp_add.c */
+#include "tma.h"
+#ifdef BN_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* high level addition (handles signs) */
+int mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (mp_cmp_mag (a, b) == MP_LT) {
+      c->sign = sb;
+      res = s_mp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      res = s_mp_sub (a, b, c);
+    }
+  }
+  return res;
+}
+
+#endif
+
+/* End: bn_mp_add.c */
+
+/* Start: bn_mp_add_d.c */
+#include "tma.h"
+#ifdef BN_MP_ADD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* single digit addition */
+int
+mp_add_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  int     res, ix, oldused;
+  mp_digit *tmpa, *tmpc, mu;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative and |a| >= b, call c = |a| - b */
+  if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
+     /* temporarily fix sign of a */
+     a->sign = MP_ZPOS;
+
+     /* c = |a| - b */
+     res = mp_sub_d(a, b, c);
+
+     /* fix sign  */
+     a->sign = c->sign = MP_NEG;
+
+     return res;
+  }
+
+  /* old number of used digits in c */
+  oldused = c->used;
+
+  /* sign always positive */
+  c->sign = MP_ZPOS;
+
+  /* source alias */
+  tmpa    = a->dp;
+
+  /* destination alias */
+  tmpc    = c->dp;
+
+  /* if a is positive */
+  if (a->sign == MP_ZPOS) {
+     /* add digit, after this we're propagating
+      * the carry.
+      */
+     *tmpc   = *tmpa++ + b;
+     mu      = *tmpc >> DIGIT_BIT;
+     *tmpc++ &= MP_MASK;
+
+     /* now handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc   = *tmpa++ + mu;
+        mu      = *tmpc >> DIGIT_BIT;
+        *tmpc++ &= MP_MASK;
+     }
+     /* set final carry */
+     ix++;
+     *tmpc++  = mu;
+
+     /* setup size */
+     c->used = a->used + 1;
+  } else {
+     /* a was negative and |a| < b */
+     c->used  = 1;
+
+     /* the result is a single digit */
+     if (a->used == 1) {
+        *tmpc++  =  b - a->dp[0];
+     } else {
+        *tmpc++  =  b;
+     }
+
+     /* setup count so the clearing of oldused
+      * can fall through correctly
+      */
+     ix       = 1;
+  }
+
+  /* now zero to oldused */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_add_d.c */
+
+/* Start: bn_mp_addmod.c */
+#include "tma.h"
+#ifdef BN_MP_ADDMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* d = a + b (mod c) */
+int
+mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_add (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* End: bn_mp_addmod.c */
+
+/* Start: bn_mp_and.c */
+#include "tma.h"
+#ifdef BN_MP_AND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* AND two ints together */
+int
+mp_and (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] &= x->dp[ix];
+  }
+
+  /* zero digits above the last from the smallest mp_int */
+  for (; ix < t.used; ix++) {
+    t.dp[ix] = 0;
+  }
+
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_and.c */
+
+/* Start: bn_mp_clamp.c */
+#include "tma.h"
+#ifdef BN_MP_CLAMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* trim unused digits 
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast.  Also fixes the sign if there
+ * are no more leading digits
+ */
+void
+mp_clamp (mp_int * a)
+{
+  /* decrease used while the most significant digit is
+   * zero.
+   */
+  while (a->used > 0 && a->dp[a->used - 1] == 0) {
+    --(a->used);
+  }
+
+  /* reset the sign flag if used == 0 */
+  if (a->used == 0) {
+    a->sign = MP_ZPOS;
+  }
+}
+#endif
+
+/* End: bn_mp_clamp.c */
+
+/* Start: bn_mp_clear.c */
+#include "tma.h"
+#ifdef BN_MP_CLEAR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* clear one (frees)  */
+void
+mp_clear (mp_int * a)
+{
+  int i;
+
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
+
+    /* free ram */
+    XFREE(a->dp);
+
+    /* reset members to make debugging easier */
+    a->dp    = NULL;
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+#endif
+
+/* End: bn_mp_clear.c */
+
+/* Start: bn_mp_clear_multi.c */
+#include "tma.h"
+#ifdef BN_MP_CLEAR_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+#include <stdarg.h>
+
+void mp_clear_multi(mp_int *mp, ...) 
+{
+    mp_int* next_mp = mp;
+    va_list args;
+    va_start(args, mp);
+    while (next_mp != NULL) {
+        mp_clear(next_mp);
+        next_mp = va_arg(args, mp_int*);
+    }
+    va_end(args);
+}
+#endif
+
+/* End: bn_mp_clear_multi.c */
+
+/* Start: bn_mp_cmp.c */
+#include "tma.h"
+#ifdef BN_MP_CMP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* compare two ints (signed)*/
+int
+mp_cmp (mp_int * a, mp_int * b)
+{
+  /* compare based on sign */
+  if (a->sign != b->sign) {
+     if (a->sign == MP_NEG) {
+        return MP_LT;
+     } else {
+        return MP_GT;
+     }
+  }
+  
+  /* compare digits */
+  if (a->sign == MP_NEG) {
+     /* if negative compare opposite direction */
+     return mp_cmp_mag(b, a);
+  } else {
+     return mp_cmp_mag(a, b);
+  }
+}
+#endif
+
+/* End: bn_mp_cmp.c */
+
+/* Start: bn_mp_cmp_d.c */
+#include "tma.h"
+#ifdef BN_MP_CMP_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* compare a digit */
+int mp_cmp_d(mp_int * a, mp_digit b)
+{
+  /* compare based on sign */
+  if (a->sign == MP_NEG) {
+    return MP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return MP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return MP_GT;
+  } else if (a->dp[0] < b) {
+    return MP_LT;
+  } else {
+    return MP_EQ;
+  }
+}
+#endif
+
+/* End: bn_mp_cmp_d.c */
+
+/* Start: bn_mp_cmp_mag.c */
+#include "tma.h"
+#ifdef BN_MP_CMP_MAG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* compare maginitude of two ints (unsigned) */
+int mp_cmp_mag (mp_int * a, mp_int * b)
+{
+  int     n;
+  mp_digit *tmpa, *tmpb;
+
+  /* compare based on # of non-zero digits */
+  if (a->used > b->used) {
+    return MP_GT;
+  }
+  
+  if (a->used < b->used) {
+    return MP_LT;
+  }
+
+  /* alias for a */
+  tmpa = a->dp + (a->used - 1);
+
+  /* alias for b */
+  tmpb = b->dp + (a->used - 1);
+
+  /* compare based on digits  */
+  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+    if (*tmpa > *tmpb) {
+      return MP_GT;
+    }
+
+    if (*tmpa < *tmpb) {
+      return MP_LT;
+    }
+  }
+  return MP_EQ;
+}
+#endif
+
+/* End: bn_mp_cmp_mag.c */
+
+/* Start: bn_mp_cnt_lsb.c */
+#include "tma.h"
+#ifdef BN_MP_CNT_LSB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+static const int lnz[16] = { 
+   4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a)
+{
+   int x;
+   mp_digit q, qq;
+
+   /* easy out */
+   if (mp_iszero(a) == 1) {
+      return 0;
+   }
+
+   /* scan lower digits until non-zero */
+   for (x = 0; x < a->used && a->dp[x] == 0; x++);
+   q = a->dp[x];
+   x *= DIGIT_BIT;
+
+   /* now scan this digit until a 1 is found */
+   if ((q & 1) == 0) {
+      do {
+         qq  = q & 15;
+         x  += lnz[qq];
+         q >>= 4;
+      } while (qq == 0);
+   }
+   return x;
+}
+
+#endif
+
+/* End: bn_mp_cnt_lsb.c */
+
+/* Start: bn_mp_copy.c */
+#include "tma.h"
+#ifdef BN_MP_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* copy, b = a */
+int
+mp_copy (mp_int * a, mp_int * b)
+{
+  int     res, n;
+
+  /* if dst == src do nothing */
+  if (a == b) {
+    return MP_OKAY;
+  }
+
+  /* grow dest */
+  if (b->alloc < a->used) {
+     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero b and copy the parameters over */
+  {
+    register mp_digit *tmpa, *tmpb;
+
+    /* pointer aliases */
+
+    /* source */
+    tmpa = a->dp;
+
+    /* destination */
+    tmpb = b->dp;
+
+    /* copy all the digits */
+    for (n = 0; n < a->used; n++) {
+      *tmpb++ = *tmpa++;
+    }
+
+    /* clear high digits */
+    for (; n < b->used; n++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  /* copy used count and sign */
+  b->used = a->used;
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_copy.c */
+
+/* Start: bn_mp_count_bits.c */
+#include "tma.h"
+#ifdef BN_MP_COUNT_BITS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* returns the number of bits in an int */
+int
+mp_count_bits (mp_int * a)
+{
+  int     r;
+  mp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+  
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((mp_digit) 0)) {
+    ++r;
+    q >>= ((mp_digit) 1);
+  }
+  return r;
+}
+#endif
+
+/* End: bn_mp_count_bits.c */
+
+/* Start: bn_mp_div.c */
+#include "tma.h"
+#ifdef BN_MP_DIV_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+   mp_int ta, tb, tq, q;
+   int    res, n, n2;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+       
+  /* init our temps */
+  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+     return res;
+  }
+
+
+  mp_set(&tq, 1);
+  n = mp_count_bits(a) - mp_count_bits(b);
+  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+      ((res = mp_abs(b, &tb)) != MP_OKAY) || 
+      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+      goto LBL_ERR;
+  }
+
+  while (n-- >= 0) {
+     if (mp_cmp(&tb, &ta) != MP_GT) {
+        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+           goto LBL_ERR;
+        }
+     }
+     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+           goto LBL_ERR;
+     }
+  }
+
+  /* now q == quotient and ta == remainder */
+  n  = a->sign;
+  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+  if (c != NULL) {
+     mp_exch(c, &q);
+     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+  }
+  if (d != NULL) {
+     mp_exch(d, &ta);
+     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+  }
+LBL_ERR:
+   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+   return res;
+}
+
+#else
+
+/* integer signed division. 
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly 
+ * incomplete.  For example, it doesn't consider 
+ * the case where digits are removed from 'x' in 
+ * the inner loop.  It also doesn't consider the 
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as 
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  mp_int  q, x, y, t1, t2;
+  int     res, n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+    return res;
+  }
+  q.used = a->used + 2;
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    goto LBL_Q;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+    goto LBL_X;
+  }
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+  x.sign = y.sign = MP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = mp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+    goto LBL_Y;
+  }
+
+  while (mp_cmp (&x, &y) != MP_LT) {
+    ++(q.dp[n - t]);
+    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+  }
+
+  /* reset y by shifting it back down */
+  mp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+    } else {
+      mp_word tmp;
+      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+      tmp |= ((mp_word) x.dp[i - 1]);
+      tmp /= ((mp_word) y.dp[t]);
+      if (tmp > (mp_word) MP_MASK)
+        tmp = MP_MASK;
+      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) > 
+             xi * b**2 + xi-1 * b + xi-2 
+     
+       do q{i-t-1} -= 1; 
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+      /* find left hand */
+      mp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == MP_NEG) {
+      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder 
+   * [which we have to normalize] 
+   */
+  
+  /* get sign before writing to c */
+  x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+  if (c != NULL) {
+    mp_clamp (&q);
+    mp_exch (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    mp_div_2d (&x, norm, &x, NULL);
+    mp_exch (&x, d);
+  }
+
+  res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+  return res;
+}
+
+#endif
+
+#endif
+
+/* End: bn_mp_div.c */
+
+/* Start: bn_mp_div_2.c */
+#include "tma.h"
+#ifdef BN_MP_DIV_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* b = a/2 */
+int mp_div_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_div_2.c */
+
+/* Start: bn_mp_div_2d.c */
+#include "tma.h"
+#ifdef BN_MP_DIV_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  mp_digit D, r, rr;
+  int     x, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (mp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register mp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_div_2d.c */
+
+/* Start: bn_mp_div_3.c */
+#include "tma.h"
+#ifdef BN_MP_DIV_3_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* divide by three (based on routine from MPI and the GMP manual) */
+int
+mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
+{
+  mp_int   q;
+  mp_word  w, t;
+  mp_digit b;
+  int      res, ix;
+  
+  /* b = 2**DIGIT_BIT / 3 */
+  b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
+
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+  
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+
+     if (w >= 3) {
+        /* multiply w by [1/3] */
+        t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
+
+        /* now subtract 3 * [w/3] from w, to get the remainder */
+        w -= t+t+t;
+
+        /* fixup the remainder as required since
+         * the optimization is not exact.
+         */
+        while (w >= 3) {
+           t += 1;
+           w -= 3;
+        }
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+
+  /* [optional] store the remainder */
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+
+  /* [optional] store the quotient */
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+  
+  return res;
+}
+
+#endif
+
+/* End: bn_mp_div_3.c */
+
+/* Start: bn_mp_div_d.c */
+#include "tma.h"
+#ifdef BN_MP_DIV_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+static int s_is_power_of_two(mp_digit b, int *p)
+{
+   int x;
+
+   for (x = 1; x < DIGIT_BIT; x++) {
+      if (b == (((mp_digit)1)<<x)) {
+         *p = x;
+         return 1;
+      }
+   }
+   return 0;
+}
+
+/* single digit division (based on routine from MPI) */
+int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+{
+  mp_int  q;
+  mp_word w;
+  mp_digit t;
+  int     res, ix;
+
+  /* cannot divide by zero */
+  if (b == 0) {
+     return MP_VAL;
+  }
+
+  /* quick outs */
+  if (b == 1 || mp_iszero(a) == 1) {
+     if (d != NULL) {
+        *d = 0;
+     }
+     if (c != NULL) {
+        return mp_copy(a, c);
+     }
+     return MP_OKAY;
+  }
+
+  /* power of two ? */
+  if (s_is_power_of_two(b, &ix) == 1) {
+     if (d != NULL) {
+        *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
+     }
+     if (c != NULL) {
+        return mp_div_2d(a, ix, c, NULL);
+     }
+     return MP_OKAY;
+  }
+
+#ifdef BN_MP_DIV_3_C
+  /* three? */
+  if (b == 3) {
+     return mp_div_3(a, c, d);
+  }
+#endif
+
+  /* no easy answer [c'est la vie].  Just division */
+  if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
+     return res;
+  }
+  
+  q.used = a->used;
+  q.sign = a->sign;
+  w = 0;
+  for (ix = a->used - 1; ix >= 0; ix--) {
+     w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
+     
+     if (w >= b) {
+        t = (mp_digit)(w / b);
+        w -= ((mp_word)t) * ((mp_word)b);
+      } else {
+        t = 0;
+      }
+      q.dp[ix] = (mp_digit)t;
+  }
+  
+  if (d != NULL) {
+     *d = (mp_digit)w;
+  }
+  
+  if (c != NULL) {
+     mp_clamp(&q);
+     mp_exch(&q, c);
+  }
+  mp_clear(&q);
+  
+  return res;
+}
+
+#endif
+
+/* End: bn_mp_div_d.c */
+
+/* Start: bn_mp_dr_is_modulus.c */
+#include "tma.h"
+#ifdef BN_MP_DR_IS_MODULUS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* determines if a number is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a)
+{
+   int ix;
+
+   /* must be at least two digits */
+   if (a->used < 2) {
+      return 0;
+   }
+
+   /* must be of the form b**k - a [a <= b] so all
+    * but the first digit must be equal to -1 (mod b).
+    */
+   for (ix = 1; ix < a->used; ix++) {
+       if (a->dp[ix] != MP_MASK) {
+          return 0;
+       }
+   }
+   return 1;
+}
+
+#endif
+
+/* End: bn_mp_dr_is_modulus.c */
+
+/* Start: bn_mp_dr_reduce.c */
+#include "tma.h"
+#ifdef BN_MP_DR_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
+ *
+ * Based on algorithm from the paper
+ *
+ * "Generating Efficient Primes for Discrete Log Cryptosystems"
+ *                 Chae Hoon Lim, Pil Joong Lee,
+ *          POSTECH Information Research Laboratories
+ *
+ * The modulus must be of a special format [see manual]
+ *
+ * Has been modified to use algorithm 7.10 from the LTM book instead
+ *
+ * Input x must be in the range 0 <= x <= (n-1)**2
+ */
+int
+mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
+{
+  int      err, i, m;
+  mp_word  r;
+  mp_digit mu, *tmpx1, *tmpx2;
+
+  /* m = digits in modulus */
+  m = n->used;
+
+  /* ensure that "x" has at least 2m digits */
+  if (x->alloc < m + m) {
+    if ((err = mp_grow (x, m + m)) != MP_OKAY) {
+      return err;
+    }
+  }
+
+/* top of loop, this is where the code resumes if
+ * another reduction pass is required.
+ */
+top:
+  /* aliases for digits */
+  /* alias for lower half of x */
+  tmpx1 = x->dp;
+
+  /* alias for upper half of x, or x/B**m */
+  tmpx2 = x->dp + m;
+
+  /* set carry to zero */
+  mu = 0;
+
+  /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
+  for (i = 0; i < m; i++) {
+      r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
+      *tmpx1++  = (mp_digit)(r & MP_MASK);
+      mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
+  }
+
+  /* set final carry */
+  *tmpx1++ = mu;
+
+  /* zero words above m */
+  for (i = m + 1; i < x->used; i++) {
+      *tmpx1++ = 0;
+  }
+
+  /* clamp, sub and return */
+  mp_clamp (x);
+
+  /* if x >= n then subtract and reduce again
+   * Each successive "recursion" makes the input smaller and smaller.
+   */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    s_mp_sub(x, n, x);
+    goto top;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_dr_reduce.c */
+
+/* Start: bn_mp_dr_setup.c */
+#include "tma.h"
+#ifdef BN_MP_DR_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* determines the setup value */
+void mp_dr_setup(mp_int *a, mp_digit *d)
+{
+   /* the casts are required if DIGIT_BIT is one less than
+    * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
+    */
+   *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 
+        ((mp_word)a->dp[0]));
+}
+
+#endif
+
+/* End: bn_mp_dr_setup.c */
+
+/* Start: bn_mp_exch.c */
+#include "tma.h"
+#ifdef BN_MP_EXCH_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* swap the elements of two integers, for cases where you can't simply swap the 
+ * mp_int pointers around
+ */
+void
+mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+#endif
+
+/* End: bn_mp_exch.c */
+
+/* Start: bn_mp_expt_d.c */
+#include "tma.h"
+#ifdef BN_MP_EXPT_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* calculate c = a**b  using a square-multiply algorithm */
+int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  int     res, x;
+  mp_int  g;
+
+  if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set initial result */
+  mp_set (c, 1);
+
+  for (x = 0; x < (int) DIGIT_BIT; x++) {
+    /* square */
+    if ((res = mp_sqr (c, c)) != MP_OKAY) {
+      mp_clear (&g);
+      return res;
+    }
+
+    /* if the bit is set multiply */
+    if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
+      if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
+         mp_clear (&g);
+         return res;
+      }
+    }
+
+    /* shift to next bit */
+    b <<= 1;
+  }
+
+  mp_clear (&g);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_expt_d.c */
+
+/* Start: bn_mp_exptmod.c */
+#include "tma.h"
+#ifdef BN_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions.  Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted alot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+  int dr;
+
+  /* modulus P must be positive */
+  if (P->sign == MP_NEG) {
+     return MP_VAL;
+  }
+
+  /* if exponent X is negative we have to recurse */
+  if (X->sign == MP_NEG) {
+#ifdef BN_MP_INVMOD_C
+     mp_int tmpG, tmpX;
+     int err;
+
+     /* first compute 1/G mod P */
+     if ((err = mp_init(&tmpG)) != MP_OKAY) {
+        return err;
+     }
+     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+
+     /* now get |X| */
+     if ((err = mp_init(&tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+        mp_clear_multi(&tmpG, &tmpX, NULL);
+        return err;
+     }
+
+     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+     err = mp_exptmod(&tmpG, &tmpX, P, Y);
+     mp_clear_multi(&tmpG, &tmpX, NULL);
+     return err;
+#else 
+     /* no invmod */
+     return MP_VAL;
+#endif
+  }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C)
+  if (mp_reduce_is_2k_l(P) == MP_YES) {
+     return s_mp_exptmod(G, X, P, Y, 1);
+  }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+  /* is it a DR modulus? */
+  dr = mp_dr_is_modulus(P);
+#else
+  /* default to no */
+  dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+  /* if not, is it a unrestricted DR modulus? */
+  if (dr == 0) {
+     dr = mp_reduce_is_2k(P) << 1;
+  }
+#endif
+    
+  /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+  if (mp_isodd (P) == 1 || dr !=  0) {
+    return mp_exptmod_fast (G, X, P, Y, dr);
+  } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+    /* otherwise use the generic Barrett reduction technique */
+    return s_mp_exptmod (G, X, P, Y, 0);
+#else
+    /* no exptmod for evens */
+    return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+  }
+#endif
+}
+
+#endif
+
+/* End: bn_mp_exptmod.c */
+
+/* Start: bn_mp_exptmod_fast.c */
+#include "tma.h"
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res;
+  mp_digit buf, mp;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  int     (*redux)(mp_int*,mp_int*,mp_digit);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+  if (winsize > 5) {
+     winsize = 5;
+  }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* determine and setup reduction code */
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C     
+     /* now setup montgomery  */
+     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+
+     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+     if (((P->used * 2 + 1) < MP_WARRAY) &&
+          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+        redux = fast_mp_montgomery_reduce;
+     } else 
+#endif
+     {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+        /* use slower baseline Montgomery method */
+        redux = mp_montgomery_reduce;
+#else
+        err = MP_VAL;
+        goto LBL_M;
+#endif
+     }
+  } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+     /* setup DR reduction for moduli of the form B**k - b */
+     mp_dr_setup(P, &mp);
+     redux = mp_dr_reduce;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+     /* setup DR reduction for moduli of the form 2**k - b */
+     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+     redux = mp_reduce_2k;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  /* create M table
+   *
+
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+     /* now we need R mod m */
+     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+#else 
+     err = MP_VAL;
+     goto LBL_RES;
+#endif
+
+     /* now set M[1] to G * R mod m */
+     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  } else {
+     mp_set(&res, 1);
+     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+        goto LBL_RES;
+     }
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_RES;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  if (redmode == 0) {
+     /* fixup result if Montgomery reduction is used
+      * recall that any value in a Montgomery system is
+      * actually multiplied by R mod n.  So we have
+      * to reduce one more time to cancel out the factor
+      * of R.
+      */
+     if ((err = redux(&res, P, mp)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  }
+
+  /* swap res with Y */
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+
+/* End: bn_mp_exptmod_fast.c */
+
+/* Start: bn_mp_exteuclid.c */
+#include "tma.h"
+#ifdef BN_MP_EXTEUCLID_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* Extended euclidean algorithm of (a, b) produces 
+   a*u1 + b*u2 = u3
+ */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
+{
+   mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
+   int err;
+
+   if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
+      return err;
+   }
+
+   /* initialize, (u1,u2,u3) = (1,0,a) */
+   mp_set(&u1, 1);
+   if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }
+
+   /* initialize, (v1,v2,v3) = (0,1,b) */
+   mp_set(&v2, 1);
+   if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }
+
+   /* loop while v3 != 0 */
+   while (mp_iszero(&v3) == MP_NO) {
+       /* q = u3/v3 */
+       if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }
+
+       /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
+       if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
+       if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
+       if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }
+
+       /* (u1,u2,u3) = (v1,v2,v3) */
+       if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }
+
+       /* (v1,v2,v3) = (t1,t2,t3) */
+       if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
+       if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
+   }
+
+   /* make sure U3 >= 0 */
+   if (u3.sign == MP_NEG) {
+      mp_neg(&u1, &u1);
+      mp_neg(&u2, &u2);
+      mp_neg(&u3, &u3);
+   }
+
+   /* copy result out */
+   if (U1 != NULL) { mp_exch(U1, &u1); }
+   if (U2 != NULL) { mp_exch(U2, &u2); }
+   if (U3 != NULL) { mp_exch(U3, &u3); }
+
+   err = MP_OKAY;
+_ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
+   return err;
+}
+#endif
+
+/* End: bn_mp_exteuclid.c */
+
+/* Start: bn_mp_fread.c */
+#include "tma.h"
+#ifdef BN_MP_FREAD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* read a bigint from a file stream in ASCII */
+int mp_fread(mp_int *a, int radix, FILE *stream)
+{
+   int err, ch, neg, y;
+   
+   /* clear a */
+   mp_zero(a);
+   
+   /* if first digit is - then set negative */
+   ch = fgetc(stream);
+   if (ch == '-') {
+      neg = MP_NEG;
+      ch = fgetc(stream);
+   } else {
+      neg = MP_ZPOS;
+   }
+   
+   for (;;) {
+      /* find y in the radix map */
+      for (y = 0; y < radix; y++) {
+          if (mp_s_rmap[y] == ch) {
+             break;
+          }
+      }
+      if (y == radix) {
+         break;
+      }
+      
+      /* shift up and add */
+      if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
+         return err;
+      }
+      if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
+         return err;
+      }
+      
+      ch = fgetc(stream);
+   }
+   if (mp_cmp_d(a, 0) != MP_EQ) {
+      a->sign = neg;
+   }
+   
+   return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_fread.c */
+
+/* Start: bn_mp_fwrite.c */
+#include "tma.h"
+#ifdef BN_MP_FWRITE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+int mp_fwrite(mp_int *a, int radix, FILE *stream)
+{
+   char *buf;
+   int err, len, x;
+   
+   if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
+      return err;
+   }
+
+   buf = OPT_CAST(char) XMALLOC (len);
+   if (buf == NULL) {
+      return MP_MEM;
+   }
+   
+   if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
+      XFREE (buf);
+      return err;
+   }
+   
+   for (x = 0; x < len; x++) {
+       if (fputc(buf[x], stream) == EOF) {
+          XFREE (buf);
+          return MP_VAL;
+       }
+   }
+   
+   XFREE (buf);
+   return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_fwrite.c */
+
+/* Start: bn_mp_gcd.c */
+#include "tma.h"
+#ifdef BN_MP_GCD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* Greatest Common Divisor using the binary method */
+int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  u, v;
+  int     k, u_lsb, v_lsb, res;
+
+  /* either zero than gcd is the largest */
+  if (mp_iszero (a) == 1 && mp_iszero (b) == 0) {
+    return mp_abs (b, c);
+  }
+  if (mp_iszero (a) == 0 && mp_iszero (b) == 1) {
+    return mp_abs (a, c);
+  }
+
+  /* optimized.  At this point if a == 0 then
+   * b must equal zero too
+   */
+  if (mp_iszero (a) == 1) {
+    mp_zero(c);
+    return MP_OKAY;
+  }
+
+  /* get copies of a and b we can modify */
+  if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
+    goto LBL_U;
+  }
+
+  /* must be positive for the remainder of the algorithm */
+  u.sign = v.sign = MP_ZPOS;
+
+  /* B1.  Find the common power of two for u and v */
+  u_lsb = mp_cnt_lsb(&u);
+  v_lsb = mp_cnt_lsb(&v);
+  k     = MIN(u_lsb, v_lsb);
+
+  if (k > 0) {
+     /* divide the power of two out */
+     if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+
+     if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  /* divide any remaining factors of two out */
+  if (u_lsb != k) {
+     if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  if (v_lsb != k) {
+     if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     }
+  }
+
+  while (mp_iszero(&v) == 0) {
+     /* make sure v is the largest */
+     if (mp_cmp_mag(&u, &v) == MP_GT) {
+        /* swap u and v to make sure v is >= u */
+        mp_exch(&u, &v);
+     }
+     
+     /* subtract smallest from largest */
+     if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
+        goto LBL_V;
+     }
+     
+     /* Divide out all factors of two */
+     if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
+        goto LBL_V;
+     } 
+  } 
+
+  /* multiply by 2**k which we divided out at the beginning */
+  if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
+     goto LBL_V;
+  }
+  c->sign = MP_ZPOS;
+  res = MP_OKAY;
+LBL_V:mp_clear (&u);
+LBL_U:mp_clear (&v);
+  return res;
+}
+#endif
+
+/* End: bn_mp_gcd.c */
+
+/* Start: bn_mp_get_int.c */
+#include "tma.h"
+#ifdef BN_MP_GET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* get the lower 32-bits of an mp_int */
+unsigned long mp_get_int(mp_int * a) 
+{
+  int i;
+  unsigned long res;
+
+  if (a->used == 0) {
+     return 0;
+  }
+
+  /* get number of digits of the lsb we have to read */
+  i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
+
+  /* get most significant digit of result */
+  res = DIGIT(a,i);
+   
+  while (--i >= 0) {
+    res = (res << DIGIT_BIT) | DIGIT(a,i);
+  }
+
+  /* force result to 32-bits always so it is consistent on non 32-bit platforms */
+  return res & 0xFFFFFFFFUL;
+}
+#endif
+
+/* End: bn_mp_get_int.c */
+
+/* Start: bn_mp_grow.c */
+#include "tma.h"
+#ifdef BN_MP_GROW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* grow as required */
+int mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_grow.c */
+
+/* Start: bn_mp_init.c */
+#include "tma.h"
+#ifdef BN_MP_INIT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* init a new mp_int */
+int mp_init (mp_int * a)
+{
+  int i;
+
+  /* allocate memory required and clear it */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the digits to zero */
+  for (i = 0; i < MP_PREC; i++) {
+      a->dp[i] = 0;
+  }
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = MP_PREC;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_init.c */
+
+/* Start: bn_mp_init_copy.c */
+#include "tma.h"
+#ifdef BN_MP_INIT_COPY_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* creates "a" then copies b into it */
+int mp_init_copy (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_init (a)) != MP_OKAY) {
+    return res;
+  }
+  return mp_copy (b, a);
+}
+#endif
+
+/* End: bn_mp_init_copy.c */
+
+/* Start: bn_mp_init_multi.c */
+#include "tma.h"
+#ifdef BN_MP_INIT_MULTI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+#include <stdarg.h>
+
+int mp_init_multi(mp_int *mp, ...) 
+{
+    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
+    int n = 0;                 /* Number of ok inits */
+    mp_int* cur_arg = mp;
+    va_list args;
+
+    va_start(args, mp);        /* init args to next argument from caller */
+    while (cur_arg != NULL) {
+        if (mp_init(cur_arg) != MP_OKAY) {
+            /* Oops - error! Back-track and mp_clear what we already
+               succeeded in init-ing, then return error.
+            */
+            va_list clean_args;
+            
+            /* end the current list */
+            va_end(args);
+            
+            /* now start cleaning up */            
+            cur_arg = mp;
+            va_start(clean_args, mp);
+            while (n--) {
+                mp_clear(cur_arg);
+                cur_arg = va_arg(clean_args, mp_int*);
+            }
+            va_end(clean_args);
+            res = MP_MEM;
+            break;
+        }
+        n++;
+        cur_arg = va_arg(args, mp_int*);
+    }
+    va_end(args);
+    return res;                /* Assumed ok, if error flagged above. */
+}
+
+#endif
+
+/* End: bn_mp_init_multi.c */
+
+/* Start: bn_mp_init_set.c */
+#include "tma.h"
+#ifdef BN_MP_INIT_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b)
+{
+  int err;
+  if ((err = mp_init(a)) != MP_OKAY) {
+     return err;
+  }
+  mp_set(a, b);
+  return err;
+}
+#endif
+
+/* End: bn_mp_init_set.c */
+
+/* Start: bn_mp_init_set_int.c */
+#include "tma.h"
+#ifdef BN_MP_INIT_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* initialize and set a digit */
+int mp_init_set_int (mp_int * a, unsigned long b)
+{
+  int err;
+  if ((err = mp_init(a)) != MP_OKAY) {
+     return err;
+  }
+  return mp_set_int(a, b);
+}
+#endif
+
+/* End: bn_mp_init_set_int.c */
+
+/* Start: bn_mp_init_size.c */
+#include "tma.h"
+#ifdef BN_MP_INIT_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* init an mp_init for a given size */
+int mp_init_size (mp_int * a, int size)
+{
+  int x;
+
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);    
+  
+  /* alloc mem */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the members */
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_init_size.c */
+
+/* Start: bn_mp_invmod.c */
+#include "tma.h"
+#ifdef BN_MP_INVMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+#ifdef BN_FAST_MP_INVMOD_C
+  /* if the modulus is odd we can use a faster routine instead */
+  if (mp_isodd (b) == 1) {
+    return fast_mp_invmod (a, b, c);
+  }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+  return mp_invmod_slow(a, b, c);
+#endif
+
+  return MP_VAL;
+}
+#endif
+
+/* End: bn_mp_invmod.c */
+
+/* Start: bn_mp_invmod_slow.c */
+#include "tma.h"
+#ifdef BN_MP_INVMOD_SLOW_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* hac 14.61, pp608 */
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, A, B, C, D;
+  int     res;
+
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+  /* init temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v, 
+                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x = a, y = b */
+  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+      goto LBL_ERR;
+  }
+  if ((res = mp_copy (b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 2. [modified] if x,y are both even then return an error! */
+  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  mp_set (&A, 1);
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if A or B is odd then */
+    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+      /* A = (A+y)/2, B = (B-x)/2 */
+      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* A = A/2, B = B/2 */
+    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if C or D is odd then */
+    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+      /* C = (C+y)/2, D = (D-x)/2 */
+      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* C = C/2, D = D/2 */
+    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, A = A - C, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, C = C - A, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0)
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* if its too low */
+  while (mp_cmp_d(&C, 0) == MP_LT) {
+      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  
+  /* too big */
+  while (mp_cmp_mag(&C, b) != MP_LT) {
+      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+  
+  /* C is now the inverse */
+  mp_exch (&C, c);
+  res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+  return res;
+}
+#endif
+
+/* End: bn_mp_invmod_slow.c */
+
+/* Start: bn_mp_is_square.c */
+#include "tma.h"
+#ifdef BN_MP_IS_SQUARE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* Check if remainders are possible squares - fast exclude non-squares */
+static const char rem_128[128] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
+};
+
+static const char rem_105[105] = {
+ 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
+ 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
+ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
+};
+
+/* Store non-zero to ret if arg is square, and zero if not */
+int mp_is_square(mp_int *arg,int *ret) 
+{
+  int           res;
+  mp_digit      c;
+  mp_int        t;
+  unsigned long r;
+
+  /* Default to Non-square :) */
+  *ret = MP_NO; 
+
+  if (arg->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  /* digits used?  (TSD) */
+  if (arg->used == 0) {
+     return MP_OKAY;
+  }
+
+  /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
+  if (rem_128[127 & DIGIT(arg,0)] == 1) {
+     return MP_OKAY;
+  }
+
+  /* Next check mod 105 (3*5*7) */
+  if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
+     return res;
+  }
+  if (rem_105[c] == 1) {
+     return MP_OKAY;
+  }
+
+
+  if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
+     return res;
+  }
+  if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+  r = mp_get_int(&t);
+  /* Check for other prime modules, note it's not an ERROR but we must
+   * free "t" so the easiest way is to goto ERR.  We know that res
+   * is already equal to MP_OKAY from the mp_mod call 
+   */ 
+  if ( (1L<<(r%11)) & 0x5C4L )             goto ERR;
+  if ( (1L<<(r%13)) & 0x9E4L )             goto ERR;
+  if ( (1L<<(r%17)) & 0x5CE8L )            goto ERR;
+  if ( (1L<<(r%19)) & 0x4F50CL )           goto ERR;
+  if ( (1L<<(r%23)) & 0x7ACCA0L )          goto ERR;
+  if ( (1L<<(r%29)) & 0xC2EDD0CL )         goto ERR;
+  if ( (1L<<(r%31)) & 0x6DE2B848L )        goto ERR;
+
+  /* Final check - is sqr(sqrt(arg)) == arg ? */
+  if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+  if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
+     goto ERR;
+  }
+
+  *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
+ERR:mp_clear(&t);
+  return res;
+}
+#endif
+
+/* End: bn_mp_is_square.c */
+
+/* Start: bn_mp_jacobi.c */
+#include "tma.h"
+#ifdef BN_MP_JACOBI_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* computes the jacobi c = (a | n) (or Legendre if n is prime)
+ * HAC pp. 73 Algorithm 2.149
+ */
+int mp_jacobi (mp_int * a, mp_int * p, int *c)
+{
+  mp_int  a1, p1;
+  int     k, s, r, res;
+  mp_digit residue;
+
+  /* if p <= 0 return MP_VAL */
+  if (mp_cmp_d(p, 0) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* step 1.  if a == 0, return 0 */
+  if (mp_iszero (a) == 1) {
+    *c = 0;
+    return MP_OKAY;
+  }
+
+  /* step 2.  if a == 1, return 1 */
+  if (mp_cmp_d (a, 1) == MP_EQ) {
+    *c = 1;
+    return MP_OKAY;
+  }
+
+  /* default */
+  s = 0;
+
+  /* step 3.  write a = a1 * 2**k  */
+  if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init (&p1)) != MP_OKAY) {
+    goto LBL_A1;
+  }
+
+  /* divide out larger power of two */
+  k = mp_cnt_lsb(&a1);
+  if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
+     goto LBL_P1;
+  }
+
+  /* step 4.  if e is even set s=1 */
+  if ((k & 1) == 0) {
+    s = 1;
+  } else {
+    /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
+    residue = p->dp[0] & 7;
+
+    if (residue == 1 || residue == 7) {
+      s = 1;
+    } else if (residue == 3 || residue == 5) {
+      s = -1;
+    }
+  }
+
+  /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
+  if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
+    s = -s;
+  }
+
+  /* if a1 == 1 we're done */
+  if (mp_cmp_d (&a1, 1) == MP_EQ) {
+    *c = s;
+  } else {
+    /* n1 = n mod a1 */
+    if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
+      goto LBL_P1;
+    }
+    if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
+      goto LBL_P1;
+    }
+    *c = s * r;
+  }
+
+  /* done */
+  res = MP_OKAY;
+LBL_P1:mp_clear (&p1);
+LBL_A1:mp_clear (&a1);
+  return res;
+}
+#endif
+
+/* End: bn_mp_jacobi.c */
+
+/* Start: bn_mp_karatsuba_mul.c */
+#include "tma.h"
+#ifdef BN_MP_KARATSUBA_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* c = |a| * |b| using Karatsuba Multiplication using 
+ * three half size multiplications
+ *
+ * Let B represent the radix [e.g. 2**DIGIT_BIT] and 
+ * let n represent half of the number of digits in 
+ * the min(a,b)
+ *
+ * a = a1 * B**n + a0
+ * b = b1 * B**n + b0
+ *
+ * Then, a * b => 
+   a1b1 * B**2n + ((a1 - a0)(b1 - b0) + a0b0 + a1b1) * B + a0b0
+ *
+ * Note that a1b1 and a0b0 are used twice and only need to be 
+ * computed once.  So in total three half size (half # of 
+ * digit) multiplications are performed, a0b0, a1b1 and 
+ * (a1-b1)(a0-b0)
+ *
+ * Note that a multiplication of half the digits requires
+ * 1/4th the number of single precision multiplications so in 
+ * total after one call 25% of the single precision multiplications 
+ * are saved.  Note also that the call to mp_mul can end up back 
+ * in this function if the a0, a1, b0, or b1 are above the threshold.  
+ * This is known as divide-and-conquer and leads to the famous 
+ * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than 
+ * the standard O(N**2) that the baseline/comba methods use.  
+ * Generally though the overhead of this method doesn't pay off 
+ * until a certain size (N ~ 80) is reached.
+ */
+int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x0, x1, y0, y1, t1, x0y0, x1y1;
+  int     B, err;
+
+  /* default the return code to an error */
+  err = MP_MEM;
+
+  /* min # of digits */
+  B = MIN (a->used, b->used);
+
+  /* now divide in two */
+  B = B >> 1;
+
+  /* init copy all the temps */
+  if (mp_init_size (&x0, B) != MP_OKAY)
+    goto ERR;
+  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+    goto X0;
+  if (mp_init_size (&y0, B) != MP_OKAY)
+    goto X1;
+  if (mp_init_size (&y1, b->used - B) != MP_OKAY)
+    goto Y0;
+
+  /* init temps */
+  if (mp_init_size (&t1, B * 2) != MP_OKAY)
+    goto Y1;
+  if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
+    goto T1;
+  if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
+    goto X0Y0;
+
+  /* now shift the digits */
+  x0.used = y0.used = B;
+  x1.used = a->used - B;
+  y1.used = b->used - B;
+
+  {
+    register int x;
+    register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
+
+    /* we copy the digits directly instead of using higher level functions
+     * since we also need to shift the digits
+     */
+    tmpa = a->dp;
+    tmpb = b->dp;
+
+    tmpx = x0.dp;
+    tmpy = y0.dp;
+    for (x = 0; x < B; x++) {
+      *tmpx++ = *tmpa++;
+      *tmpy++ = *tmpb++;
+    }
+
+    tmpx = x1.dp;
+    for (x = B; x < a->used; x++) {
+      *tmpx++ = *tmpa++;
+    }
+
+    tmpy = y1.dp;
+    for (x = B; x < b->used; x++) {
+      *tmpy++ = *tmpb++;
+    }
+  }
+
+  /* only need to clamp the lower words since by definition the 
+   * upper words x1/y1 must have a known number of digits
+   */
+  mp_clamp (&x0);
+  mp_clamp (&y0);
+
+  /* now calc the products x0y0 and x1y1 */
+  /* after this x0 is no longer required, free temp [x0==t2]! */
+  if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)  
+    goto X1Y1;          /* x0y0 = x0*y0 */
+  if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
+    goto X1Y1;          /* x1y1 = x1*y1 */
+
+  /* now calc x1-x0 and y1-y0 */
+  if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x1 - x0 */
+  if (mp_sub (&y1, &y0, &x0) != MP_OKAY)
+    goto X1Y1;          /* t2 = y1 - y0 */
+  if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = (x1 - x0) * (y1 - y0) */
+
+  /* add x0y0 */
+  if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
+    goto X1Y1;          /* t2 = x0y0 + x1y1 */
+  if (mp_sub (&x0, &t1, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */
+
+  /* shift by B */
+  if (mp_lshd (&t1, B) != MP_OKAY)
+    goto X1Y1;          /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+  if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
+    goto X1Y1;          /* x1y1 = x1y1 << 2*B */
+
+  if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + t1 */
+  if (mp_add (&t1, &x1y1, c) != MP_OKAY)
+    goto X1Y1;          /* t1 = x0y0 + t1 + x1y1 */
+
+  /* Algorithm succeeded set the return code to MP_OKAY */
+  err = MP_OKAY;
+
+X1Y1:mp_clear (&x1y1);
+X0Y0:mp_clear (&x0y0);
+T1:mp_clear (&t1);
+Y1:mp_clear (&y1);
+Y0:mp_clear (&y0);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+  return err;
+}
+#endif
+
+/* End: bn_mp_karatsuba_mul.c */
+
+/* Start: bn_mp_karatsuba_sqr.c */
+#include "tma.h"
+#ifdef BN_MP_KARATSUBA_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* Karatsuba squaring, computes b = a*a using three 
+ * half size squarings
+ *
+ * See comments of karatsuba_mul for details.  It 
+ * is essentially the same algorithm but merely 
+ * tuned to perform recursive squarings.
+ */
+int mp_karatsuba_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  x0, x1, t1, t2, x0x0, x1x1;
+  int     B, err;
+
+  err = MP_MEM;
+
+  /* min # of digits */
+  B = a->used;
+
+  /* now divide in two */
+  B = B >> 1;
+
+  /* init copy all the temps */
+  if (mp_init_size (&x0, B) != MP_OKAY)
+    goto ERR;
+  if (mp_init_size (&x1, a->used - B) != MP_OKAY)
+    goto X0;
+
+  /* init temps */
+  if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
+    goto X1;
+  if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
+    goto T1;
+  if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
+    goto T2;
+  if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
+    goto X0X0;
+
+  {
+    register int x;
+    register mp_digit *dst, *src;
+
+    src = a->dp;
+
+    /* now shift the digits */
+    dst = x0.dp;
+    for (x = 0; x < B; x++) {
+      *dst++ = *src++;
+    }
+
+    dst = x1.dp;
+    for (x = B; x < a->used; x++) {
+      *dst++ = *src++;
+    }
+  }
+
+  x0.used = B;
+  x1.used = a->used - B;
+
+  mp_clamp (&x0);
+
+  /* now calc the products x0*x0 and x1*x1 */
+  if (mp_sqr (&x0, &x0x0) != MP_OKAY)
+    goto X1X1;           /* x0x0 = x0*x0 */
+  if (mp_sqr (&x1, &x1x1) != MP_OKAY)
+    goto X1X1;           /* x1x1 = x1*x1 */
+
+  /* now calc (x1-x0)**2 */
+  if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x1 - x0 */
+  if (mp_sqr (&t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = (x1 - x0) * (x1 - x0) */
+
+  /* add x0y0 */
+  if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
+    goto X1X1;           /* t2 = x0x0 + x1x1 */
+  if (mp_sub (&t2, &t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + x1x1 - (x1-x0)*(x1-x0) */
+
+  /* shift by B */
+  if (mp_lshd (&t1, B) != MP_OKAY)
+    goto X1X1;           /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
+  if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
+    goto X1X1;           /* x1x1 = x1x1 << 2*B */
+
+  if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + t1 */
+  if (mp_add (&t1, &x1x1, b) != MP_OKAY)
+    goto X1X1;           /* t1 = x0x0 + t1 + x1x1 */
+
+  err = MP_OKAY;
+
+X1X1:mp_clear (&x1x1);
+X0X0:mp_clear (&x0x0);
+T2:mp_clear (&t2);
+T1:mp_clear (&t1);
+X1:mp_clear (&x1);
+X0:mp_clear (&x0);
+ERR:
+  return err;
+}
+#endif
+
+/* End: bn_mp_karatsuba_sqr.c */
+
+/* Start: bn_mp_lcm.c */
+#include "tma.h"
+#ifdef BN_MP_LCM_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* computes least common multiple as |a*b|/(a, b) */
+int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t1, t2;
+
+
+  if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
+    return res;
+  }
+
+  /* t1 = get the GCD of the two inputs */
+  if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
+    goto LBL_T;
+  }
+
+  /* divide the smallest by the GCD */
+  if (mp_cmp_mag(a, b) == MP_LT) {
+     /* store quotient in t2 such that t2 * b is the LCM */
+     if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
+        goto LBL_T;
+     }
+     res = mp_mul(b, &t2, c);
+  } else {
+     /* store quotient in t2 such that t2 * a is the LCM */
+     if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
+        goto LBL_T;
+     }
+     res = mp_mul(a, &t2, c);
+  }
+
+  /* fix the sign to positive */
+  c->sign = MP_ZPOS;
+
+LBL_T:
+  mp_clear_multi (&t1, &t2, NULL);
+  return res;
+}
+#endif
+
+/* End: bn_mp_lcm.c */
+
+/* Start: bn_mp_lshd.c */
+#include "tma.h"
+#ifdef BN_MP_LSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* shift left a certain amount of digits */
+int mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    register mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the otherway around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_lshd.c */
+
+/* Start: bn_mp_mod.c */
+#include "tma.h"
+#ifdef BN_MP_MOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* c = a mod b, 0 <= c < b */
+int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  t;
+  int     res;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  if (t.sign != b->sign) {
+    res = mp_add (b, &t, c);
+  } else {
+    res = MP_OKAY;
+    mp_exch (&t, c);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* End: bn_mp_mod.c */
+
+/* Start: bn_mp_mod_2d.c */
+#include "tma.h"
+#ifdef BN_MP_MOD_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* calc a value mod 2**b */
+int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b >= (int) (a->used * DIGIT_BIT)) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &=
+    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_mod_2d.c */
+
+/* Start: bn_mp_mod_d.c */
+#include "tma.h"
+#ifdef BN_MP_MOD_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+int
+mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
+{
+  return mp_div_d(a, b, NULL, c);
+}
+#endif
+
+/* End: bn_mp_mod_d.c */
+
+/* Start: bn_mp_montgomery_calc_normalization.c */
+#include "tma.h"
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally upto just under
+ * the leading bit of b.  This saves alot of multiple precision shifting.
+ */
+int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+        return res;
+     }
+  } else {
+     mp_set(a, 1);
+     bits = 1;
+  }
+
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_montgomery_calc_normalization.c */
+
+/* Start: bn_mp_montgomery_reduce.c */
+#include "tma.h"
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* computes xR**-1 == x (mod N) via Montgomery Reduction */
+int
+mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, digs;
+  mp_digit mu;
+
+  /* can the fast reduction [comba] method be used?
+   *
+   * Note that unlike in mul you're safely allowed *less*
+   * than the available columns [255 per default] since carries
+   * are fixed up in the inner loop.
+   */
+  digs = n->used * 2 + 1;
+  if ((digs < MP_WARRAY) &&
+      n->used <
+      (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_mp_montgomery_reduce (x, n, rho);
+  }
+
+  /* grow the input as required */
+  if (x->alloc < digs) {
+    if ((res = mp_grow (x, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+  x->used = digs;
+
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * rho mod b
+     *
+     * The value of rho must be precalculated via
+     * montgomery_setup() such that
+     * it equals -1/n0 mod b this allows the
+     * following inner loop to reduce the
+     * input one digit at a time
+     */
+    mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i */
+    {
+      register int iy;
+      register mp_digit *tmpn, *tmpx, u;
+      register mp_word r;
+
+      /* alias for digits of the modulus */
+      tmpn = n->dp;
+
+      /* alias for the digits of x [the input] */
+      tmpx = x->dp + ix;
+
+      /* set the carry to zero */
+      u = 0;
+
+      /* Multiply and add in place */
+      for (iy = 0; iy < n->used; iy++) {
+        /* compute product and sum */
+        r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
+                  ((mp_word) u) + ((mp_word) * tmpx);
+
+        /* get carry */
+        u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+        /* fix digit */
+        *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
+      }
+      /* At this point the ix'th digit of x should be zero */
+
+
+      /* propagate carries upwards as required*/
+      while (u) {
+        *tmpx   += u;
+        u        = *tmpx >> DIGIT_BIT;
+        *tmpx++ &= MP_MASK;
+      }
+    }
+  }
+
+  /* at this point the n.used'th least
+   * significant digits of x are all zero
+   * which means we can shift x to the
+   * right by n.used digits and the
+   * residue is unchanged.
+   */
+
+  /* x = x/b**n.used */
+  mp_clamp(x);
+  mp_rshd (x, n->used);
+
+  /* if x >= n then x = x - n */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_montgomery_reduce.c */
+
+/* Start: bn_mp_montgomery_setup.c */
+#include "tma.h"
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* setups the montgomery reduction stuff */
+int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_montgomery_setup.c */
+
+/* Start: bn_mp_mul.c */
+#include "tma.h"
+#ifdef BN_MP_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* high level multiplication (handles sign) */
+int mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, neg;
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+  /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+    res = mp_toom_mul(a, b, c);
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+  /* use Karatsuba? */
+  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+    res = mp_karatsuba_mul (a, b, c);
+  } else 
+#endif
+  {
+    /* can we use the fast multiplier?
+     *
+     * The fast multiplier can be used if the output will 
+     * have less than MP_WARRAY digits and the number of 
+     * digits won't affect carry propagation
+     */
+    int     digs = a->used + b->used + 1;
+
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+    if ((digs < MP_WARRAY) &&
+        MIN(a->used, b->used) <= 
+        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+      res = fast_s_mp_mul_digs (a, b, c, digs);
+    } else 
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+      res = MP_VAL;
+#endif
+
+  }
+  c->sign = (c->used > 0) ? neg : MP_ZPOS;
+  return res;
+}
+#endif
+
+/* End: bn_mp_mul.c */
+
+/* Start: bn_mp_mul_2.c */
+#include "tma.h"
+#ifdef BN_MP_MUL_2_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* b = a*2 */
+int mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accomodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+    
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+    
+      /* get what will be the *next* carry bit from the 
+       * MSB of the current digit 
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+      
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+      
+      /* copy the carry that would be from the source 
+       * digit into the next iteration 
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination 
+     * that we didn't write to 
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_mul_2.c */
+
+/* Start: bn_mp_mul_2d.c */
+#include "tma.h"
+#ifdef BN_MP_MUL_2D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* shift left by a certain bit count */
+int mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    register mp_digit *tmpc, shift, mask, r, rr;
+    register int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = ((*tmpc << d) | r) & MP_MASK;
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+    
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_mul_2d.c */
+
+/* Start: bn_mp_mul_d.c */
+#include "tma.h"
+#ifdef BN_MP_MUL_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* multiply by a digit */
+int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] and increment ix offset  */
+  *tmpc++ = u;
+  ++ix;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_mul_d.c */
+
+/* Start: bn_mp_mulmod.c */
+#include "tma.h"
+#ifdef BN_MP_MULMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* d = a * b (mod c) */
+int
+mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* End: bn_mp_mulmod.c */
+
+/* Start: bn_mp_n_root.c */
+#include "tma.h"
+#ifdef BN_MP_N_ROOT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* find the n'th root of an integer 
+ *
+ * Result found such that (c)**b <= a and (c+1)**b > a 
+ *
+ * This algorithm uses Newton's approximation 
+ * x[i+1] = x[i] - f(x[i])/f'(x[i]) 
+ * which will find the root in log(N) time where 
+ * each step involves a fair bit.  This is not meant to 
+ * find huge roots [square and cube, etc].
+ */
+int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_int  t1, t2, t3;
+  int     res, neg;
+
+  /* input must be positive if b is even */
+  if ((b & 1) == 0 && a->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init (&t3)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  /* if a is negative fudge the sign but keep track */
+  neg     = a->sign;
+  a->sign = MP_ZPOS;
+
+  /* t2 = 2 */
+  mp_set (&t2, 2);
+
+  do {
+    /* t1 = t2 */
+    if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
+      goto LBL_T3;
+    }
+
+    /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
+    
+    /* t3 = t1**(b-1) */
+    if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {   
+      goto LBL_T3;
+    }
+
+    /* numerator */
+    /* t2 = t1**b */
+    if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {    
+      goto LBL_T3;
+    }
+
+    /* t2 = t1**b - a */
+    if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {  
+      goto LBL_T3;
+    }
+
+    /* denominator */
+    /* t3 = t1**(b-1) * b  */
+    if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {    
+      goto LBL_T3;
+    }
+
+    /* t3 = (t1**b - a)/(b * t1**(b-1)) */
+    if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {  
+      goto LBL_T3;
+    }
+
+    if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
+      goto LBL_T3;
+    }
+  }  while (mp_cmp (&t1, &t2) != MP_EQ);
+
+  /* result can be off by a few so check */
+  for (;;) {
+    if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
+      goto LBL_T3;
+    }
+
+    if (mp_cmp (&t2, a) == MP_GT) {
+      if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
+         goto LBL_T3;
+      }
+    } else {
+      break;
+    }
+  }
+
+  /* reset the sign of a first */
+  a->sign = neg;
+
+  /* set the result */
+  mp_exch (&t1, c);
+
+  /* set the sign of the result */
+  c->sign = neg;
+
+  res = MP_OKAY;
+
+LBL_T3:mp_clear (&t3);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+  return res;
+}
+#endif
+
+/* End: bn_mp_n_root.c */
+
+/* Start: bn_mp_neg.c */
+#include "tma.h"
+#ifdef BN_MP_NEG_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* b = -a */
+int mp_neg (mp_int * a, mp_int * b)
+{
+  int     res;
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  if (mp_iszero(b) != MP_YES) {
+     b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+  } else {
+     b->sign = MP_ZPOS;
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_neg.c */
+
+/* Start: bn_mp_or.c */
+#include "tma.h"
+#ifdef BN_MP_OR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* OR two ints together */
+int mp_or (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+    t.dp[ix] |= x->dp[ix];
+  }
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_or.c */
+
+/* Start: bn_mp_prime_fermat.c */
+#include "tma.h"
+#ifdef BN_MP_PRIME_FERMAT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* performs one Fermat test.
+ * 
+ * If "a" were prime then b**a == b (mod a) since the order of
+ * the multiplicative sub-group would be phi(a) = a-1.  That means
+ * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
+ *
+ * Sets result to 1 if the congruence holds, or zero otherwise.
+ */
+int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  t;
+  int     err;
+
+  /* default to composite  */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }
+
+  /* init t */
+  if ((err = mp_init (&t)) != MP_OKAY) {
+    return err;
+  }
+
+  /* compute t = b**a mod a */
+  if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
+    goto LBL_T;
+  }
+
+  /* is it equal to b? */
+  if (mp_cmp (&t, b) == MP_EQ) {
+    *result = MP_YES;
+  }
+
+  err = MP_OKAY;
+LBL_T:mp_clear (&t);
+  return err;
+}
+#endif
+
+/* End: bn_mp_prime_fermat.c */
+
+/* Start: bn_mp_prime_is_divisible.c */
+#include "tma.h"
+#ifdef BN_MP_PRIME_IS_DIVISIBLE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* determines if an integers is divisible by one 
+ * of the first PRIME_SIZE primes or not
+ *
+ * sets result to 0 if not, 1 if yes
+ */
+int mp_prime_is_divisible (mp_int * a, int *result)
+{
+  int     err, ix;
+  mp_digit res;
+
+  /* default to not */
+  *result = MP_NO;
+
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+    /* what is a mod LBL_prime_tab[ix] */
+    if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
+      return err;
+    }
+
+    /* is the residue zero? */
+    if (res == 0) {
+      *result = MP_YES;
+      return MP_OKAY;
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_prime_is_divisible.c */
+
+/* Start: bn_mp_prime_is_prime.c */
+#include "tma.h"
+#ifdef BN_MP_PRIME_IS_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+  mp_int  b;
+  int     ix, err, res;
+
+  /* default to no */
+  *result = MP_NO;
+
+  /* valid value of t? */
+  if (t <= 0 || t > PRIME_SIZE) {
+    return MP_VAL;
+  }
+
+  /* is the input equal to one of the primes in the table? */
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+      if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
+         *result = 1;
+         return MP_OKAY;
+      }
+  }
+
+  /* first perform trial division */
+  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+    return err;
+  }
+
+  /* return if it was trivially divisible */
+  if (res == MP_YES) {
+    return MP_OKAY;
+  }
+
+  /* now perform the miller-rabin rounds */
+  if ((err = mp_init (&b)) != MP_OKAY) {
+    return err;
+  }
+
+  for (ix = 0; ix < t; ix++) {
+    /* set the prime */
+    mp_set (&b, ltm_prime_tab[ix]);
+
+    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+      goto LBL_B;
+    }
+
+    if (res == MP_NO) {
+      goto LBL_B;
+    }
+  }
+
+  /* passed the test */
+  *result = MP_YES;
+LBL_B:mp_clear (&b);
+  return err;
+}
+#endif
+
+/* End: bn_mp_prime_is_prime.c */
+
+/* Start: bn_mp_prime_miller_rabin.c */
+#include "tma.h"
+#ifdef BN_MP_PRIME_MILLER_RABIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* Miller-Rabin test of "a" to the base of "b" as described in 
+ * HAC pp. 139 Algorithm 4.24
+ *
+ * Sets result to 0 if definitely composite or 1 if probably prime.
+ * Randomly the chance of error is no more than 1/4 and often 
+ * very much lower.
+ */
+int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
+{
+  mp_int  n1, y, r;
+  int     s, j, err;
+
+  /* default */
+  *result = MP_NO;
+
+  /* ensure b > 1 */
+  if (mp_cmp_d(b, 1) != MP_GT) {
+     return MP_VAL;
+  }     
+
+  /* get n1 = a - 1 */
+  if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
+    return err;
+  }
+  if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
+    goto LBL_N1;
+  }
+
+  /* set 2**s * r = n1 */
+  if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
+    goto LBL_N1;
+  }
+
+  /* count the number of least significant bits
+   * which are zero
+   */
+  s = mp_cnt_lsb(&r);
+
+  /* now divide n - 1 by 2**s */
+  if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
+    goto LBL_R;
+  }
+
+  /* compute y = b**r mod a */
+  if ((err = mp_init (&y)) != MP_OKAY) {
+    goto LBL_R;
+  }
+  if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
+    goto LBL_Y;
+  }
+
+  /* if y != 1 and y != n1 do */
+  if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
+    j = 1;
+    /* while j <= s-1 and y != n1 */
+    while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
+      if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
+         goto LBL_Y;
+      }
+
+      /* if y == 1 then composite */
+      if (mp_cmp_d (&y, 1) == MP_EQ) {
+         goto LBL_Y;
+      }
+
+      ++j;
+    }
+
+    /* if y != n1 then composite */
+    if (mp_cmp (&y, &n1) != MP_EQ) {
+      goto LBL_Y;
+    }
+  }
+
+  /* probably prime now */
+  *result = MP_YES;
+LBL_Y:mp_clear (&y);
+LBL_R:mp_clear (&r);
+LBL_N1:mp_clear (&n1);
+  return err;
+}
+#endif
+
+/* End: bn_mp_prime_miller_rabin.c */
+
+/* Start: bn_mp_prime_next_prime.c */
+#include "tma.h"
+#ifdef BN_MP_PRIME_NEXT_PRIME_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
+{
+   int      err, res, x, y;
+   mp_digit res_tab[PRIME_SIZE], step, kstep;
+   mp_int   b;
+
+   /* ensure t is valid */
+   if (t <= 0 || t > PRIME_SIZE) {
+      return MP_VAL;
+   }
+
+   /* force positive */
+   a->sign = MP_ZPOS;
+
+   /* simple algo if a is less than the largest prime in the table */
+   if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
+      /* find which prime it is bigger than */
+      for (x = PRIME_SIZE - 2; x >= 0; x--) {
+          if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
+             if (bbs_style == 1) {
+                /* ok we found a prime smaller or
+                 * equal [so the next is larger]
+                 *
+                 * however, the prime must be
+                 * congruent to 3 mod 4
+                 */
+                if ((ltm_prime_tab[x + 1] & 3) != 3) {
+                   /* scan upwards for a prime congruent to 3 mod 4 */
+                   for (y = x + 1; y < PRIME_SIZE; y++) {
+                       if ((ltm_prime_tab[y] & 3) == 3) {
+                          mp_set(a, ltm_prime_tab[y]);
+                          return MP_OKAY;
+                       }
+                   }
+                }
+             } else {
+                mp_set(a, ltm_prime_tab[x + 1]);
+                return MP_OKAY;
+             }
+          }
+      }
+      /* at this point a maybe 1 */
+      if (mp_cmp_d(a, 1) == MP_EQ) {
+         mp_set(a, 2);
+         return MP_OKAY;
+      }
+      /* fall through to the sieve */
+   }
+
+   /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
+   if (bbs_style == 1) {
+      kstep   = 4;
+   } else {
+      kstep   = 2;
+   }
+
+   /* at this point we will use a combination of a sieve and Miller-Rabin */
+
+   if (bbs_style == 1) {
+      /* if a mod 4 != 3 subtract the correct value to make it so */
+      if ((a->dp[0] & 3) != 3) {
+         if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
+      }
+   } else {
+      if (mp_iseven(a) == 1) {
+         /* force odd */
+         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
+            return err;
+         }
+      }
+   }
+
+   /* generate the restable */
+   for (x = 1; x < PRIME_SIZE; x++) {
+      if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
+         return err;
+      }
+   }
+
+   /* init temp used for Miller-Rabin Testing */
+   if ((err = mp_init(&b)) != MP_OKAY) {
+      return err;
+   }
+
+   for (;;) {
+      /* skip to the next non-trivially divisible candidate */
+      step = 0;
+      do {
+         /* y == 1 if any residue was zero [e.g. cannot be prime] */
+         y     =  0;
+
+         /* increase step to next candidate */
+         step += kstep;
+
+         /* compute the new residue without using division */
+         for (x = 1; x < PRIME_SIZE; x++) {
+             /* add the step to each residue */
+             res_tab[x] += kstep;
+
+             /* subtract the modulus [instead of using division] */
+             if (res_tab[x] >= ltm_prime_tab[x]) {
+                res_tab[x]  -= ltm_prime_tab[x];
+             }
+
+             /* set flag if zero */
+             if (res_tab[x] == 0) {
+                y = 1;
+             }
+         }
+      } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));
+
+      /* add the step */
+      if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+
+      /* if didn't pass sieve and step == MAX then skip test */
+      if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
+         continue;
+      }
+
+      /* is this prime? */
+      for (x = 0; x < t; x++) {
+          mp_set(&b, ltm_prime_tab[t]);
+          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
+             goto LBL_ERR;
+          }
+          if (res == MP_NO) {
+             break;
+          }
+      }
+
+      if (res == MP_YES) {
+         break;
+      }
+   }
+
+   err = MP_OKAY;
+LBL_ERR:
+   mp_clear(&b);
+   return err;
+}
+
+#endif
+
+/* End: bn_mp_prime_next_prime.c */
+
+/* Start: bn_mp_prime_rabin_miller_trials.c */
+#include "tma.h"
+#ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+
+static const struct {
+   int k, t;
+} sizes[] = {
+{   128,    28 },
+{   256,    16 },
+{   384,    10 },
+{   512,     7 },
+{   640,     6 },
+{   768,     5 },
+{   896,     4 },
+{  1024,     4 }
+};
+
+/* returns # of RM trials required for a given bit size */
+int mp_prime_rabin_miller_trials(int size)
+{
+   int x;
+
+   for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
+       if (sizes[x].k == size) {
+          return sizes[x].t;
+       } else if (sizes[x].k > size) {
+          return (x == 0) ? sizes[0].t : sizes[x - 1].t;
+       }
+   }
+   return sizes[x-1].t + 1;
+}
+
+
+#endif
+
+/* End: bn_mp_prime_rabin_miller_trials.c */
+
+/* Start: bn_mp_prime_random_ex.c */
+#include "tma.h"
+#ifdef BN_MP_PRIME_RANDOM_EX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ * 
+ *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
+{
+   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+   int res, err, bsize, maskOR_msb_offset;
+
+   /* sanity check the input */
+   if (size <= 1 || t <= 0) {
+      return MP_VAL;
+   }
+
+   /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
+   if (flags & LTM_PRIME_SAFE) {
+      flags |= LTM_PRIME_BBS;
+   }
+
+   /* calc the byte size */
+   bsize = (size>>3) + ((size&7)?1:0);
+
+   /* we need a buffer of bsize bytes */
+   tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
+   if (tmp == NULL) {
+      return MP_MEM;
+   }
+
+   /* calc the maskAND value for the MSbyte*/
+   maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));
+
+   /* calc the maskOR_msb */
+   maskOR_msb        = 0;
+   maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
+   if (flags & LTM_PRIME_2MSB_ON) {
+      maskOR_msb     |= 1 << ((size - 2) & 7);
+   } else if (flags & LTM_PRIME_2MSB_OFF) {
+      maskAND        &= ~(1 << ((size - 2) & 7));
+   } 
+
+   /* get the maskOR_lsb */
+   maskOR_lsb         = 1;
+   if (flags & LTM_PRIME_BBS) {
+      maskOR_lsb     |= 3;
+   }
+
+   do {
+      /* read the bytes */
+      if (cb(tmp, bsize, dat) != bsize) {
+         err = MP_VAL;
+         goto error;
+      }
+      /* work over the MSbyte */
+      tmp[0]    &= maskAND;
+      tmp[0]    |= 1 << ((size - 1) & 7);
+
+      /* mix in the maskORs */
+      tmp[maskOR_msb_offset]   |= maskOR_msb;
+      tmp[bsize-1]             |= maskOR_lsb;
+
+      /* read it in */
+      if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY)     { goto error; }
+
+      /* is it prime? */
+      if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)           { goto error; }
+      if (res == MP_NO) {  
+         continue;
+      }
+
+      if (flags & LTM_PRIME_SAFE) {
+         /* see if (a-1)/2 is prime */
+         if ((err = mp_sub_d(a, 1, a)) != MP_OKAY)                    { goto error; }
+         if ((err = mp_div_2(a, a)) != MP_OKAY)                       { goto error; }
+         /* is it prime? */
+         if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)        { goto error; }
+      }
+   } while (res == MP_NO);
+
+   if (flags & LTM_PRIME_SAFE) {
+      /* restore a to the original value */
+      if ((err = mp_mul_2(a, a)) != MP_OKAY)                          { goto error; }
+      if ((err = mp_add_d(a, 1, a)) != MP_OKAY)                       { goto error; }
+   }
+
+   err = MP_OKAY;
+error:
+   XFREE(tmp);
+   return err;
+}
+
+
+#endif
+
+/* End: bn_mp_prime_random_ex.c */
+
+/* Start: bn_mp_radix_size.c */
+#include "tma.h"
+#ifdef BN_MP_RADIX_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* returns size of ASCII reprensentation */
+int mp_radix_size (mp_int * a, int radix, int *size)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+
+  *size = 0;
+
+  /* special case for binary */
+  if (radix == 2) {
+    *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
+    return MP_OKAY;
+  }
+
+  /* make sure the radix is in range */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  if (mp_iszero(a) == MP_YES) {
+     *size = 2;
+    return MP_OKAY;
+  }
+
+  /* digs is the digit count */
+  digs = 0;
+
+  /* if it's negative add one for the sign */
+  if (a->sign == MP_NEG) {
+    ++digs;
+  }
+
+  /* init a copy of the input */
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* force temp to positive */
+  t.sign = MP_ZPOS; 
+
+  /* fetch out all of the digits */
+  while (mp_iszero (&t) == MP_NO) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    ++digs;
+  }
+  mp_clear (&t);
+
+  /* return digs + 1, the 1 is for the NULL byte that would be required. */
+  *size = digs + 1;
+  return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_radix_size.c */
+
+/* Start: bn_mp_radix_smap.c */
+#include "tma.h"
+#ifdef BN_MP_RADIX_SMAP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* chars used in radix conversions */
+const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+#endif
+
+/* End: bn_mp_radix_smap.c */
+
+/* Start: bn_mp_rand.c */
+#include "tma.h"
+#ifdef BN_MP_RAND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* makes a pseudo-random int of a given size */
+int
+mp_rand (mp_int * a, int digits)
+{
+  int     res;
+  mp_digit d;
+
+  mp_zero (a);
+  if (digits <= 0) {
+    return MP_OKAY;
+  }
+
+  /* first place a random non-zero digit */
+  do {
+    d = ((mp_digit) abs (rand ())) & MP_MASK;
+  } while (d == 0);
+
+  if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
+    return res;
+  }
+
+  while (--digits > 0) {
+    if ((res = mp_lshd (a, 1)) != MP_OKAY) {
+      return res;
+    }
+
+    if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_rand.c */
+
+/* Start: bn_mp_read_radix.c */
+#include "tma.h"
+#ifdef BN_MP_READ_RADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* read a string [ASCII] in a given radix */
+int mp_read_radix (mp_int * a, const char *str, int radix)
+{
+  int     y, res, neg;
+  char    ch;
+
+  /* make sure the radix is ok */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* if the leading digit is a 
+   * minus set the sign to negative. 
+   */
+  if (*str == '-') {
+    ++str;
+    neg = MP_NEG;
+  } else {
+    neg = MP_ZPOS;
+  }
+
+  /* set the integer to the default of zero */
+  mp_zero (a);
+  
+  /* process each digit of the string */
+  while (*str) {
+    /* if the radix < 36 the conversion is case insensitive
+     * this allows numbers like 1AB and 1ab to represent the same  value
+     * [e.g. in hex]
+     */
+    ch = (char) ((radix < 36) ? toupper (*str) : *str);
+    for (y = 0; y < 64; y++) {
+      if (ch == mp_s_rmap[y]) {
+         break;
+      }
+    }
+
+    /* if the char was found in the map 
+     * and is less than the given radix add it
+     * to the number, otherwise exit the loop. 
+     */
+    if (y < radix) {
+      if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
+         return res;
+      }
+      if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
+         return res;
+      }
+    } else {
+      break;
+    }
+    ++str;
+  }
+  
+  /* set the sign only if a != 0 */
+  if (mp_iszero(a) != 1) {
+     a->sign = neg;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_read_radix.c */
+
+/* Start: bn_mp_read_signed_bin.c */
+#include "tma.h"
+#ifdef BN_MP_READ_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* read signed bin, big endian, first byte is 0==positive or 1==negative */
+int
+mp_read_signed_bin (mp_int * a, unsigned char *b, int c)
+{
+  int     res;
+
+  /* read magnitude */
+  if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* first byte is 0 for positive, non-zero for negative */
+  if (b[0] == 0) {
+     a->sign = MP_ZPOS;
+  } else {
+     a->sign = MP_NEG;
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_read_signed_bin.c */
+
+/* Start: bn_mp_read_unsigned_bin.c */
+#include "tma.h"
+#ifdef BN_MP_READ_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+int
+mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c)
+{
+  int     res;
+
+  /* make sure there are at least two digits */
+  if (a->alloc < 2) {
+     if ((res = mp_grow(a, 2)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero the int */
+  mp_zero (a);
+
+  /* read the bytes in */
+  while (c-- > 0) {
+    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+      return res;
+    }
+
+#ifndef MP_8BIT
+      a->dp[0] |= *b++;
+      a->used += 1;
+#else
+      a->dp[0] = (*b & MP_MASK);
+      a->dp[1] |= ((*b++ >> 7U) & 1);
+      a->used += 2;
+#endif
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_read_unsigned_bin.c */
+
+/* Start: bn_mp_reduce.c */
+#include "tma.h"
+#ifdef BN_MP_REDUCE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is 
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+  mp_int  q;
+  int     res, um = m->used;
+
+  /* q = x */
+  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+    return res;
+  }
+
+  /* q1 = x / b**(k-1)  */
+  mp_rshd (&q, um - 1);         
+
+  /* according to HAC this optimization is ok */
+  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#else 
+    { 
+      res = MP_VAL;
+      goto CLEANUP;
+    }
+#endif
+  }
+
+  /* q3 = q2 / b**(k+1) */
+  mp_rshd (&q, um + 1);         
+
+  /* x = x mod b**(k+1), quick (no division) */
+  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* x = x - q */
+  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* If x < 0, add b**(k+1) to it */
+  if (mp_cmp_d (x, 0) == MP_LT) {
+    mp_set (&q, 1);
+    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
+      goto CLEANUP;
+    if ((res = mp_add (x, &q, x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  /* Back off if it's too big */
+  while (mp_cmp (x, m) != MP_LT) {
+    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+  
+CLEANUP:
+  mp_clear (&q);
+
+  return res;
+}
+#endif
+
+/* End: bn_mp_reduce.c */
+
+/* Start: bn_mp_reduce_2k.c */
+#include "tma.h"
+#ifdef BN_MP_REDUCE_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (d != 1) {
+      /* q = q * d */
+      if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 
+         goto ERR;
+      }
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+#endif
+
+/* End: bn_mp_reduce_2k.c */
+
+/* Start: bn_mp_reduce_2k_l.c */
+#include "tma.h"
+#ifdef BN_MP_REDUCE_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* reduces a modulo n where n is of the form 2**p - d 
+   This differs from reduce_2k since "d" can be larger
+   than a single digit.
+*/
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+   mp_int q;
+   int    p, res;
+   
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(n);    
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   /* q = q * d */
+   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { 
+      goto ERR;
+   }
+   
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+   
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+#endif
+
+/* End: bn_mp_reduce_2k_l.c */
+
+/* Start: bn_mp_reduce_2k_setup.c */
+#include "tma.h"
+#ifdef BN_MP_REDUCE_2K_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
+{
+   int res, p;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   p = mp_count_bits(a);
+   if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
+      mp_clear(&tmp);
+      return res;
+   }
+   
+   *d = tmp.dp[0];
+   mp_clear(&tmp);
+   return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_reduce_2k_setup.c */
+
+/* Start: bn_mp_reduce_2k_setup_l.c */
+#include "tma.h"
+#ifdef BN_MP_REDUCE_2K_SETUP_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* determines the setup value */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+   int    res;
+   mp_int tmp;
+   
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+   
+   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+      goto ERR;
+   }
+   
+   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+      goto ERR;
+   }
+   
+ERR:
+   mp_clear(&tmp);
+   return res;
+}
+#endif
+
+/* End: bn_mp_reduce_2k_setup_l.c */
+
+/* Start: bn_mp_reduce_is_2k.c */
+#include "tma.h"
+#ifdef BN_MP_REDUCE_IS_2K_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* determines if mp_reduce_2k can be used */
+int mp_reduce_is_2k(mp_int *a)
+{
+   int ix, iy, iw;
+   mp_digit iz;
+   
+   if (a->used == 0) {
+      return MP_NO;
+   } else if (a->used == 1) {
+      return MP_YES;
+   } else if (a->used > 1) {
+      iy = mp_count_bits(a);
+      iz = 1;
+      iw = 1;
+    
+      /* Test every bit from the second digit up, must be 1 */
+      for (ix = DIGIT_BIT; ix < iy; ix++) {
+          if ((a->dp[iw] & iz) == 0) {
+             return MP_NO;
+          }
+          iz <<= 1;
+          if (iz > (mp_digit)MP_MASK) {
+             ++iw;
+             iz = 1;
+          }
+      }
+   }
+   return MP_YES;
+}
+
+#endif
+
+/* End: bn_mp_reduce_is_2k.c */
+
+/* Start: bn_mp_reduce_is_2k_l.c */
+#include "tma.h"
+#ifdef BN_MP_REDUCE_IS_2K_L_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* determines if reduce_2k_l can be used */
+int mp_reduce_is_2k_l(mp_int *a)
+{
+   int ix, iy;
+   
+   if (a->used == 0) {
+      return MP_NO;
+   } else if (a->used == 1) {
+      return MP_YES;
+   } else if (a->used > 1) {
+      /* if more than half of the digits are -1 we're sold */
+      for (iy = ix = 0; ix < a->used; ix++) {
+          if (a->dp[ix] == MP_MASK) {
+              ++iy;
+          }
+      }
+      return (iy >= (a->used/2)) ? MP_YES : MP_NO;
+      
+   }
+   return MP_NO;
+}
+
+#endif
+
+/* End: bn_mp_reduce_is_2k_l.c */
+
+/* Start: bn_mp_reduce_setup.c */
+#include "tma.h"
+#ifdef BN_MP_REDUCE_SETUP_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+int mp_reduce_setup (mp_int * a, mp_int * b)
+{
+  int     res;
+  
+  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+    return res;
+  }
+  return mp_div (a, b, a, NULL);
+}
+#endif
+
+/* End: bn_mp_reduce_setup.c */
+
+/* Start: bn_mp_rshd.c */
+#include "tma.h"
+#ifdef BN_MP_RSHD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* shift right a certain amount of digits */
+void mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    register mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where 
+     * the window is b-digits long and digits from 
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+  
+  /* remove excess digits */
+  a->used -= b;
+}
+#endif
+
+/* End: bn_mp_rshd.c */
+
+/* Start: bn_mp_set.c */
+#include "tma.h"
+#ifdef BN_MP_SET_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* set to a digit */
+void mp_set (mp_int * a, mp_digit b)
+{
+  mp_zero (a);
+  a->dp[0] = b & MP_MASK;
+  a->used  = (a->dp[0] != 0) ? 1 : 0;
+}
+#endif
+
+/* End: bn_mp_set.c */
+
+/* Start: bn_mp_set_int.c */
+#include "tma.h"
+#ifdef BN_MP_SET_INT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* set a 32-bit const */
+int mp_set_int (mp_int * a, unsigned long b)
+{
+  int     x, res;
+
+  mp_zero (a);
+  
+  /* set four bits at a time */
+  for (x = 0; x < 8; x++) {
+    /* shift the number up four bits */
+    if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
+      return res;
+    }
+
+    /* OR in the top four bits of the source */
+    a->dp[0] |= (b >> 28) & 15;
+
+    /* shift the source up to the next four bits */
+    b <<= 4;
+
+    /* ensure that digits are not clamped off */
+    a->used += 1;
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_set_int.c */
+
+/* Start: bn_mp_shrink.c */
+#include "tma.h"
+#ifdef BN_MP_SHRINK_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* shrink a bignum */
+int mp_shrink (mp_int * a)
+{
+  mp_digit *tmp;
+  if (a->alloc != a->used && a->used > 0) {
+    if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
+      return MP_MEM;
+    }
+    a->dp    = tmp;
+    a->alloc = a->used;
+  }
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_shrink.c */
+
+/* Start: bn_mp_signed_bin_size.c */
+#include "tma.h"
+#ifdef BN_MP_SIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* get the size for an signed equivalent */
+int mp_signed_bin_size (mp_int * a)
+{
+  return 1 + mp_unsigned_bin_size (a);
+}
+#endif
+
+/* End: bn_mp_signed_bin_size.c */
+
+/* Start: bn_mp_sqr.c */
+#include "tma.h"
+#ifdef BN_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* computes b = a*a */
+int
+mp_sqr (mp_int * a, mp_int * b)
+{
+  int     res;
+
+#ifdef BN_MP_TOOM_SQR_C
+  /* use Toom-Cook? */
+  if (a->used >= TOOM_SQR_CUTOFF) {
+    res = mp_toom_sqr(a, b);
+  /* Karatsuba? */
+  } else 
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+    res = mp_karatsuba_sqr (a, b);
+  } else 
+#endif
+  {
+#ifdef BN_FAST_S_MP_SQR_C
+    /* can we use the fast comba multiplier? */
+    if ((a->used * 2 + 1) < MP_WARRAY && 
+         a->used < 
+         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+      res = fast_s_mp_sqr (a, b);
+    } else
+#endif
+#ifdef BN_S_MP_SQR_C
+      res = s_mp_sqr (a, b);
+#else
+      res = MP_VAL;
+#endif
+  }
+  b->sign = MP_ZPOS;
+  return res;
+}
+#endif
+
+/* End: bn_mp_sqr.c */
+
+/* Start: bn_mp_sqrmod.c */
+#include "tma.h"
+#ifdef BN_MP_SQRMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* c = a * a (mod b) */
+int
+mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sqr (a, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, b, c);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* End: bn_mp_sqrmod.c */
+
+/* Start: bn_mp_sqrt.c */
+#include "tma.h"
+#ifdef BN_MP_SQRT_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* this function is less generic than mp_n_root, simpler and faster */
+int mp_sqrt(mp_int *arg, mp_int *ret) 
+{
+  int res;
+  mp_int t1,t2;
+
+  /* must be positive */
+  if (arg->sign == MP_NEG) {
+    return MP_VAL;
+  }
+
+  /* easy out */
+  if (mp_iszero(arg) == MP_YES) {
+    mp_zero(ret);
+    return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_init(&t2)) != MP_OKAY) {
+    goto E2;
+  }
+
+  /* First approx. (not very bad for large arg) */
+  mp_rshd (&t1,t1.used/2);
+
+  /* t1 > 0  */ 
+  if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+    goto E1;
+  }
+  if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+    goto E1;
+  }
+  if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+    goto E1;
+  }
+  /* And now t1 > sqrt(arg) */
+  do { 
+    if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
+      goto E1;
+    }
+    if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
+      goto E1;
+    }
+    if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
+      goto E1;
+    }
+    /* t1 >= sqrt(arg) >= t2 at this point */
+  } while (mp_cmp_mag(&t1,&t2) == MP_GT);
+
+  mp_exch(&t1,ret);
+
+E1: mp_clear(&t2);
+E2: mp_clear(&t1);
+  return res;
+}
+
+#endif
+
+/* End: bn_mp_sqrt.c */
+
+/* Start: bn_mp_sub.c */
+#include "tma.h"
+#ifdef BN_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* high level subtraction (handles signs) */
+int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      res = s_mp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+      /* The second has a larger magnitude */
+      res = s_mp_sub (b, a, c);
+    }
+  }
+  return res;
+}
+
+#endif
+
+/* End: bn_mp_sub.c */
+
+/* Start: bn_mp_sub_d.c */
+#include "tma.h"
+#ifdef BN_MP_SUB_D_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* single digit subtraction */
+int
+mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit *tmpa, *tmpc, mu;
+  int       res, ix, oldused;
+
+  /* grow c as required */
+  if (c->alloc < a->used + 1) {
+     if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* if a is negative just do an unsigned
+   * addition [with fudged signs]
+   */
+  if (a->sign == MP_NEG) {
+     a->sign = MP_ZPOS;
+     res     = mp_add_d(a, b, c);
+     a->sign = c->sign = MP_NEG;
+     return res;
+  }
+
+  /* setup regs */
+  oldused = c->used;
+  tmpa    = a->dp;
+  tmpc    = c->dp;
+
+  /* if a <= b simply fix the single digit */
+  if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
+     if (a->used == 1) {
+        *tmpc++ = b - *tmpa;
+     } else {
+        *tmpc++ = b;
+     }
+     ix      = 1;
+
+     /* negative/1digit */
+     c->sign = MP_NEG;
+     c->used = 1;
+  } else {
+     /* positive/size */
+     c->sign = MP_ZPOS;
+     c->used = a->used;
+
+     /* subtract first digit */
+     *tmpc    = *tmpa++ - b;
+     mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+     *tmpc++ &= MP_MASK;
+
+     /* handle rest of the digits */
+     for (ix = 1; ix < a->used; ix++) {
+        *tmpc    = *tmpa++ - mu;
+        mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
+        *tmpc++ &= MP_MASK;
+     }
+  }
+
+  /* zero excess digits */
+  while (ix++ < oldused) {
+     *tmpc++ = 0;
+  }
+  mp_clamp(c);
+  return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_sub_d.c */
+
+/* Start: bn_mp_submod.c */
+#include "tma.h"
+#ifdef BN_MP_SUBMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* d = a - b (mod c) */
+int
+mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+#endif
+
+/* End: bn_mp_submod.c */
+
+/* Start: bn_mp_to_signed_bin.c */
+#include "tma.h"
+#ifdef BN_MP_TO_SIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin (mp_int * a, unsigned char *b)
+{
+  int     res;
+
+  if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
+    return res;
+  }
+  b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_to_signed_bin.c */
+
+/* Start: bn_mp_to_signed_bin_n.c */
+#include "tma.h"
+#ifdef BN_MP_TO_SIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* store in signed [big endian] format */
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+   if (*outlen < (unsigned long)mp_signed_bin_size(a)) {
+      return MP_VAL;
+   }
+   *outlen = mp_signed_bin_size(a);
+   return mp_to_signed_bin(a, b);
+}
+#endif
+
+/* End: bn_mp_to_signed_bin_n.c */
+
+/* Start: bn_mp_to_unsigned_bin.c */
+#include "tma.h"
+#ifdef BN_MP_TO_UNSIGNED_BIN_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+  int     x, res;
+  mp_int  t;
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  x = 0;
+  while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+      b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+  bn_reverse (b, x);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_to_unsigned_bin.c */
+
+/* Start: bn_mp_to_unsigned_bin_n.c */
+#include "tma.h"
+#ifdef BN_MP_TO_UNSIGNED_BIN_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* store in unsigned [big endian] format */
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
+{
+   if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
+      return MP_VAL;
+   }
+   *outlen = mp_unsigned_bin_size(a);
+   return mp_to_unsigned_bin(a, b);
+}
+#endif
+
+/* End: bn_mp_to_unsigned_bin_n.c */
+
+/* Start: bn_mp_toom_mul.c */
+#include "tma.h"
+#ifdef BN_MP_TOOM_MUL_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* multiplication using the Toom-Cook 3-way algorithm 
+ *
+ * Much more complicated than Karatsuba but has a lower 
+ * asymptotic running time of O(N**1.464).  This algorithm is 
+ * only particularly useful on VERY large inputs 
+ * (we're talking 1000s of digits here...).
+*/
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
+{
+    mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
+    int res, B;
+        
+    /* init temps */
+    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
+                             &a0, &a1, &a2, &b0, &b1, 
+                             &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
+       return res;
+    }
+    
+    /* B */
+    B = MIN(a->used, b->used) / 3;
+    
+    /* a = a2 * B**2 + a1 * B + a0 */
+    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a1, B);
+    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a2, B*2);
+    
+    /* b = b2 * B**2 + b1 * B + b0 */
+    if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(b, &b1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&b1, B);
+    mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
+
+    if ((res = mp_copy(b, &b2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&b2, B*2);
+    
+    /* w0 = a0*b0 */
+    if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w4 = a2 * b2 */
+    if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
+    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
+    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+
+    /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
+    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
+       goto ERR;
+    }
+    
+    /* now solve the matrix 
+    
+       0  0  0  0  1
+       1  2  4  8  16
+       1  1  1  1  1
+       16 8  4  2  1
+       1  0  0  0  0
+       
+       using 12 subtractions, 4 shifts, 
+              2 small divisions and 1 small multiplication 
+     */
+     
+     /* r1 - r4 */
+     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r0 */
+     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/2 */
+     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/2 */
+     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r2 - r0 - r4 */
+     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - 8r0 */
+     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - 8r4 */
+     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* 3r2 - r1 - r3 */
+     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/3 */
+     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/3 */
+     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     
+     /* at this point shift W[n] by B*n */
+     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+        goto ERR;
+     }     
+     
+     if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
+        goto ERR;
+     }     
+     
+ERR:
+     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
+                    &a0, &a1, &a2, &b0, &b1, 
+                    &b2, &tmp1, &tmp2, NULL);
+     return res;
+}     
+     
+#endif
+
+/* End: bn_mp_toom_mul.c */
+
+/* Start: bn_mp_toom_sqr.c */
+#include "tma.h"
+#ifdef BN_MP_TOOM_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* squaring using Toom-Cook 3-way algorithm */
+int
+mp_toom_sqr(mp_int *a, mp_int *b)
+{
+    mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
+    int res, B;
+
+    /* init temps */
+    if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
+       return res;
+    }
+
+    /* B */
+    B = a->used / 3;
+
+    /* a = a2 * B**2 + a1 * B + a0 */
+    if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_copy(a, &a1)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a1, B);
+    mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
+
+    if ((res = mp_copy(a, &a2)) != MP_OKAY) {
+       goto ERR;
+    }
+    mp_rshd(&a2, B*2);
+
+    /* w0 = a0*a0 */
+    if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w4 = a2 * a2 */
+    if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w1 = (a2 + 2(a1 + 2a0))**2 */
+    if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* w3 = (a0 + 2(a1 + 2a2))**2 */
+    if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
+       goto ERR;
+    }
+
+
+    /* w2 = (a2 + a1 + a0)**2 */
+    if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
+       goto ERR;
+    }
+    if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
+       goto ERR;
+    }
+
+    /* now solve the matrix
+
+       0  0  0  0  1
+       1  2  4  8  16
+       1  1  1  1  1
+       16 8  4  2  1
+       1  0  0  0  0
+
+       using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
+     */
+
+     /* r1 - r4 */
+     if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r0 */
+     if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/2 */
+     if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/2 */
+     if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r2 - r0 - r4 */
+     if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - 8r0 */
+     if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - 8r4 */
+     if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* 3r2 - r1 - r3 */
+     if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1 - r2 */
+     if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3 - r2 */
+     if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r1/3 */
+     if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+     /* r3/3 */
+     if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
+        goto ERR;
+     }
+
+     /* at this point shift W[n] by B*n */
+     if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
+        goto ERR;
+     }
+
+     if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
+        goto ERR;
+     }
+     if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
+        goto ERR;
+     }
+
+ERR:
+     mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
+     return res;
+}
+
+#endif
+
+/* End: bn_mp_toom_sqr.c */
+
+/* Start: bn_mp_toradix.c */
+#include "tma.h"
+#ifdef BN_MP_TORADIX_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64) */
+int mp_toradix (mp_int * a, char *str, int radix)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+  char   *_s = str;
+
+  /* check range of the radix */
+  if (radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* quick out if its zero */
+  if (mp_iszero(a) == 1) {
+     *str++ = '0';
+     *str = '\0';
+     return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* if it is negative output a - */
+  if (t.sign == MP_NEG) {
+    ++_s;
+    *str++ = '-';
+    t.sign = MP_ZPOS;
+  }
+
+  digs = 0;
+  while (mp_iszero (&t) == 0) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    *str++ = mp_s_rmap[d];
+    ++digs;
+  }
+
+  /* reverse the digits of the string.  In this case _s points
+   * to the first digit [exluding the sign] of the number]
+   */
+  bn_reverse ((unsigned char *)_s, digs);
+
+  /* append a NULL so the string is properly terminated */
+  *str = '\0';
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_toradix.c */
+
+/* Start: bn_mp_toradix_n.c */
+#include "tma.h"
+#ifdef BN_MP_TORADIX_N_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* stores a bignum as a ASCII string in a given radix (2..64) 
+ *
+ * Stores upto maxlen-1 chars and always a NULL byte 
+ */
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
+{
+  int     res, digs;
+  mp_int  t;
+  mp_digit d;
+  char   *_s = str;
+
+  /* check range of the maxlen, radix */
+  if (maxlen < 3 || radix < 2 || radix > 64) {
+    return MP_VAL;
+  }
+
+  /* quick out if its zero */
+  if (mp_iszero(a) == 1) {
+     *str++ = '0';
+     *str = '\0';
+     return MP_OKAY;
+  }
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  /* if it is negative output a - */
+  if (t.sign == MP_NEG) {
+    /* we have to reverse our digits later... but not the - sign!! */
+    ++_s;
+
+    /* store the flag and mark the number as positive */
+    *str++ = '-';
+    t.sign = MP_ZPOS;
+    /* subtract a char */
+    --maxlen;
+  }
+
+  digs = 0;
+  while (mp_iszero (&t) == 0) {
+    if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+    *str++ = mp_s_rmap[d];
+    ++digs;
+
+    if (--maxlen == 1) {
+       /* no more room */
+       break;
+    }
+  }
+
+  /* reverse the digits of the string.  In this case _s points
+   * to the first digit [exluding the sign] of the number]
+   */
+  bn_reverse ((unsigned char *)_s, digs);
+
+  /* append a NULL so the string is properly terminated */
+  *str = '\0';
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_mp_toradix_n.c */
+
+/* Start: bn_mp_unsigned_bin_size.c */
+#include "tma.h"
+#ifdef BN_MP_UNSIGNED_BIN_SIZE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* get the size for an unsigned equivalent */
+int mp_unsigned_bin_size (mp_int * a)
+{
+  int     size = mp_count_bits (a);
+  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+#endif
+
+/* End: bn_mp_unsigned_bin_size.c */
+
+/* Start: bn_mp_xor.c */
+#include "tma.h"
+#ifdef BN_MP_XOR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* XOR two ints together */
+int
+mp_xor (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, ix, px;
+  mp_int  t, *x;
+
+  if (a->used > b->used) {
+    if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+      return res;
+    }
+    px = b->used;
+    x = b;
+  } else {
+    if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
+      return res;
+    }
+    px = a->used;
+    x = a;
+  }
+
+  for (ix = 0; ix < px; ix++) {
+     t.dp[ix] ^= x->dp[ix];
+  }
+  mp_clamp (&t);
+  mp_exch (c, &t);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_mp_xor.c */
+
+/* Start: bn_mp_zero.c */
+#include "tma.h"
+#ifdef BN_MP_ZERO_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* set to zero */
+void mp_zero (mp_int * a)
+{
+  int       n;
+  mp_digit *tmp;
+
+  a->sign = MP_ZPOS;
+  a->used = 0;
+
+  tmp = a->dp;
+  for (n = 0; n < a->alloc; n++) {
+     *tmp++ = 0;
+  }
+}
+#endif
+
+/* End: bn_mp_zero.c */
+
+/* Start: bn_prime_tab.c */
+#include "tma.h"
+#ifdef BN_PRIME_TAB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+const mp_digit ltm_prime_tab[] = {
+  0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
+  0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
+  0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
+  0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
+#ifndef MP_8BIT
+  0x0083,
+  0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
+  0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
+  0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
+  0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
+
+  0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
+  0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
+  0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
+  0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
+  0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
+  0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
+  0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
+  0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
+
+  0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
+  0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
+  0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
+  0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
+  0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
+  0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
+  0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
+  0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
+
+  0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
+  0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
+  0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
+  0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
+  0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
+  0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
+  0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
+  0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
+#endif
+};
+#endif
+
+/* End: bn_prime_tab.c */
+
+/* Start: bn_reverse.c */
+#include "tma.h"
+#ifdef BN_REVERSE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* reverse an array, used for radix code */
+void
+bn_reverse (unsigned char *s, int len)
+{
+  int     ix, iy;
+  unsigned char t;
+
+  ix = 0;
+  iy = len - 1;
+  while (ix < iy) {
+    t     = s[ix];
+    s[ix] = s[iy];
+    s[iy] = t;
+    ++ix;
+    --iy;
+  }
+}
+#endif
+
+/* End: bn_reverse.c */
+
+/* Start: bn_s_mp_add.c */
+#include "tma.h"
+#ifdef BN_S_MP_ADD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int *x;
+  int     olduse, res, min, max;
+
+  /* find sizes, we let |a| <= |b| which means we have to sort
+   * them.  "x" will point to the input with the most digits
+   */
+  if (a->used > b->used) {
+    min = b->used;
+    max = a->used;
+    x = a;
+  } else {
+    min = a->used;
+    max = b->used;
+    x = b;
+  }
+
+  /* init result */
+  if (c->alloc < max + 1) {
+    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get old used digit count and set new one */
+  olduse = c->used;
+  c->used = max + 1;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+
+    /* first input */
+    tmpa = a->dp;
+
+    /* second input */
+    tmpb = b->dp;
+
+    /* destination */
+    tmpc = c->dp;
+
+    /* zero the carry */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+      *tmpc = *tmpa++ + *tmpb++ + u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+      /* take away carry bit from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, that is in A+B 
+     * if A or B has more digits add those in 
+     */
+    if (min != max) {
+      for (; i < max; i++) {
+        /* T[i] = X[i] + U */
+        *tmpc = x->dp[i] + u;
+
+        /* U = carry bit of T[i] */
+        u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+        /* take away carry bit from T[i] */
+        *tmpc++ &= MP_MASK;
+      }
+    }
+
+    /* add carry */
+    *tmpc++ = u;
+
+    /* clear digits above oldused */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_s_mp_add.c */
+
+/* Start: bn_s_mp_exptmod.c */
+#include "tma.h"
+#ifdef BN_S_MP_EXPTMOD_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res, mu;
+  mp_digit buf;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+  int (*redux)(mp_int*,mp_int*,mp_int*);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+    if (winsize > 5) {
+       winsize = 5;
+    }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err; 
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* create mu, used for Barrett reduction */
+  if ((err = mp_init (&mu)) != MP_OKAY) {
+    goto LBL_M;
+  }
+  
+  if (redmode == 0) {
+     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce;
+  } else {
+     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce_2k_l;
+  }    
+
+  /* create M table
+   *
+   * The M table contains powers of the base, 
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not 
+   * computed though accept for M[0] and M[1]
+   */
+  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring 
+   * M[1] (winsize-1) times 
+   */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    /* square it */
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], 
+                       &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+
+    /* reduce modulo P */
+    if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_MU;
+  }
+  mp_set (&res, 1);
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset the bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int) DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+/* End: bn_s_mp_exptmod.c */
+
+/* Start: bn_s_mp_mul_digs.c */
+#include "tma.h"
+#ifdef BN_S_MP_MUL_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* multiplies |a| * |b| and only computes upto digs digits of result
+ * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
+ * many digits of output are created.
+ */
+int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if (((digs) < MP_WARRAY) &&
+      MIN (a->used, b->used) < 
+          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+    return res;
+  }
+  t.used = digs;
+
+  /* compute the digits of the product directly */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* set the carry to zero */
+    u = 0;
+
+    /* limit ourselves to making digs digits of output */
+    pb = MIN (b->used, digs - ix);
+
+    /* setup some aliases */
+    /* copy of the digit from a used within the nested loop */
+    tmpx = a->dp[ix];
+    
+    /* an alias for the destination shifted ix places */
+    tmpt = t.dp + ix;
+    
+    /* an alias for the digits of b */
+    tmpy = b->dp;
+
+    /* compute the columns of the output and propagate the carry */
+    for (iy = 0; iy < pb; iy++) {
+      /* compute the column as a mp_word */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* the new column is the lower part of the result */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get the carry word from the result */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    /* set carry if it is placed below digs */
+    if (ix + iy < digs) {
+      *tmpt = u;
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, c);
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_s_mp_mul_digs.c */
+
+/* Start: bn_s_mp_mul_high_digs.c */
+#include "tma.h"
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+  if (((a->used + b->used + 1) < MP_WARRAY)
+      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_high_digs (a, b, c, digs);
+  }
+#endif
+
+  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+    return res;
+  }
+  t.used = a->used + b->used + 1;
+
+  pa = a->used;
+  pb = b->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* clear the carry */
+    u = 0;
+
+    /* left hand side of A[ix] * B[iy] */
+    tmpx = a->dp[ix];
+
+    /* alias to the address of where the digits will be stored */
+    tmpt = &(t.dp[digs]);
+
+    /* alias for where to read the right hand side from */
+    tmpy = b->dp + (digs - ix);
+
+    for (iy = digs - ix; iy < pb; iy++) {
+      /* calculate the double precision result */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* get the lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* carry the carry */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    *tmpt = u;
+  }
+  mp_clamp (&t);
+  mp_exch (&t, c);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_s_mp_mul_high_digs.c */
+
+/* Start: bn_s_mp_sqr.c */
+#include "tma.h"
+#ifdef BN_S_MP_SQR_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+int s_mp_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+  int     res, ix, iy, pa;
+  mp_word r;
+  mp_digit u, tmpx, *tmpt;
+
+  pa = a->used;
+  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* default used is maximum possible size */
+  t.used = 2*pa + 1;
+
+  for (ix = 0; ix < pa; ix++) {
+    /* first calculate the digit at 2*ix */
+    /* calculate double precision result */
+    r = ((mp_word) t.dp[2*ix]) +
+        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+    /* store lower part in result */
+    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* get the carry */
+    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+    /* left hand side of A[ix] * A[iy] */
+    tmpx        = a->dp[ix];
+
+    /* alias for where to store the results */
+    tmpt        = t.dp + (2*ix + 1);
+    
+    for (iy = ix + 1; iy < pa; iy++) {
+      /* first calculate the product */
+      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+      /* now calculate the double precision result, note we use
+       * addition instead of *2 since it's easier to optimize
+       */
+      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+      /* store lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get carry */
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+    /* propagate upwards */
+    while (u != ((mp_digit) 0)) {
+      r       = ((mp_word) *tmpt) + ((mp_word) u);
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, b);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+#endif
+
+/* End: bn_s_mp_sqr.c */
+
+/* Start: bn_s_mp_sub.c */
+#include "tma.h"
+#ifdef BN_S_MP_SUB_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     olduse, res, min, max;
+
+  /* find sizes */
+  min = b->used;
+  max = a->used;
+
+  /* init result */
+  if (c->alloc < max) {
+    if ((res = mp_grow (c, max)) != MP_OKAY) {
+      return res;
+    }
+  }
+  olduse = c->used;
+  c->used = max;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+    tmpa = a->dp;
+    tmpb = b->dp;
+    tmpc = c->dp;
+
+    /* set carry to zero */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* T[i] = A[i] - B[i] - U */
+      *tmpc = *tmpa++ - *tmpb++ - u;
+
+      /* U = carry bit of T[i]
+       * Note this saves performing an AND operation since
+       * if a carry does occur it will propagate all the way to the
+       * MSB.  As a result a single shift is enough to get the carry
+       */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, e.g. if A has more digits than B  */
+    for (; i < max; i++) {
+      /* T[i] = A[i] - U */
+      *tmpc = *tmpa++ - u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* clear digits above used (since we may not have grown result above) */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+#endif
+
+/* End: bn_s_mp_sub.c */
+
+/* Start: bncore.c */
+#include "tma.h"
+#ifdef BNCORE_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+
+/* Known optimal configurations
+
+ CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF
+-------------------------------------------------------------
+ Intel P4 Northwood     /GCC v3.4.1   /        88/       128/LTM 0.32 ;-)
+ AMD Athlon64           /GCC v3.4.4   /        74/       124/LTM 0.34
+*/
+
+int     KARATSUBA_MUL_CUTOFF = 74,      /* Min. number of digits before Karatsuba multiplication is used. */
+        KARATSUBA_SQR_CUTOFF = 124,     /* Min. number of digits before Karatsuba squaring is used. */
+        
+        TOOM_MUL_CUTOFF      = 350,      /* no optimal values of these are known yet so set em high */
+        TOOM_SQR_CUTOFF      = 400; 
+#endif
+
+/* End: bncore.c */
+
+
+/* EOF */
diff --git a/lib/silcmath/tma.h b/lib/silcmath/tma.h
new file mode 100644 (file)
index 0000000..02e370a
--- /dev/null
@@ -0,0 +1,582 @@
+/* LibTomMath, multiple-precision integer library -- Tom St Denis
+ *
+ * LibTomMath is a library that provides multiple-precision
+ * integer arithmetic as well as number theoretic functionality.
+ *
+ * The library was designed directly after the MPI library by
+ * Michael Fromberger but has been written from scratch with
+ * additional optimizations in place.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
+ */
+#ifndef TMA_H
+#define TMA_H
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include <tma_class.h>
+
+/* Assure these -Pekka */
+#undef MP_8BIT
+#undef MP_16BIT
+#undef CRYPT
+
+#undef MIN
+#define MIN(x,y) ((x)<(y)?(x):(y))
+#undef MAX
+#define MAX(x,y) ((x)>(y)?(x):(y))
+
+#ifdef __cplusplus
+extern "C" {
+
+/* C++ compilers don't like assigning void * to mp_digit * */
+#define  OPT_CAST(x)  (x *)
+
+#else
+
+/* C on the other hand doesn't care */
+#define  OPT_CAST(x)
+
+#endif
+
+
+/* detect 64-bit mode if possible */
+#if defined(__x86_64__)
+   #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT))
+      #define MP_64BIT
+   #endif
+#endif
+
+/* some default configurations.
+ *
+ * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
+ * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits
+ *
+ * At the very least a mp_digit must be able to hold 7 bits
+ * [any size beyond that is ok provided it doesn't overflow the data type]
+ */
+#ifdef MP_8BIT
+   typedef unsigned char      mp_digit;
+   typedef unsigned short     mp_word;
+#elif defined(MP_16BIT)
+   typedef unsigned short     mp_digit;
+   typedef unsigned long      mp_word;
+#elif defined(MP_64BIT)
+   /* for GCC only on supported platforms */
+#ifndef CRYPT
+   typedef unsigned long long ulong64;
+   typedef signed long long   long64;
+#endif
+
+   typedef unsigned long      mp_digit;
+   typedef unsigned long      mp_word __attribute__ ((mode(TI)));
+
+   #define DIGIT_BIT          60
+#else
+   /* this is the default case, 28-bit digits */
+
+   /* this is to make porting into LibTomCrypt easier :-) */
+#ifndef CRYPT
+   #if defined(_MSC_VER) || defined(__BORLANDC__)
+      typedef unsigned __int64   ulong64;
+      typedef signed __int64     long64;
+   #else
+      typedef unsigned long long ulong64;
+      typedef signed long long   long64;
+   #endif
+#endif
+
+   typedef unsigned long      mp_digit;
+   typedef ulong64            mp_word;
+
+#ifdef MP_31BIT
+   /* this is an extension that uses 31-bit digits */
+   #define DIGIT_BIT          31
+#else
+   /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */
+   #define DIGIT_BIT          28
+   #define MP_28BIT
+#endif
+#endif
+
+/* define heap macros */
+#ifndef CRYPT
+   /* default to libc stuff */
+   #ifndef XMALLOC
+       #define XMALLOC  malloc
+       #define XFREE    free
+       #define XREALLOC realloc
+       #define XCALLOC  calloc
+   #else
+      /* prototypes for our heap functions */
+      extern void *XMALLOC(size_t n);
+      extern void *REALLOC(void *p, size_t n);
+      extern void *XCALLOC(size_t n, size_t s);
+      extern void XFREE(void *p);
+   #endif
+#endif
+
+
+/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
+#ifndef DIGIT_BIT
+   #define DIGIT_BIT     ((int)((CHAR_BIT * sizeof(mp_digit) - 1)))  /* bits per digit */
+#endif
+
+#define MP_DIGIT_BIT     DIGIT_BIT
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+#define MP_DIGIT_MAX     MP_MASK
+
+/* equalities */
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+#define MP_RANGE      MP_VAL
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+/* Primality generation flags */
+#define LTM_PRIME_BBS      0x0001 /* BBS style prime */
+#define LTM_PRIME_SAFE     0x0002 /* Safe prime (p-1)/2 == prime */
+#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */
+#define LTM_PRIME_2MSB_ON  0x0008 /* force 2nd MSB to 1 */
+
+typedef int           mp_err;
+
+/* you'll have to tune these... */
+extern int KARATSUBA_MUL_CUTOFF,
+           KARATSUBA_SQR_CUTOFF,
+           TOOM_MUL_CUTOFF,
+           TOOM_SQR_CUTOFF;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+/* #define MP_LOW_MEM */
+
+/* default precision */
+#ifndef MP_PREC
+   #ifndef MP_LOW_MEM
+      #define MP_PREC                 64     /* default digits of precision */
+   #else
+      #define MP_PREC                 8      /* default digits of precision */
+   #endif
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct  {
+    int used, alloc, sign;
+    mp_digit *dp;
+} mp_int;
+
+/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
+typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+
+
+#define USED(m)    ((m)->used)
+#define DIGIT(m,k) ((m)->dp[(k)])
+#define SIGN(m)    ((m)->sign)
+
+/* error code to char* string */
+char *mp_error_to_string(int code);
+
+/* ---> init and deinit bignum functions <--- */
+/* init a bignum */
+int mp_init(mp_int *a);
+
+/* free a bignum */
+void mp_clear(mp_int *a);
+
+/* init a null terminated series of arguments */
+int mp_init_multi(mp_int *mp, ...);
+
+/* clear a null terminated series of arguments */
+void mp_clear_multi(mp_int *mp, ...);
+
+/* exchange two ints */
+void mp_exch(mp_int *a, mp_int *b);
+
+/* shrink ram required for a bignum */
+int mp_shrink(mp_int *a);
+
+/* grow an int to a given size */
+int mp_grow(mp_int *a, int size);
+
+/* init to a given number of digits */
+int mp_init_size(mp_int *a, int size);
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+/* set to zero */
+void mp_zero(mp_int *a);
+
+/* set to a digit */
+void mp_set(mp_int *a, mp_digit b);
+
+/* set a 32-bit const */
+int mp_set_int(mp_int *a, unsigned long b);
+
+/* get a 32-bit value */
+unsigned long mp_get_int(mp_int * a);
+
+/* initialize and set a digit */
+int mp_init_set (mp_int * a, mp_digit b);
+
+/* initialize and set 32-bit value */
+int mp_init_set_int (mp_int * a, unsigned long b);
+
+/* copy, b = a */
+int mp_copy(mp_int *a, mp_int *b);
+
+/* inits and copies, a = b */
+int mp_init_copy(mp_int *a, mp_int *b);
+
+/* trim unused digits */
+void mp_clamp(mp_int *a);
+
+/* ---> digit manipulation <--- */
+
+/* right shift by "b" digits */
+void mp_rshd(mp_int *a, int b);
+
+/* left shift by "b" digits */
+int mp_lshd(mp_int *a, int b);
+
+/* c = a / 2**b */
+int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d);
+
+/* b = a/2 */
+int mp_div_2(mp_int *a, mp_int *b);
+
+/* c = a * 2**b */
+int mp_mul_2d(mp_int *a, int b, mp_int *c);
+
+/* b = a*2 */
+int mp_mul_2(mp_int *a, mp_int *b);
+
+/* c = a mod 2**d */
+int mp_mod_2d(mp_int *a, int b, mp_int *c);
+
+/* computes a = 2**b */
+int mp_2expt(mp_int *a, int b);
+
+/* Counts the number of lsbs which are zero before the first zero bit */
+int mp_cnt_lsb(mp_int *a);
+
+/* I Love Earth! */
+
+/* makes a pseudo-random int of a given size */
+int mp_rand(mp_int *a, int digits);
+
+/* ---> binary operations <--- */
+/* c = a XOR b  */
+int mp_xor(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a OR b */
+int mp_or(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a AND b */
+int mp_and(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> Basic arithmetic <--- */
+
+/* b = -a */
+int mp_neg(mp_int *a, mp_int *b);
+
+/* b = |a| */
+int mp_abs(mp_int *a, mp_int *b);
+
+/* compare a to b */
+int mp_cmp(mp_int *a, mp_int *b);
+
+/* compare |a| to |b| */
+int mp_cmp_mag(mp_int *a, mp_int *b);
+
+/* c = a + b */
+int mp_add(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a - b */
+int mp_sub(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = a * b */
+int mp_mul(mp_int *a, mp_int *b, mp_int *c);
+
+/* b = a*a  */
+int mp_sqr(mp_int *a, mp_int *b);
+
+/* a/b => cb + d == a */
+int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod(mp_int *a, mp_int *b, mp_int *c);
+
+/* ---> single digit functions <--- */
+
+/* compare against a single digit */
+int mp_cmp_d(mp_int *a, mp_digit b);
+
+/* c = a + b */
+int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a - b */
+int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a * b */
+int mp_mul_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* a/b => cb + d == a */
+int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
+
+/* a/3 => 3c + d == a */
+int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
+
+/* c = a**b */
+int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
+
+/* c = a mod b, 0 <= c < b  */
+int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c);
+
+/* ---> number theory <--- */
+
+/* d = a + b (mod c) */
+int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a - b (mod c) */
+int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* d = a * b (mod c) */
+int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* c = a * a (mod b) */
+int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = 1/a (mod b) */
+int mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+
+/* c = (a, b) */
+int mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+
+/* produces value such that U1*a + U2*b = U3 */
+int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3);
+
+/* c = [a, b] or (a*b)/(a, b) */
+int mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+
+/* finds one of the b'th root of a, such that |c|**b <= |a|
+ *
+ * returns error if a < 0 and b is even
+ */
+int mp_n_root(mp_int *a, mp_digit b, mp_int *c);
+
+/* special sqrt algo */
+int mp_sqrt(mp_int *arg, mp_int *ret);
+
+/* is number a square? */
+int mp_is_square(mp_int *arg, int *ret);
+
+/* computes the jacobi c = (a | n) (or Legendre if b is prime)  */
+int mp_jacobi(mp_int *a, mp_int *n, int *c);
+
+/* used to setup the Barrett reduction for a given modulus b */
+int mp_reduce_setup(mp_int *a, mp_int *b);
+
+/* Barrett Reduction, computes a (mod b) with a precomputed value c
+ *
+ * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely
+ * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code].
+ */
+int mp_reduce(mp_int *a, mp_int *b, mp_int *c);
+
+/* setups the montgomery reduction */
+int mp_montgomery_setup(mp_int *a, mp_digit *mp);
+
+/* computes a = B**n mod b without division or multiplication useful for
+ * normalizing numbers in a Montgomery system.
+ */
+int mp_montgomery_calc_normalization(mp_int *a, mp_int *b);
+
+/* computes x/R == x (mod N) via Montgomery Reduction */
+int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+
+/* returns 1 if a is a valid DR modulus */
+int mp_dr_is_modulus(mp_int *a);
+
+/* sets the value of "d" required for mp_dr_reduce */
+void mp_dr_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b using the Diminished Radix method */
+int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp);
+
+/* returns true if a can be reduced with mp_reduce_2k */
+int mp_reduce_is_2k(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup(mp_int *a, mp_digit *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d);
+
+/* returns true if a can be reduced with mp_reduce_2k_l */
+int mp_reduce_is_2k_l(mp_int *a);
+
+/* determines k value for 2k reduction */
+int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+
+/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */
+int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+
+/* d = a**b (mod c) */
+int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d);
+
+/* ---> Primes <--- */
+
+/* number of primes */
+#ifdef MP_8BIT
+   #define PRIME_SIZE      31
+#else
+   #define PRIME_SIZE      256
+#endif
+
+/* table of first PRIME_SIZE primes */
+extern const mp_digit ltm_prime_tab[];
+
+/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
+int mp_prime_is_divisible(mp_int *a, int *result);
+
+/* performs one Fermat test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
+
+/* performs one Miller-Rabin test of "a" using base "b".
+ * Sets result to 0 if composite or 1 if probable prime
+ */
+int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
+
+/* This gives [for a given bit size] the number of trials required
+ * such that Miller-Rabin gives a prob of failure lower than 2^-96
+ */
+int mp_prime_rabin_miller_trials(int size);
+
+/* performs t rounds of Miller-Rabin on "a" using the first
+ * t prime bases.  Also performs an initial sieve of trial
+ * division.  Determines if "a" is prime with probability
+ * of error no more than (1/4)**t.
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+int mp_prime_is_prime(mp_int *a, int t, int *result);
+
+/* finds the next prime after the number "a" using "t" trials
+ * of Miller-Rabin.
+ *
+ * bbs_style = 1 means the prime must be congruent to 3 mod 4
+ */
+int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
+
+/* makes a truly random prime of a given size (bytes),
+ * call with bbs = 1 if you want it to be congruent to 3 mod 4
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ * The prime generated will be larger than 2^(8*size).
+ */
+#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat)
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
+ *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
+ *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat);
+
+/* ---> radix conversion <--- */
+int mp_count_bits(mp_int *a);
+
+int mp_unsigned_bin_size(mp_int *a);
+int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_unsigned_bin(mp_int *a, unsigned char *b);
+int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_signed_bin_size(mp_int *a);
+int mp_read_signed_bin(mp_int *a, unsigned char *b, int c);
+int mp_to_signed_bin(mp_int *a, unsigned char *b);
+int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen);
+
+int mp_read_radix(mp_int *a, const char *str, int radix);
+int mp_toradix(mp_int *a, char *str, int radix);
+int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen);
+int mp_radix_size(mp_int *a, int radix, int *size);
+
+int mp_fread(mp_int *a, int radix, FILE *stream);
+int mp_fwrite(mp_int *a, int radix, FILE *stream);
+
+#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len))
+#define mp_raw_size(mp)           mp_signed_bin_size(mp)
+#define mp_toraw(mp, str)         mp_to_signed_bin((mp), (str))
+#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len))
+#define mp_mag_size(mp)           mp_unsigned_bin_size(mp)
+#define mp_tomag(mp, str)         mp_to_unsigned_bin((mp), (str))
+
+#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S)     mp_toradix((M), (S), 16)
+
+/* lowlevel functions, do not call! */
+int s_mp_add(mp_int *a, mp_int *b, mp_int *c);
+int s_mp_sub(mp_int *a, mp_int *b, mp_int *c);
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs);
+int fast_s_mp_sqr(mp_int *a, mp_int *b);
+int s_mp_sqr(mp_int *a, mp_int *b);
+int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c);
+int mp_karatsuba_sqr(mp_int *a, mp_int *b);
+int mp_toom_sqr(mp_int *a, mp_int *b);
+int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c);
+int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c);
+int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp);
+int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode);
+int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int mode);
+void bn_reverse(unsigned char *s, int len);
+
+extern const char *mp_s_rmap;
+
+#ifdef __cplusplus
+   }
+#endif
+
+#endif /* TMA_H */
diff --git a/lib/silcmath/tma_class.h b/lib/silcmath/tma_class.h
new file mode 100644 (file)
index 0000000..649cb18
--- /dev/null
@@ -0,0 +1,994 @@
+#if !(defined(LTM1) && defined(LTM2) && defined(LTM3))
+#if defined(LTM2)
+#define LTM3
+#endif
+#if defined(LTM1)
+#define LTM2
+#endif
+#define LTM1
+
+#if defined(LTM_ALL)
+#define BN_ERROR_C
+#define BN_FAST_MP_INVMOD_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_FAST_S_MP_MUL_DIGS_C
+#define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+#define BN_FAST_S_MP_SQR_C
+#define BN_MP_2EXPT_C
+#define BN_MP_ABS_C
+#define BN_MP_ADD_C
+#define BN_MP_ADD_D_C
+#define BN_MP_ADDMOD_C
+#define BN_MP_AND_C
+#define BN_MP_CLAMP_C
+#define BN_MP_CLEAR_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_CMP_C
+#define BN_MP_CMP_D_C
+#define BN_MP_CMP_MAG_C
+#define BN_MP_CNT_LSB_C
+#define BN_MP_COPY_C
+#define BN_MP_COUNT_BITS_C
+#define BN_MP_DIV_C
+#define BN_MP_DIV_2_C
+#define BN_MP_DIV_2D_C
+#define BN_MP_DIV_3_C
+#define BN_MP_DIV_D_C
+#undef BN_MP_DR_IS_MODULUS_C
+#undef BN_MP_DR_REDUCE_C
+#undef BN_MP_DR_SETUP_C
+#define BN_MP_EXCH_C
+#define BN_MP_EXPT_D_C
+#define BN_MP_EXPTMOD_C
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_EXTEUCLID_C
+#define BN_MP_FREAD_C
+#define BN_MP_FWRITE_C
+#define BN_MP_GCD_C
+#define BN_MP_GET_INT_C
+#define BN_MP_GROW_C
+#define BN_MP_INIT_C
+#define BN_MP_INIT_COPY_C
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_INIT_SET_C
+#define BN_MP_INIT_SET_INT_C
+#define BN_MP_INIT_SIZE_C
+#define BN_MP_INVMOD_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_MP_IS_SQUARE_C
+#undef BN_MP_JACOBI_C
+#define BN_MP_KARATSUBA_MUL_C
+#define BN_MP_KARATSUBA_SQR_C
+#define BN_MP_LCM_C
+#define BN_MP_LSHD_C
+#define BN_MP_MOD_C
+#define BN_MP_MOD_2D_C
+#define BN_MP_MOD_D_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_MP_MUL_C
+#define BN_MP_MUL_2_C
+#define BN_MP_MUL_2D_C
+#define BN_MP_MUL_D_C
+#define BN_MP_MULMOD_C
+#define BN_MP_N_ROOT_C
+#define BN_MP_NEG_C
+#define BN_MP_OR_C
+#undef BN_MP_PRIME_FERMAT_C
+#undef BN_MP_PRIME_IS_DIVISIBLE_C
+#undef BN_MP_PRIME_IS_PRIME_C
+#undef BN_MP_PRIME_MILLER_RABIN_C
+#undef BN_MP_PRIME_NEXT_PRIME_C
+#undef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+#undef BN_MP_PRIME_RANDOM_EX_C
+#define BN_MP_RADIX_SIZE_C
+#define BN_MP_RADIX_SMAP_C
+#define BN_MP_RAND_C
+#define BN_MP_READ_RADIX_C
+#define BN_MP_READ_SIGNED_BIN_C
+#define BN_MP_READ_UNSIGNED_BIN_C
+#define BN_MP_REDUCE_C
+#define BN_MP_REDUCE_2K_C
+#define BN_MP_REDUCE_2K_L_C
+#define BN_MP_REDUCE_2K_SETUP_C
+#define BN_MP_REDUCE_2K_SETUP_L_C
+#define BN_MP_REDUCE_IS_2K_C
+#define BN_MP_REDUCE_IS_2K_L_C
+#define BN_MP_REDUCE_SETUP_C
+#define BN_MP_RSHD_C
+#define BN_MP_SET_C
+#define BN_MP_SET_INT_C
+#define BN_MP_SHRINK_C
+#define BN_MP_SIGNED_BIN_SIZE_C
+#define BN_MP_SQR_C
+#define BN_MP_SQRMOD_C
+#define BN_MP_SQRT_C
+#define BN_MP_SUB_C
+#define BN_MP_SUB_D_C
+#define BN_MP_SUBMOD_C
+#define BN_MP_TO_SIGNED_BIN_C
+#define BN_MP_TO_SIGNED_BIN_N_C
+#define BN_MP_TO_UNSIGNED_BIN_C
+#define BN_MP_TO_UNSIGNED_BIN_N_C
+#undef BN_MP_TOOM_MUL_C
+#undef BN_MP_TOOM_SQR_C
+#define BN_MP_TORADIX_C
+#define BN_MP_TORADIX_N_C
+#define BN_MP_UNSIGNED_BIN_SIZE_C
+#define BN_MP_XOR_C
+#define BN_MP_ZERO_C
+#define BN_PRIME_TAB_C
+#define BN_REVERSE_C
+#define BN_S_MP_ADD_C
+#define BN_S_MP_EXPTMOD_C
+#define BN_S_MP_MUL_DIGS_C
+#define BN_S_MP_MUL_HIGH_DIGS_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_SUB_C
+#define BNCORE_C
+#endif
+
+#if defined(BN_ERROR_C)
+   #define BN_MP_ERROR_TO_STRING_C
+#endif
+
+#if defined(BN_FAST_MP_INVMOD_C)
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_COPY_C
+   #define BN_MP_MOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_FAST_S_MP_SQR_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_2EXPT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_ABS_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_ADD_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_ADD_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_ADDMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_AND_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CLAMP_C)
+#endif
+
+#if defined(BN_MP_CLEAR_C)
+#endif
+
+#if defined(BN_MP_CLEAR_MULTI_C)
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_CMP_C)
+   #define BN_MP_CMP_MAG_C
+#endif
+
+#if defined(BN_MP_CMP_D_C)
+#endif
+
+#if defined(BN_MP_CMP_MAG_C)
+#endif
+
+#if defined(BN_MP_CNT_LSB_C)
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_COPY_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_COUNT_BITS_C)
+#endif
+
+#if defined(BN_MP_DIV_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_ABS_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_2_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_DIV_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_DIV_3_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DIV_D_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_DR_IS_MODULUS_C)
+#endif
+
+#if defined(BN_MP_DR_REDUCE_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_DR_SETUP_C)
+#endif
+
+#if defined(BN_MP_EXCH_C)
+#endif
+
+#if defined(BN_MP_EXPT_D_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SET_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MUL_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ABS_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_REDUCE_IS_2K_L_C
+   #define BN_S_MP_EXPTMOD_C
+   #undef BN_MP_DR_IS_MODULUS_C
+   #define BN_MP_REDUCE_IS_2K_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_EXPTMOD_FAST_C
+#endif
+
+#if defined(BN_MP_EXPTMOD_FAST_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MONTGOMERY_SETUP_C
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_MONTGOMERY_REDUCE_C
+   #undef BN_MP_DR_SETUP_C
+   #undef BN_MP_DR_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_C
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_SET_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_EXTEUCLID_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_NEG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_FREAD_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CMP_D_C
+#endif
+
+#if defined(BN_MP_FWRITE_C)
+   #define BN_MP_RADIX_SIZE_C
+   #define BN_MP_TORADIX_C
+#endif
+
+#if defined(BN_MP_GCD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ABS_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_GET_INT_C)
+#endif
+
+#if defined(BN_MP_GROW_C)
+#endif
+
+#if defined(BN_MP_INIT_C)
+#endif
+
+#if defined(BN_MP_INIT_COPY_C)
+   #define BN_MP_COPY_C
+#endif
+
+#if defined(BN_MP_INIT_MULTI_C)
+   #define BN_MP_ERR_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_INIT_SET_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+#endif
+
+#if defined(BN_MP_INIT_SET_INT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_INT_C
+#endif
+
+#if defined(BN_MP_INIT_SIZE_C)
+   #define BN_MP_INIT_C
+#endif
+
+#if defined(BN_MP_INVMOD_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ISODD_C
+   #define BN_FAST_MP_INVMOD_C
+   #define BN_MP_INVMOD_SLOW_C
+#endif
+
+#if defined(BN_MP_INVMOD_SLOW_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_SET_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_ISODD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_IS_SQUARE_C)
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_SET_INT_C
+   #define BN_MP_MOD_C
+   #define BN_MP_GET_INT_C
+   #define BN_MP_SQRT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_JACOBI_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_MUL_C)
+   #define BN_MP_MUL_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SUB_C
+   #define BN_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_KARATSUBA_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_SQR_C
+   #define BN_MP_SUB_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_LCM_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_GCD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_DIV_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_LSHD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_RSHD_C
+#endif
+
+#if defined(BN_MP_MOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_ADD_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_MP_MOD_2D_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_COPY_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MOD_D_C)
+   #define BN_MP_DIV_D_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_SET_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_REDUCE_C)
+   #define BN_FAST_MP_MONTGOMERY_REDUCE_C
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_MONTGOMERY_SETUP_C)
+#endif
+
+#if defined(BN_MP_MUL_C)
+   #undef BN_MP_TOOM_MUL_C
+   #define BN_MP_KARATSUBA_MUL_C
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_S_MP_MUL_C
+   #define BN_S_MP_MUL_DIGS_C
+#endif
+
+#if defined(BN_MP_MUL_2_C)
+   #define BN_MP_GROW_C
+#endif
+
+#if defined(BN_MP_MUL_2D_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_GROW_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MUL_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_MULMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_MUL_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_N_ROOT_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_COPY_C
+   #define BN_MP_EXPT_D_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SUB_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_NEG_C)
+   #define BN_MP_COPY_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_OR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_FERMAT_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_DIVISIBLE_C)
+   #define BN_MP_MOD_D_C
+#endif
+
+#if defined(BN_MP_PRIME_IS_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_PRIME_IS_DIVISIBLE_C
+   #define BN_MP_INIT_C
+   #define BN_MP_SET_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_MILLER_RABIN_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_CNT_LSB_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_CMP_C
+   #define BN_MP_SQRMOD_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_NEXT_PRIME_C)
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_ISEVEN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_INIT_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_PRIME_MILLER_RABIN_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
+#endif
+
+#if defined(BN_MP_PRIME_RANDOM_EX_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+   #define BN_MP_PRIME_IS_PRIME_C
+   #define BN_MP_SUB_D_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_D_C
+#endif
+
+#if defined(BN_MP_RADIX_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_RADIX_SMAP_C)
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_RAND_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_LSHD_C
+#endif
+
+#if defined(BN_MP_READ_RADIX_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_S_RMAP_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_ISZERO_C
+#endif
+
+#if defined(BN_MP_READ_SIGNED_BIN_C)
+   #define BN_MP_READ_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_READ_UNSIGNED_BIN_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_REDUCE_C)
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_MUL_HIGH_DIGS_C
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_MOD_2D_C
+   #define BN_S_MP_MUL_DIGS_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CMP_D_C
+   #define BN_MP_SET_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_ADD_C
+   #define BN_MP_CMP_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_L_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_MUL_C
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_CLEAR_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_REDUCE_2K_SETUP_L_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_2EXPT_C
+   #define BN_MP_COUNT_BITS_C
+   #define BN_S_MP_SUB_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_C)
+   #define BN_MP_REDUCE_2K_C
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_REDUCE_IS_2K_L_C)
+#endif
+
+#if defined(BN_MP_REDUCE_SETUP_C)
+   #define BN_MP_2EXPT_C
+   #define BN_MP_DIV_C
+#endif
+
+#if defined(BN_MP_RSHD_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_C)
+   #define BN_MP_ZERO_C
+#endif
+
+#if defined(BN_MP_SET_INT_C)
+   #define BN_MP_ZERO_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SHRINK_C)
+#endif
+
+#if defined(BN_MP_SIGNED_BIN_SIZE_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+#endif
+
+#if defined(BN_MP_SQR_C)
+   #undef BN_MP_TOOM_SQR_C
+   #define BN_MP_KARATSUBA_SQR_C
+   #define BN_FAST_S_MP_SQR_C
+   #define BN_S_MP_SQR_C
+#endif
+
+#if defined(BN_MP_SQRMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SQR_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_SQRT_C)
+   #define BN_MP_N_ROOT_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_ZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_DIV_C
+   #define BN_MP_ADD_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_SUB_C)
+   #define BN_S_MP_ADD_C
+   #define BN_MP_CMP_MAG_C
+   #define BN_S_MP_SUB_C
+#endif
+
+#if defined(BN_MP_SUB_D_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_ADD_D_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_MP_SUBMOD_C)
+   #define BN_MP_INIT_C
+   #define BN_MP_SUB_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_MOD_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_C)
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_SIGNED_BIN_N_C)
+   #define BN_MP_SIGNED_BIN_SIZE_C
+   #define BN_MP_TO_SIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_ISZERO_C
+   #define BN_MP_DIV_2D_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_TO_UNSIGNED_BIN_N_C)
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+#endif
+
+#if defined(BN_MP_TOOM_MUL_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_MUL_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TOOM_SQR_C)
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_MOD_2D_C
+   #define BN_MP_COPY_C
+   #define BN_MP_RSHD_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_2_C
+   #define BN_MP_ADD_C
+   #define BN_MP_SUB_C
+   #define BN_MP_DIV_2_C
+   #define BN_MP_MUL_2D_C
+   #define BN_MP_MUL_D_C
+   #define BN_MP_DIV_3_C
+   #define BN_MP_LSHD_C
+   #define BN_MP_CLEAR_MULTI_C
+#endif
+
+#if defined(BN_MP_TORADIX_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_TORADIX_N_C)
+   #define BN_MP_ISZERO_C
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_DIV_D_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_S_RMAP_C
+#endif
+
+#if defined(BN_MP_UNSIGNED_BIN_SIZE_C)
+   #define BN_MP_COUNT_BITS_C
+#endif
+
+#if defined(BN_MP_XOR_C)
+   #define BN_MP_INIT_COPY_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_MP_ZERO_C)
+#endif
+
+#if defined(BN_PRIME_TAB_C)
+#endif
+
+#if defined(BN_REVERSE_C)
+#endif
+
+#if defined(BN_S_MP_ADD_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BN_S_MP_EXPTMOD_C)
+   #define BN_MP_COUNT_BITS_C
+   #define BN_MP_INIT_C
+   #define BN_MP_CLEAR_C
+   #define BN_MP_REDUCE_SETUP_C
+   #define BN_MP_REDUCE_C
+   #define BN_MP_REDUCE_2K_SETUP_L_C
+   #define BN_MP_REDUCE_2K_L_C
+   #define BN_MP_MOD_C
+   #define BN_MP_COPY_C
+   #define BN_MP_SQR_C
+   #define BN_MP_MUL_C
+   #define BN_MP_SET_C
+   #define BN_MP_EXCH_C
+#endif
+
+#if defined(BN_S_MP_MUL_DIGS_C)
+   #define BN_FAST_S_MP_MUL_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_MUL_HIGH_DIGS_C)
+   #define BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SQR_C)
+   #define BN_MP_INIT_SIZE_C
+   #define BN_MP_CLAMP_C
+   #define BN_MP_EXCH_C
+   #define BN_MP_CLEAR_C
+#endif
+
+#if defined(BN_S_MP_SUB_C)
+   #define BN_MP_GROW_C
+   #define BN_MP_CLAMP_C
+#endif
+
+#if defined(BNCORE_C)
+#endif
+
+#ifdef LTM3
+#define LTM_LAST
+#endif
+#include <tma_superclass.h>
+#include <tma_class.h>
+#else
+#define LTM_LAST
+#endif
diff --git a/lib/silcmath/tma_superclass.h b/lib/silcmath/tma_superclass.h
new file mode 100644 (file)
index 0000000..b50ecb0
--- /dev/null
@@ -0,0 +1,72 @@
+/* super class file for PK algos */
+
+/* default ... include all MPI */
+#define LTM_ALL
+
+/* RSA only (does not support DH/DSA/ECC) */
+// #define SC_RSA_1
+
+/* For reference.... On an Athlon64 optimizing for speed...
+
+   LTM's mpi.o with all functions [striped] is 142KiB in size.
+
+*/
+
+/* Works for RSA only, mpi.o is 68KiB */
+#ifdef SC_RSA_1
+   #define BN_MP_SHRINK_C
+   #define BN_MP_LCM_C
+   #define BN_MP_PRIME_RANDOM_EX_C
+   #define BN_MP_INVMOD_C
+   #define BN_MP_GCD_C
+   #define BN_MP_MOD_C
+   #define BN_MP_MULMOD_C
+   #define BN_MP_ADDMOD_C
+   #define BN_MP_EXPTMOD_C
+   #define BN_MP_SET_INT_C
+   #define BN_MP_INIT_MULTI_C
+   #define BN_MP_CLEAR_MULTI_C
+   #define BN_MP_UNSIGNED_BIN_SIZE_C
+   #define BN_MP_TO_UNSIGNED_BIN_C
+   #define BN_MP_MOD_D_C
+   #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
+   #define BN_REVERSE_C
+   #define BN_PRIME_TAB_C
+
+   /* other modifiers */
+   #define BN_MP_DIV_SMALL                    /* Slower division, not critical */
+
+   /* here we are on the last pass so we turn things off.  The functions classes are still there
+    * but we remove them specifically from the build.  This also invokes tweaks in functions
+    * like removing support for even moduli, etc...
+    */
+#ifdef LTM_LAST
+   #undef  BN_MP_TOOM_MUL_C
+   #undef  BN_MP_TOOM_SQR_C
+   #undef  BN_MP_KARATSUBA_MUL_C
+   #undef  BN_MP_KARATSUBA_SQR_C
+   #undef  BN_MP_REDUCE_C
+   #undef  BN_MP_REDUCE_SETUP_C
+   #undef  BN_MP_DR_IS_MODULUS_C
+   #undef  BN_MP_DR_SETUP_C
+   #undef  BN_MP_DR_REDUCE_C
+   #undef  BN_MP_REDUCE_IS_2K_C
+   #undef  BN_MP_REDUCE_2K_SETUP_C
+   #undef  BN_MP_REDUCE_2K_C
+   #undef  BN_S_MP_EXPTMOD_C
+   #undef  BN_MP_DIV_3_C
+   #undef  BN_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_S_MP_MUL_HIGH_DIGS_C
+   #undef  BN_FAST_MP_INVMOD_C
+
+   /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold
+    * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] 
+    * which means roughly speaking you can handle upto 2536-bit RSA keys with these defined without
+    * trouble.  
+    */
+   #undef  BN_S_MP_MUL_DIGS_C
+   #undef  BN_S_MP_SQR_C
+   #undef  BN_MP_MONTGOMERY_REDUCE_C
+#endif
+
+#endif
index 38b300b6277e4c807b68e8c7c284fadec5acd874..1c75064215ec688f67435856a19e17f11f92d403 100644 (file)
@@ -862,7 +862,7 @@ void silc_sftp_extended(SilcSFTP sftp,
  * DESCRIPTION
  *
  *    Starts SFTP server and returns a context to it.  This function returns
- *    the allocated SFTP client context or NULL on error. The `send_packet'
+ *    the allocated SFTP server context or NULL on error. The `send_packet'
  *    is called by the library when it needs to send a packet. The `fs' is the
  *    filesystem context allocated by the application.  Each socket connection
  *    should start its own server by calling this function.
@@ -983,7 +983,7 @@ typedef void (*SilcSFTPMonitor)(SilcSFTP sftp,
  *
  * DESCRIPTION
  *
- *    Sets monitor callback to monitor various request sent by an client.
+ *    Sets monitor callback to monitor various request sent by a client.
  *    When request that has been set in the `monitors' is received the
  *    monitor callback will be called to notify the caller.
  *
index ae222ab71e5fcd021fa1e4b913736b6a73c81cc5..d9a96fc98b14fb753e61a102db8398d4a8708499 100644 (file)
@@ -340,7 +340,7 @@ void silc_sftp_fs_memory_free(SilcSFTPFilesystem fs);
  *
  * SYNOPSIS
  *
- *    void *silc_sftp_fs_memory_add_dir(void *context, void *dir,
+ *    void *silc_sftp_fs_memory_add_dir(SilcSFTPFilesystem fs, void *dir,
  *                                      SilcSFTPFSMemoryPerm perm,
  *                                      const char *name);
  *
index baf8d782081c728dbb2d8666417dcf5b48098996..0c9149755bfd35c836cb05c1cb49b0e97f85fe0f 100644 (file)
@@ -80,4 +80,11 @@ include_HEADERS = silcsim.h silcsimutil.h
 
 EXTRA_DIST = *.h
 
+#
+# Installation
+#
+install-data-hook:
+       -mkdir -p $(modulesdir)
+       -$(INSTALL_DATA) $(top_srcdir)/lib/silcsim/*.so $(modulesdir)/
+
 include $(top_srcdir)/Makefile.defines.in
index 6e772620454cfdea5e85497093de5b2f795a7a29..dcec015024b66e353671b8f86f39cae5913e41f2 100644 (file)
@@ -2,14 +2,13 @@
 
   silcsim.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index ca8880818858070c0b55234d20f6081ca4b693b9..357ab5735e81a86a7fdfb4a4aaf8af880de1000f 100644 (file)
@@ -2,14 +2,13 @@
 
   silcsim.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 0da8993a367a5adf47bae90659e8d9e1cdb70362..1e839db33d76624ad5451c97e001b9b65ffd05c9 100644 (file)
@@ -2,14 +2,13 @@
 
   silcsimutil.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 70c4be3aba45f0447d9d92158a36dc6efc58e8f9..cf818825b05ff064303ae731d1373aa429aa9047 100644 (file)
@@ -2,14 +2,13 @@
 
   silcsimutil.h
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 2000 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index e0bbce0fff3a8bf8d301e25ef26388079271b39a..2ba52de9c802d268699c8f94343f5e45781950f9 100644 (file)
@@ -8,8 +8,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index eb62758365bc6434ac12b1775db3a4ed6adb1cf7..dccbe57f88e36822c0033f3ccec196d4e8da22fd 100644 (file)
@@ -8,8 +8,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index e00121210a4b767ab89a295318768d8251f189e3..f3db0baf289fe17d7445cbc5469db0805b4814a9 100644 (file)
@@ -1,10 +1,10 @@
 /*
 
-  silcske.c 
+  silcske.c
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2000 - 2002 Pekka Riikonen
+  Copyright (C) 2000 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
 #include "groups_internal.h"
 
 /* Static functions */
-static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, 
-                                        SilcUInt32 len, 
+static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
+                                        SilcUInt32 len,
                                         SilcMPInt *rnd);
-static SilcSKEStatus silc_ske_make_hash(SilcSKE ske, 
+static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
                                        unsigned char *return_hash,
                                        SilcUInt32 *return_hash_len,
                                        int initiator);
@@ -117,11 +117,11 @@ void silc_ske_free(SilcSKE ske)
   }
 }
 
-/* Sets the callback functions for the SKE session. 
+/* Sets the callback functions for the SKE session.
 
    The `send_packet' callback is a function that sends the packet to
    network. The SKE library will call it at any time packet needs to
-   be sent to the remote host. 
+   be sent to the remote host.
 
    The `payload_receive' callback is called when the remote host's Key
    Exchange Start Payload has been processed.  The payload is saved
@@ -133,8 +133,8 @@ void silc_ske_free(SilcSKE ske)
    That is why the application must call the completion callback when the
    verification process has been completed. The library then calls the user
    callback (`proto_continue'), if it is provided to indicate that the SKE
-   protocol may continue. 
-   
+   protocol may continue.
+
    The `proto_continue' callback is called to indicate that it is
    safe to continue the execution of the SKE protocol after executing
    an asynchronous operation, such as calling the `verify_key' callback
@@ -145,7 +145,7 @@ void silc_ske_free(SilcSKE ske)
    The `check_version' callback is called to verify the remote host's
    version. The application may check its own version against the remote
    host's version and determine whether supporting the remote host
-   is possible. 
+   is possible.
 
    The `context' is passed as argument to all of the above callback
    functions. */
@@ -203,10 +203,10 @@ SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
 
   /* Send the packet. */
   if (ske->callbacks->send_packet)
-    (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, 
+    (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
                                   ske->callbacks->context);
 
-  /* Save the the payload buffer for future use. It is later used to 
+  /* Save the the payload buffer for future use. It is later used to
      compute the HASH value. */
   ske->start_payload_copy = payload_buf;
   ske->start_payload = start_payload;
@@ -219,7 +219,7 @@ SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
    security properties selected by the responder from our payload
    sent in the silc_ske_initiator_start function. */
 
-SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske, 
+SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
                                         SilcBuffer start_payload)
 {
   SilcSKEStatus status = SILC_SKE_STATUS_OK;
@@ -248,7 +248,7 @@ SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
 
   /* Check version string */
   if (ske->callbacks->check_version) {
-    status = ske->callbacks->check_version(ske, payload->version, 
+    status = ske->callbacks->check_version(ske, payload->version,
                                           payload->version_len,
                                           ske->callbacks->context);
     if (status != SILC_SKE_STATUS_OK) {
@@ -262,7 +262,7 @@ SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
   silc_ske_payload_start_free(ske->start_payload);
 
   /* Take the selected security properties into use while doing
-     the key exchange. This is used only while doing the key 
+     the key exchange. This is used only while doing the key
      exchange. The same data is returned to upper levels by calling
      the callback function. */
   ske->prop = prop = silc_calloc(1, sizeof(*prop));
@@ -328,8 +328,8 @@ SilcSKEStatus silc_ske_initiator_phase_1(SilcSKE ske,
   return status;
 }
 
-/* This function creates random number x, such that 1 < x < q and 
-   computes e = g ^ x mod p and sends the result to the remote end in 
+/* This function creates random number x, such that 1 < x < q and
+   computes e = g ^ x mod p and sends the result to the remote end in
    Key Exchange Payload. */
 
 SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
@@ -352,7 +352,7 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
     return ske->status;
   }
   silc_mp_init(x);
-  status = 
+  status =
     silc_ske_create_rnd(ske, &ske->prop->group->group_order,
                        silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
                        x);
@@ -378,7 +378,7 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
 
   /* Do the Diffie Hellman computation, e = g ^ x mod p */
   silc_mp_init(&payload->x);
-  silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x, 
+  silc_mp_pow_mod(&payload->x, &ske->prop->group->generator, x,
                  &ske->prop->group->group);
 
   /* Get public key */
@@ -410,9 +410,9 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
     silc_ske_make_hash(ske, hash, &hash_len, TRUE);
 
     SILC_LOG_DEBUG(("Signing HASH_i value"));
-    
+
     /* Sign the hash value */
-    silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, 
+    silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
                                   private_key->prv_len);
     if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
        !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
@@ -447,8 +447,8 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
 
   /* Send the packet. */
   if (ske->callbacks->send_packet)
-    (*ske->callbacks->send_packet)(ske, payload_buf, 
-                                  SILC_PACKET_KEY_EXCHANGE_1, 
+    (*ske->callbacks->send_packet)(ske, payload_buf,
+                                  SILC_PACKET_KEY_EXCHANGE_1,
                                   ske->callbacks->context);
 
   silc_buffer_free(payload_buf);
@@ -495,7 +495,7 @@ static void silc_ske_initiator_finish_final(SilcSKE ske,
 
   if (payload->pk_data) {
     /* Decode the public key */
-    if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len, 
+    if (!silc_pkcs_public_key_decode(payload->pk_data, payload->pk_len,
                                     &public_key)) {
       status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
       SILC_LOG_ERROR(("Unsupported/malformed public key received"));
@@ -518,7 +518,7 @@ static void silc_ske_initiator_finish_final(SilcSKE ske,
 
     /* Verify signature */
     silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
-    if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data, 
+    if (silc_pkcs_verify(ske->prop->pkcs, payload->sign_data,
                         payload->sign_len, hash, hash_len) == FALSE) {
       SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
       status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
@@ -526,7 +526,7 @@ static void silc_ske_initiator_finish_final(SilcSKE ske,
     }
 
     SILC_LOG_DEBUG(("Signature is Ok"));
-    
+
     silc_pkcs_public_key_free(public_key);
     memset(hash, 'F', hash_len);
   }
@@ -569,7 +569,7 @@ static void silc_ske_initiator_finish_final(SilcSKE ske,
 
 /* Receives Key Exchange Payload from responder consisting responders
    public key, f, and signature. This function verifies the public key,
-   computes the secret shared key and verifies the signature. 
+   computes the secret shared key and verifies the signature.
 
    The `proto_continue' will be called to indicate that the caller may
    continue with the SKE protocol.  The caller must not continue
@@ -581,7 +581,7 @@ static void silc_ske_initiator_finish_final(SilcSKE ske,
 
    This calls the `verify_key' callback to verify the received public
    key or certificate. If the `verify_key' is provided then the remote
-   must send public key and it is considered to be an error if remote 
+   must send public key and it is considered to be an error if remote
    does not send its public key. If caller is performing a re-key with
    SKE then the `verify_key' is usually not provided when it is not also
    required for the remote to send its public key. */
@@ -620,12 +620,12 @@ SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
 
   if (payload->pk_data && ske->callbacks->verify_key) {
     SILC_LOG_DEBUG(("Verifying public key"));
-    
+
     ske->users++;
     (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
                                  payload->pk_type, ske->callbacks->context,
                                  silc_ske_initiator_finish_final, NULL);
-    
+
     /* We will continue to the final state after the public key has
        been verified by the caller. */
     return SILC_SKE_STATUS_PENDING;
@@ -655,7 +655,7 @@ SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
 /* Starts Key Exchange protocol for responder. Responder receives
    Key Exchange Start Payload from initiator consisting of all the
    security properties the initiator supports. This function decodes
-   the payload and parses the payload further and selects the right 
+   the payload and parses the payload further and selects the right
    security properties. */
 
 SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
@@ -731,7 +731,7 @@ SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
   return status;
 }
 
-/* The selected security properties from the initiator payload is now 
+/* The selected security properties from the initiator payload is now
    encoded into Key Exchange Start Payload and sent to the initiator. */
 
 SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
@@ -753,13 +753,13 @@ SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
 
   prop->group = group;
 
-  if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list, 
+  if (silc_pkcs_alloc(ske->start_payload->pkcs_alg_list,
                      &prop->pkcs) == FALSE) {
     status = SILC_SKE_STATUS_UNKNOWN_PKCS;
     goto err;
   }
 
-  if (silc_cipher_alloc(ske->start_payload->enc_alg_list, 
+  if (silc_cipher_alloc(ske->start_payload->enc_alg_list,
                        &prop->cipher) == FALSE) {
     status = SILC_SKE_STATUS_UNKNOWN_CIPHER;
     goto err;
@@ -778,14 +778,14 @@ SilcSKEStatus silc_ske_responder_phase_1(SilcSKE ske)
   }
 
   /* Encode the payload */
-  status = silc_ske_payload_start_encode(ske, ske->start_payload, 
+  status = silc_ske_payload_start_encode(ske, ske->start_payload,
                                         &payload_buf);
   if (status != SILC_SKE_STATUS_OK)
     goto err;
 
   /* Send the packet. */
   if (ske->callbacks->send_packet)
-    (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, 
+    (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE,
                                   ske->callbacks->context);
 
   silc_buffer_free(payload_buf);
@@ -851,15 +851,15 @@ static void silc_ske_responder_phase2_final(SilcSKE ske,
 
   /* The public key verification was performed only if the Mutual
      Authentication flag is set. */
-  if (ske->start_payload && 
+  if (ske->start_payload &&
       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
     SilcPublicKey public_key = NULL;
     unsigned char hash[32];
     SilcUInt32 hash_len;
 
     /* Decode the public key */
-    if (!silc_pkcs_public_key_decode(recv_payload->pk_data, 
-                                    recv_payload->pk_len, 
+    if (!silc_pkcs_public_key_decode(recv_payload->pk_data,
+                                    recv_payload->pk_len,
                                     &public_key)) {
       ske->status = SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY;
       SILC_LOG_ERROR(("Unsupported/malformed public key received"));
@@ -880,10 +880,10 @@ static void silc_ske_responder_phase2_final(SilcSKE ske,
     }
 
     SILC_LOG_DEBUG(("Verifying signature (HASH_i)"));
-    
+
     /* Verify signature */
     silc_pkcs_public_key_set(ske->prop->pkcs, public_key);
-    if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data, 
+    if (silc_pkcs_verify(ske->prop->pkcs, recv_payload->sign_data,
                         recv_payload->sign_len, hash, hash_len) == FALSE) {
       SILC_LOG_ERROR(("Signature verification failed, incorrect signature"));
       ske->status = SILC_SKE_STATUS_INCORRECT_SIGNATURE;
@@ -891,9 +891,9 @@ static void silc_ske_responder_phase2_final(SilcSKE ske,
        ske->callbacks->proto_continue(ske, ske->callbacks->context);
       return;
     }
-    
+
     SILC_LOG_DEBUG(("Signature is Ok"));
-    
+
     silc_pkcs_public_key_free(public_key);
     memset(hash, 'F', hash_len);
   }
@@ -901,7 +901,7 @@ static void silc_ske_responder_phase2_final(SilcSKE ske,
   /* Create the random number x, 1 < x < q. */
   x = silc_calloc(1, sizeof(*x));
   silc_mp_init(x);
-  status = 
+  status =
     silc_ske_create_rnd(ske, &ske->prop->group->group_order,
                        silc_mp_sizeinbase(&ske->prop->group->group_order, 2),
                        x);
@@ -923,9 +923,9 @@ static void silc_ske_responder_phase2_final(SilcSKE ske,
 
   /* Do the Diffie Hellman computation, f = g ^ x mod p */
   silc_mp_init(&send_payload->x);
-  silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x, 
+  silc_mp_pow_mod(&send_payload->x, &ske->prop->group->generator, x,
                  &ske->prop->group->group);
-  
+
   /* Call the callback. The caller may now continue with the SKE protocol. */
   ske->status = SILC_SKE_STATUS_OK;
   if (ske->callbacks->proto_continue)
@@ -933,10 +933,10 @@ static void silc_ske_responder_phase2_final(SilcSKE ske,
 }
 
 /* This function receives the Key Exchange Payload from the initiator.
-   This also performs the mutual authentication if required. Then, this 
+   This also performs the mutual authentication if required. Then, this
    function first generated a random number x, such that 1 < x < q
    and computes f = g ^ x mod p. This then puts the result f to a Key
-   Exchange Payload. 
+   Exchange Payload.
 
    The `proto_continue' will be called to indicate that the caller may
    continue with the SKE protocol.  The caller must not continue
@@ -970,11 +970,11 @@ SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
 
   /* Verify the received public key and verify the signature if we are
      doing mutual authentication. */
-  if (ske->start_payload && 
+  if (ske->start_payload &&
       ske->start_payload->flags & SILC_SKE_SP_FLAG_MUTUAL) {
 
     SILC_LOG_DEBUG(("We are doing mutual authentication"));
-    
+
     if (!recv_payload->pk_data && ske->callbacks->verify_key) {
       SILC_LOG_ERROR(("Remote end did not send its public key (or "
                      "certificate), even though we require it"));
@@ -986,9 +986,9 @@ SilcSKEStatus silc_ske_responder_phase_2(SilcSKE ske,
       SILC_LOG_DEBUG(("Verifying public key"));
 
       ske->users++;
-      (*ske->callbacks->verify_key)(ske, recv_payload->pk_data, 
+      (*ske->callbacks->verify_key)(ske, recv_payload->pk_data,
                                    recv_payload->pk_len,
-                                   recv_payload->pk_type, 
+                                   recv_payload->pk_type,
                                    ske->callbacks->context,
                                    silc_ske_responder_phase2_final, NULL);
 
@@ -1027,13 +1027,13 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
   /* Compute the shared secret key */
   KEY = silc_calloc(1, sizeof(*KEY));
   silc_mp_init(KEY);
-  silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x, 
+  silc_mp_pow_mod(KEY, &ske->ke1_payload->x, ske->x,
                  &ske->prop->group->group);
   ske->KEY = KEY;
 
   if (public_key && private_key) {
     SILC_LOG_DEBUG(("Getting public key"));
-    
+
     /* Get the public key */
     pk = silc_pkcs_public_key_encode(public_key, &pk_len);
     if (!pk) {
@@ -1042,9 +1042,9 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
     }
     ske->ke2_payload->pk_data = pk;
     ske->ke2_payload->pk_len = pk_len;
-    
+
     SILC_LOG_DEBUG(("Computing HASH value"));
-    
+
     /* Compute the hash value */
     memset(hash, 0, sizeof(hash));
     status = silc_ske_make_hash(ske, hash, &hash_len, FALSE);
@@ -1053,11 +1053,11 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
 
     ske->hash = silc_memdup(hash, hash_len);
     ske->hash_len = hash_len;
-    
+
     SILC_LOG_DEBUG(("Signing HASH value"));
-    
+
     /* Sign the hash value */
-    silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv, 
+    silc_pkcs_private_key_data_set(ske->prop->pkcs, private_key->prv,
                                   private_key->prv_len);
     if (silc_pkcs_get_key_len(ske->prop->pkcs) / 8 > sizeof(sign) - 1 ||
        !silc_pkcs_sign(ske->prop->pkcs, hash, hash_len, sign, &sign_len)) {
@@ -1078,7 +1078,7 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
 
   /* Send the packet. */
   if (ske->callbacks->send_packet)
-    (*ske->callbacks->send_packet)(ske, payload_buf, 
+    (*ske->callbacks->send_packet)(ske, payload_buf,
                                   SILC_PACKET_KEY_EXCHANGE_2,
                                   ske->callbacks->context);
 
@@ -1114,7 +1114,7 @@ SilcSKEStatus silc_ske_end(SilcSKE ske)
   silc_buffer_set(&packet, data, 4);
 
   if (ske->callbacks->send_packet)
-    (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_SUCCESS, 
+    (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_SUCCESS,
                                   ske->callbacks->context);
 
   return SILC_SKE_STATUS_OK;
@@ -1138,7 +1138,7 @@ SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
   silc_buffer_set(&packet, data, 4);
 
   if (ske->callbacks->send_packet)
-    (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_FAILURE, 
+    (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_FAILURE,
                                   ske->callbacks->context);
 
   return SILC_SKE_STATUS_OK;
@@ -1151,7 +1151,7 @@ SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
    as, this function is called by the caller of the protocol and not
    by the protocol itself. */
 
-SilcSKEStatus 
+SilcSKEStatus
 silc_ske_assemble_security_properties(SilcSKE ske,
                                      SilcSKESecurityPropertyFlag flags,
                                      const char *version,
@@ -1202,10 +1202,10 @@ silc_ske_assemble_security_properties(SilcSKE ske,
   rp->comp_alg_list = strdup("none");
   rp->comp_alg_len = strlen("none");
 
-  rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 
+  rp->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
     2 + rp->version_len +
-    2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len + 
-    2 + rp->enc_alg_len + 2 + rp->hash_alg_len + 
+    2 + rp->ke_grp_len + 2 + rp->pkcs_alg_len +
+    2 + rp->enc_alg_len + 2 + rp->hash_alg_len +
     2 + rp->hmac_alg_len + 2 + rp->comp_alg_len;
 
   *return_payload = rp;
@@ -1213,10 +1213,10 @@ silc_ske_assemble_security_properties(SilcSKE ske,
   return SILC_SKE_STATUS_OK;
 }
 
-/* Selects the supported security properties from the remote end's Key 
+/* Selects the supported security properties from the remote end's Key
    Exchange Start Payload. */
 
-SilcSKEStatus 
+SilcSKEStatus
 silc_ske_select_security_properties(SilcSKE ske,
                                    const char *version,
                                    SilcSKEStartPayload *payload,
@@ -1233,7 +1233,7 @@ silc_ske_select_security_properties(SilcSKE ske,
 
   /* Check version string */
   if (ske->callbacks->check_version) {
-    status = ske->callbacks->check_version(ske, rp->version, 
+    status = ske->callbacks->check_version(ske, rp->version,
                                           rp->version_len,
                                           ske->callbacks->context);
     if (status != SILC_SKE_STATUS_OK) {
@@ -1565,10 +1565,10 @@ silc_ske_select_security_properties(SilcSKE ske,
     }
   }
 
-  payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN + 
-    2 + payload->version_len + 
-    2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len + 
-    2 + payload->enc_alg_len + 2 + payload->hash_alg_len + 
+  payload->len = 1 + 1 + 2 + SILC_SKE_COOKIE_LEN +
+    2 + payload->version_len +
+    2 + payload->ke_grp_len + 2 + payload->pkcs_alg_len +
+    2 + payload->enc_alg_len + 2 + payload->hash_alg_len +
     2 + payload->hmac_alg_len + 2 + payload->comp_alg_len;
 
   return SILC_SKE_STATUS_OK;
@@ -1577,8 +1577,8 @@ silc_ske_select_security_properties(SilcSKE ske,
 /* Creates random number such that 1 < rnd < n and at most length
    of len bits. The rnd sent as argument must be initialized. */
 
-static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n, 
-                                        SilcUInt32 len, 
+static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
+                                        SilcUInt32 len,
                                         SilcMPInt *rnd)
 {
   SilcSKEStatus status = SILC_SKE_STATUS_OK;
@@ -1618,7 +1618,7 @@ static SilcSKEStatus silc_ske_create_rnd(SilcSKE ske, SilcMPInt *n,
    hash value defined in the protocol. If it is FALSE then this is used
    to create the HASH value defined by the protocol. */
 
-static SilcSKEStatus silc_ske_make_hash(SilcSKE ske, 
+static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
                                        unsigned char *return_hash,
                                        SilcUInt32 *return_hash_len,
                                        int initiator)
@@ -1635,39 +1635,39 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
     e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
     f = silc_mp_mp2bin(&ske->ke2_payload->x, 0, &f_len);
     KEY = silc_mp_mp2bin(ske->KEY, 0, &KEY_len);
-    
+
     /* Format the buffer used to compute the hash value */
-    buf = silc_buffer_alloc_size(ske->start_payload_copy->len + 
-                                ske->ke2_payload->pk_len + 
-                                ske->ke1_payload->pk_len + 
+    buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
+                                ske->ke2_payload->pk_len +
+                                ske->ke1_payload->pk_len +
                                 e_len + f_len + KEY_len);
     if (!buf)
       return SILC_SKE_STATUS_OUT_OF_MEMORY;
 
     /* Initiator is not required to send its public key */
     if (!ske->ke1_payload->pk_data) {
-      ret = 
+      ret =
        silc_buffer_format(buf,
                           SILC_STR_UI_XNSTRING(ske->start_payload_copy->
                                                data,
                                                ske->start_payload_copy->
                                                len),
-                          SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data, 
+                          SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
                                                ske->ke2_payload->pk_len),
                           SILC_STR_UI_XNSTRING(e, e_len),
                           SILC_STR_UI_XNSTRING(f, f_len),
                           SILC_STR_UI_XNSTRING(KEY, KEY_len),
                           SILC_STR_END);
     } else {
-      ret = 
+      ret =
        silc_buffer_format(buf,
                           SILC_STR_UI_XNSTRING(ske->start_payload_copy->
                                                data,
                                                ske->start_payload_copy->
                                                len),
-                          SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data, 
+                          SILC_STR_UI_XNSTRING(ske->ke2_payload->pk_data,
                                                ske->ke2_payload->pk_len),
-                          SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data, 
+                          SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
                                                ske->ke1_payload->pk_len),
                           SILC_STR_UI_XNSTRING(e, e_len),
                           SILC_STR_UI_XNSTRING(f, f_len),
@@ -1694,17 +1694,17 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
   } else {
     e = silc_mp_mp2bin(&ske->ke1_payload->x, 0, &e_len);
 
-    buf = silc_buffer_alloc_size(ske->start_payload_copy->len + 
+    buf = silc_buffer_alloc_size(ske->start_payload_copy->len +
                                  ske->ke1_payload->pk_len + e_len);
     if (!buf)
       return SILC_SKE_STATUS_OUT_OF_MEMORY;
-    
+
     /* Format the buffer used to compute the hash value */
-    ret = 
+    ret =
       silc_buffer_format(buf,
                         SILC_STR_UI_XNSTRING(ske->start_payload_copy->data,
                                              ske->start_payload_copy->len),
-                        SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data, 
+                        SILC_STR_UI_XNSTRING(ske->ke1_payload->pk_data,
                                              ske->ke1_payload->pk_len),
                         SILC_STR_UI_XNSTRING(e, e_len),
                         SILC_STR_END);
@@ -1734,10 +1734,10 @@ static SilcSKEStatus silc_ske_make_hash(SilcSKE ske,
   return status;
 }
 
-/* Processes the provided key material `data' as the SILC protocol 
+/* Processes the provided key material `data' as the SILC protocol
    specification defines. */
 
-SilcSKEStatus 
+SilcSKEStatus
 silc_ske_process_key_material_data(unsigned char *data,
                                   SilcUInt32 data_len,
                                   SilcUInt32 req_iv_len,
@@ -1785,15 +1785,15 @@ silc_ske_process_key_material_data(unsigned char *data,
     SilcBuffer dist;
     unsigned char k1[32], k2[32], k3[32];
     unsigned char *dtmp;
-    
+
     /* XXX */
     if (enc_key_len > (3 * hash_len))
       return SILC_SKE_STATUS_ERROR;
-    
+
     /* Take first round */
     memset(k1, 0, sizeof(k1));
     silc_hash_make(hash, buf->data, buf->len, k1);
-    
+
     /* Take second round */
     dist = silc_buffer_alloc_size(data_len + hash_len);
     if (!dist)
@@ -1847,15 +1847,15 @@ silc_ske_process_key_material_data(unsigned char *data,
     SilcBuffer dist;
     unsigned char k1[32], k2[32], k3[32];
     unsigned char *dtmp;
-    
+
     /* XXX */
     if (enc_key_len > (3 * hash_len))
       return SILC_SKE_STATUS_ERROR;
-    
+
     /* Take first round */
     memset(k1, 0, sizeof(k1));
     silc_hash_make(hash, buf->data, buf->len, k1);
-    
+
     /* Take second round */
     dist = silc_buffer_alloc_size(data_len + hash_len);
     if (!dist)
@@ -1866,7 +1866,7 @@ silc_ske_process_key_material_data(unsigned char *data,
                       SILC_STR_END);
     memset(k2, 0, sizeof(k2));
     silc_hash_make(hash, dist->data, dist->len, k2);
-    
+
     /* Take third round */
     dist = silc_buffer_realloc(dist, data_len + hash_len + hash_len);
     silc_buffer_pull_tail(dist, hash_len);
@@ -1927,7 +1927,7 @@ silc_ske_process_key_material_data(unsigned char *data,
 /* Processes negotiated key material as protocol specifies. This returns
    the actual keys to be used in the SILC. */
 
-SilcSKEStatus silc_ske_process_key_material(SilcSKE ske, 
+SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
                                            SilcUInt32 req_iv_len,
                                            SilcUInt32 req_enc_key_len,
                                            SilcUInt32 req_hmac_key_len,
@@ -1952,7 +1952,7 @@ SilcSKEStatus silc_ske_process_key_material(SilcSKE ske,
   /* Process the key material */
   status = silc_ske_process_key_material_data(buf->data, buf->len,
                                              req_iv_len, req_enc_key_len,
-                                             req_hmac_key_len, 
+                                             req_hmac_key_len,
                                              ske->prop->hash, key);
 
   memset(tmpbuf, 0, klen);
@@ -1993,7 +1993,7 @@ void silc_ske_free_key_material(SilcSKEKeyMaterial *key)
   silc_free(key);
 }
 
-const char *silc_ske_status_string[] = 
+const char *silc_ske_status_string[] =
 {
   /* Official */
   "Ok",
@@ -2037,16 +2037,16 @@ const char *silc_ske_map_status(SilcSKEStatus status)
 
 /* Parses remote host's version string. */
 
-bool silc_ske_parse_version(SilcSKE ske, 
+bool silc_ske_parse_version(SilcSKE ske,
                            SilcUInt32 *protocol_version,
                            char **protocol_version_string,
-                           SilcUInt32 *software_version, 
+                           SilcUInt32 *software_version,
                            char **software_version_string,
                            char **vendor_version)
 {
   return silc_parse_version_string(ske->remote_version,
-                                  protocol_version, 
-                                  protocol_version_string, 
+                                  protocol_version,
+                                  protocol_version_string,
                                   software_version,
                                   software_version_string,
                                   vendor_version);
index c9ba5f61ffb1a1a2abb83ba1fda97779d27bf487..027525a6d4822cbba8d0a9d0a60999f27e1b3210 100644 (file)
@@ -71,6 +71,7 @@ include_HEADERS =     \
        silcconfig.h    \
        silchashtable.h \
        silclog.h       \
+       silclog_i.h     \
        silcmemory.h    \
        silcmutex.h     \
        silcnet.h       \
index 65dd76b42c6ac102e7988b72851f6eecafbb8430..23653c4b0614c77128cea7cdb8e5744f000f9fb3 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 03fb2a492e6ac0fdb0b8583580a6ff78ed268bb0..032b361e8019209bf651185c1d5dad4730b6bdc4 100644 (file)
@@ -8,8 +8,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index b7f4dfeb3c7e74b5c8568b74e78abe79d2fefdcc..59deac80b1a30a00da3802aa5963dc05611bc81b 100644 (file)
@@ -8,8 +8,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index ab5a25a51f1cf28e057eedcf47e2f019fb62bceb..192204a4d08e90781eb76a6d2cd47d986dd63de1 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 - 2003 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -77,12 +77,13 @@ struct SilcHashTableStruct {
 
 /* Prime sizes for the hash table. The size of the table will always
    be one of these. */
-const SilcUInt32 primesize[42] =
+const SilcUInt32 primesize[] =
 {
   3, 5, 11, 17, 37, 67, 109, 131, 163, 257, 367, 521, 823, 1031,
-  1237, 2053, 2777, 4099, 6247, 8209, 14057, 16411, 21089, 32771, 47431,
-  65537, 106721, 131101, 262147, 360163, 524309, 810343, 1048583, 2097169,
-  4194319, 6153409, 8388617, 13845163, 16777259, 33554467, 67108879
+  1237, 1447, 2053, 2389, 2777, 3323, 4099, 5059, 6247, 7001, 8209, 10993,
+  14057, 16411, 19181, 21089, 25033, 32771, 40009, 47431, 65537, 106721,
+  131101, 262147, 360163, 524309, 810343, 1048583, 2097169, 4194319,
+  6153409, 8388617, 13845163, 16777259, 33554467, 67108879
 };
 
 /* Find appropriate size for the hash table. The size will be a prime. */
index 976005266bb108c190096d9bd6134b79c103d838..2955a5dd761e2203ebb3196dc945871487eb5f4b 100644 (file)
@@ -2,14 +2,13 @@
 
   silclog.c
 
-  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 #include "silcincludes.h"
 
-/* Minimum time delay for log flushing calls (in seconds) */
-#define SILC_LOG_FLUSH_MIN_DELAY 2
-
-/* nice macro for looping through all logs -- makes the code more readable */
-#define SILC_FOREACH_LOG(__x__) for (__x__ = 0; __x__ < SILC_LOG_MAX; __x__++)
-
-/* Our working struct -- at the moment we keep it private, but this could
- * change in the future */
-struct SilcLogStruct {
+/* SilcLogSettings context */
+typedef struct {
+  SilcUInt32 flushdelay;
+
+  char debug_string[128];
+  SilcLogDebugCb debug_cb;
+  void *debug_context;
+  SilcLogHexdumpCb hexdump_cb;
+  void *hexdump_context;
+
+  unsigned int timestamp       : 1;
+  unsigned int quick           : 1;
+  unsigned int debug           : 1;
+  unsigned int debug_hexdump   : 1;
+  unsigned int scheduled       : 1;
+  unsigned int no_init         : 1;
+  unsigned int starting        : 1;
+} *SilcLogSettings, SilcLogSettingsStruct;
+
+/* SilcLog context */
+typedef struct {
   char filename[256];
   FILE *fp;
-  SilcUInt32 maxsize;
+  SilcUInt64 maxsize;
   const char *typename;
   SilcLogType type;
   SilcLogCb cb;
   void *context;
+} *SilcLog, SilcLogStruct;
+
+/* Default settings */
+static SilcLogSettingsStruct silclog =
+{
+  300,
+  { 0 },
+  NULL, NULL,
+  NULL, NULL,
+  TRUE,
+  FALSE,
+  FALSE,
+  FALSE,
+  FALSE,
+  FALSE,
+  TRUE,
 };
-typedef struct SilcLogStruct *SilcLog;
 
-/* These are the known logging channels.  We initialize this struct with most
- * of the fields set to NULL, because we'll fill in those values at runtime. */
-static struct SilcLogStruct silclogs[SILC_LOG_MAX] = {
+/* Default log contexts */
+static SilcLogStruct silclogs[4] =
+{
   {"", NULL, 0, "Info", SILC_LOG_INFO, NULL, NULL},
   {"", NULL, 0, "Warning", SILC_LOG_WARNING, NULL, NULL},
   {"", NULL, 0, "Error", SILC_LOG_ERROR, NULL, NULL},
   {"", NULL, 0, "Fatal", SILC_LOG_FATAL, NULL, NULL},
 };
 
-/* Causes logging output to contain timestamps */
-bool silc_log_timestamp = TRUE;
-
-/* If TRUE, log files will be flushed for each log input */
-bool silc_log_quick = FALSE;
-
-/* Set TRUE/FALSE to enable/disable debugging */
-bool silc_debug = FALSE;
-bool silc_debug_hexdump = FALSE;
-
-/* Flush delay (in seconds) */
-long silc_log_flushdelay = 300;
-
-/* Regular pattern matching expression for the debug output */
-char silc_log_debug_string[128];
-
-/* Debug callbacks. If set, these are triggered for each specific output. */
-static SilcLogDebugCb silc_log_debug_cb = NULL;
-static void *silc_log_debug_context = NULL;
-static SilcLogHexdumpCb silc_log_hexdump_cb = NULL;
-static void *silc_log_hexdump_context = NULL;
-
-/* Did we register already our functions to the scheduler? */
-static bool silc_log_scheduled = FALSE;
-static bool silc_log_no_init = FALSE;
-
-/* This is only needed during starting up -- don't lose any logging message */
-static bool silc_log_starting = TRUE;
+/* Return log context by type */
 
-/* The type wrapper utility. Translates a SilcLogType id to the corresponding
- * logfile, or NULL if not found. */
-static SilcLog silc_log_find_by_type(SilcLogType type)
+static SilcLog silc_log_get_context(SilcLogType type)
 {
-  /* this is not really needed, but i think it's more secure */
-  switch (type) {
-    case SILC_LOG_INFO:
-      return &silclogs[SILC_LOG_INFO];
-    case SILC_LOG_WARNING:
-      return &silclogs[SILC_LOG_WARNING];
-    case SILC_LOG_ERROR:
-      return &silclogs[SILC_LOG_ERROR];
-    case SILC_LOG_FATAL:
-      return &silclogs[SILC_LOG_FATAL];
-    default:
-      return NULL;
-  }
-  return NULL;
+  if (type < 1 || type > 4)
+    return NULL;
+  return &silclogs[(int)type - 1];
 }
 
-/* Given an open log file, checks the size and rotates it if there is a
- * max size set lower then the current size */
+/* Check log file site and cycle log file if it is over max size. */
+
 static void silc_log_checksize(SilcLog log)
 {
-  char newname[127];
-  long size;
+  char newname[256];
+  SilcUInt64 size;
 
   if (!log || !log->fp || !log->maxsize)
-    return; /* we are not interested */
-
-  if ((size = ftell(log->fp)) < 0) {
-    /* OMG, EBADF is here.. we'll try our best.. */
-    FILE *oldfp = log->fp;
-    fclose(oldfp); /* we can discard the error */
-    log->fp = NULL; /* make sure we don't get here recursively */
-    SILC_LOG_ERROR(("Error while checking size of the log file %s, fp=%p",
-                   log->filename, oldfp));
     return;
+
+  size = silc_file_size(log->filename);
+  if (!size) {
+    fclose(log->fp);
+    log->fp = NULL;
   }
+
   if (size < log->maxsize)
     return;
 
-  /* It's too big */
-  fprintf(log->fp, "[%s] [%s] Cycling log file, over max "
-         "logsize (%lu kilobytes)\n",
+  /* Cycle log file */
+  fprintf(log->fp,
+         "[%s] [%s] Cycling log file, over max log size (%lu kilobytes)\n",
          silc_get_time(0), log->typename, (unsigned long)log->maxsize / 1024);
   fflush(log->fp);
   fclose(log->fp);
+
   memset(newname, 0, sizeof(newname));
   snprintf(newname, sizeof(newname) - 1, "%s.old", log->filename);
   unlink(newname);
-
-  /* I heard the following syscall may cause portability issues, but I don't
-   * have any other solution since SILC library doesn't provide any other
-   * function like this. -Johnny */
   rename(log->filename, newname);
-  if (!(log->fp = fopen(log->filename, "w")))
-    SILC_LOG_WARNING(("Couldn't reopen logfile %s for type \"%s\": %s",
+
+  log->fp = fopen(log->filename, "w");
+  if (!log->fp)
+    SILC_LOG_WARNING(("Couldn't reopen log file '%s' for type '%s': %s",
                      log->filename, log->typename, strerror(errno)));
 #ifdef HAVE_CHMOD
   chmod(log->filename, 0600);
 #endif /* HAVE_CHMOD */
 }
 
-/* Reset a logging channel (close and reopen) */
-
-static bool silc_log_reset(SilcLog log)
-{
-  if (!log) return FALSE;
-  if (log->fp) {
-    fflush(log->fp);
-    fclose(log->fp);
-  }
-  if (!log->filename[0]) return FALSE;
-  if (!(log->fp = fopen(log->filename, "a+"))) {
-    SILC_LOG_WARNING(("Couldn't reset logfile %s for type \"%s\": %s",
-                     log->filename, log->typename, strerror(errno)));
-    return FALSE;
-  }
-
-  return TRUE;
-}
-
 /* Internal timeout callback to flush log channels and check file sizes */
 
 SILC_TASK_CALLBACK(silc_log_fflush_callback)
 {
-  unsigned int u;
-  if (!silc_log_quick) {
+  SilcLog log;
+
+  if (!silclog.quick) {
     silc_log_flush_all();
-    SILC_FOREACH_LOG(u)
-      silc_log_checksize(&silclogs[u]);
+    log = silc_log_get_context(SILC_LOG_INFO);
+    silc_log_checksize(log);
+    log = silc_log_get_context(SILC_LOG_WARNING);
+    silc_log_checksize(log);
+    log = silc_log_get_context(SILC_LOG_ERROR);
+    silc_log_checksize(log);
+    log = silc_log_get_context(SILC_LOG_FATAL);
+    silc_log_checksize(log);
   }
-  silc_log_starting = FALSE;
-  if (silc_log_flushdelay < SILC_LOG_FLUSH_MIN_DELAY)
-    silc_log_flushdelay = SILC_LOG_FLUSH_MIN_DELAY;
-  silc_schedule_task_add((SilcSchedule) context, 0, silc_log_fflush_callback,
-                        context, silc_log_flushdelay, 0, SILC_TASK_TIMEOUT,
+
+  silclog.starting = FALSE;
+
+  if (silclog.flushdelay < 2)
+    silclog.flushdelay = 2;
+  silc_schedule_task_add(context, 0, silc_log_fflush_callback, context,
+                        silclog.flushdelay, 0, SILC_TASK_TIMEOUT,
                         SILC_TASK_PRI_NORMAL);
 }
 
-/* Outputs the log message to the first available channel. Channels are
- * ordered by importance (see SilcLogType documentation).
- * More important channels can be printed on less important ones, but not
- * vice-versa. */
+/* Output log message to log file */
 
 void silc_log_output(SilcLogType type, char *string)
 {
   const char *typename = NULL;
+  SilcLog log = silc_log_get_context(type);
   FILE *fp;
-  SilcLog log;
 
-  if ((type > SILC_LOG_MAX) || !(log = silc_log_find_by_type(type)))
+  if (!log)
     goto end;
 
-  /* Save the original typename, because even if we redirect the message
-   * to another channel we'll keep however the original channel name */
-  typename = log->typename;
-
-  /* If there is a custom callback set, use it and return. */
-  if (log->cb) {
+  /* Forward to callback if set */
+  if (log->cb)
     if ((*log->cb)(type, string, log->context))
       goto end;
-  }
 
-  if (!silc_log_scheduled) {
-    if (silc_log_no_init == FALSE) {
+  typename = log->typename;
+
+  if (!silclog.scheduled) {
+    if (silclog.no_init == FALSE) {
       fprintf(stderr,
              "Warning, trying to output without log files initialization, "
              "log output is going to stderr\n");
-      silc_log_no_init = TRUE;
+      silclog.no_init = TRUE;
     }
-    /* redirect output */
+
     fp = stderr;
     log = NULL;
     goto found;
   }
 
-  /* ok, now we have to find an open stream */
-  while (TRUE) {
-    if (log && (fp = log->fp)) goto found;
-    if (type == 0) break;
-    log = silc_log_find_by_type(--type);
-  }
+  /* Find open log file */
+  while (log) {
+    if (log->fp) {
+      fp = log->fp;
+      break;
+    }
 
-  /* Couldn't find any open stream.. sorry :( */
-  SILC_LOG_DEBUG(("Warning! couldn't find any available log channel!"));
-  goto end;
+    log = silc_log_get_context(--type);
+  }
+  if (!log || !log->fp)
+    goto end;
 
  found:
-  /* writes the logging string to the selected channel */
-  if (silc_log_timestamp)
+  if (silclog.timestamp)
     fprintf(fp, "[%s] [%s] %s\n", silc_get_time(0), typename, string);
   else
     fprintf(fp, "[%s] %s\n", typename, string);
 
-  if (silc_log_quick || silc_log_starting) {
+  if (silclog.quick || silclog.starting) {
     fflush(fp);
-    if (log) /* we may have been redirected to stderr */
+    if (log)
       silc_log_checksize(log);
   }
 
  end:
-  /* If debugging, also output the logging message to the console */
-  if (typename && silc_debug) {
+  /* Output log to stderr if debugging */
+  if (typename && silclog.debug) {
     fprintf(stderr, "[Logging] [%s] %s\n", typename, string);
     fflush(stderr);
   }
   silc_free(string);
 }
 
-/* returns an internally allocated pointer to a logging channel file */
-char *silc_log_get_file(SilcLogType type)
-{
-  SilcLog log;
-
-  if (!(log = silc_log_find_by_type(type)))
-    return NULL;
-  if (log->fp)
-    return log->filename;
-  return NULL;
-}
+/* Set and initialize the specified log file. */
 
-/* Set and initialize the specified logging channel. See the API reference */
 bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
                       SilcSchedule scheduler)
 {
   FILE *fp = NULL;
   SilcLog log;
 
-  log = silc_log_find_by_type(type);
+  log = silc_log_get_context(type);
   if (!log)
     return FALSE;
 
-  SILC_LOG_DEBUG(("Setting \"%s\" file to %s (max size=%d)",
+  SILC_LOG_DEBUG(("Setting '%s' file to %s (max size=%d)",
                  log->typename, filename, maxsize));
 
-  /* before assuming the new file, make sure we can open it */
+  /* Open log file */
   if (filename) {
-    if (!(fp = fopen(filename, "a+"))) {
-      fprintf(stderr, "warning: couldn't open log file %s: %s\n",
+    fp = fopen(filename, "a+");
+    if (!fp) {
+      fprintf(stderr, "warning: couldn't open log file '%s': %s\n",
              filename, strerror(errno));
       return FALSE;
     }
@@ -287,7 +243,7 @@ bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
 #endif /* HAVE_CHMOD */
   }
 
-  /* clean the logging channel */
+  /* Close previous log file if it exists */
   if (strlen(log->filename)) {
     if (log->fp)
       fclose(log->fp);
@@ -295,92 +251,210 @@ bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
     log->fp = NULL;
   }
 
+  /* Set new log file */
   if (fp) {
-    memset(log->filename, 0, sizeof(log->filename));
-    strncpy(log->filename, filename,
-           strlen(filename) < sizeof(log->filename) ? strlen(filename) :
-           sizeof(log->filename) - 1);
     log->fp = fp;
     log->maxsize = maxsize;
+
+    memset(log->filename, 0, sizeof(log->filename));
+    silc_strncat(log->filename, sizeof(log->filename), filename,
+                strlen(filename));
   }
 
+  /* Add flush timeout */
   if (scheduler) {
-    if (silc_log_scheduled)
-      return TRUE;
-
-    /* Add schedule hook with a short delay to make sure we'll use
-       right delay */
-    silc_schedule_task_add(scheduler, 0, silc_log_fflush_callback,
-                          (void *) scheduler, 10, 0,
-                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
-    silc_log_scheduled = TRUE;
+    silc_schedule_task_del_by_callback(scheduler, silc_log_fflush_callback);
+    silc_schedule_task_add(scheduler, 0, silc_log_fflush_callback, scheduler,
+                          10, 0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
+    silclog.scheduled = TRUE;
   }
 
   return TRUE;
 }
 
+/* Return log filename */
+
+char *silc_log_get_file(SilcLogType type)
+{
+  SilcLog log = silc_log_get_context(type);
+  return log && log->fp ? log->filename : NULL;
+}
+
 /* Sets a log callback, set callback to NULL to return to default behaviour */
 
 void silc_log_set_callback(SilcLogType type, SilcLogCb cb, void *context)
 {
-  SilcLog log;
+  SilcLog log = silc_log_get_context(type);
+  if (log) {
+    log->cb = cb;
+    log->context = context;
+  }
+}
 
-  if (!(log = silc_log_find_by_type(type)))
-    return;
+/* Reset log callbacks */
 
-  log->cb = cb;
-  log->context = context;
+void silc_log_reset_callbacks(void)
+{
+  SilcLog log;
+  log = silc_log_get_context(SILC_LOG_INFO);
+  log->cb = log->context = NULL;
+  log = silc_log_get_context(SILC_LOG_WARNING);
+  log->cb = log->context = NULL;
+  log = silc_log_get_context(SILC_LOG_ERROR);
+  log->cb = log->context = NULL;
+  log = silc_log_get_context(SILC_LOG_FATAL);
+  log->cb = log->context = NULL;
 }
 
-/* Resets log callbacks */
+/* Flush all log files */
 
-void silc_log_reset_callbacks()
+void silc_log_flush_all(void)
 {
-  unsigned int u;
-  SILC_FOREACH_LOG(u) {
-    silclogs[u].cb = NULL;
-    silclogs[u].context = NULL;
-  }
+  SilcLog log;
+  log = silc_log_get_context(SILC_LOG_INFO);
+  if (log->fp)
+    fflush(log->fp);
+  log = silc_log_get_context(SILC_LOG_WARNING);
+  if (log->fp)
+    fflush(log->fp);
+  log = silc_log_get_context(SILC_LOG_ERROR);
+  if (log->fp)
+    fflush(log->fp);
+  log = silc_log_get_context(SILC_LOG_FATAL);
+  if (log->fp)
+    fflush(log->fp);
 }
 
-/* Flushes all opened logging channels */
+/* Reset a log file */
 
-void silc_log_flush_all() {
-  unsigned int u;
-  SILC_LOG_DEBUG(("Flushing all logs"));
-  SILC_FOREACH_LOG(u) {
-    if (silclogs[u].fp)
-      fflush(silclogs[u].fp);
+static void silc_log_reset(SilcLog log)
+{
+  if (log->fp) {
+    fflush(log->fp);
+    fclose(log->fp);
   }
+
+  if (!strlen(log->filename))
+    return;
+
+  log->fp = fopen(log->filename, "a+");
+  if (!log->fp)
+    SILC_LOG_WARNING(("Couldn't reset log file '%s' for type '%s': %s",
+                     log->filename, log->typename, strerror(errno)));
 }
 
-/* Resets all known logging channels */
+/* Reset all log files */
 
-void silc_log_reset_all() {
-  unsigned int u;
-  SILC_LOG_DEBUG(("Resetting all logs"));
-  SILC_FOREACH_LOG(u)
-    silc_log_reset(&silclogs[u]);
-  /* Immediately flush any possible warning message */
+void silc_log_reset_all(void)
+{
+  SilcLog log;
+  log = silc_log_get_context(SILC_LOG_INFO);
+  if (log->fp)
+    silc_log_reset(log);
+  log = silc_log_get_context(SILC_LOG_WARNING);
+  if (log->fp)
+    silc_log_reset(log);
+  log = silc_log_get_context(SILC_LOG_ERROR);
+  if (log->fp)
+    silc_log_reset(log);
+  log = silc_log_get_context(SILC_LOG_FATAL);
+  if (log->fp)
+    silc_log_reset(log);
   silc_log_flush_all();
 }
 
+/* Sets debug callbacks */
+
+void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
+                                 void *debug_context,
+                                 SilcLogHexdumpCb hexdump_cb,
+                                 void *hexdump_context)
+{
+  silclog.debug_cb = debug_cb;
+  silclog.debug_context = debug_context;
+  silclog.hexdump_cb = hexdump_cb;
+  silclog.hexdump_context = hexdump_context;
+}
+
+/* Resets debug callbacks */
+
+void silc_log_reset_debug_callbacks()
+{
+  silclog.debug_cb = NULL;
+  silclog.debug_context = NULL;
+  silclog.hexdump_cb = NULL;
+  silclog.hexdump_context = NULL;
+}
+
+/* Set current debug string */
+
+void silc_log_set_debug_string(const char *debug_string)
+{
+  char *string;
+  int len;
+  if ((strchr(debug_string, '(') && strchr(debug_string, ')')) ||
+      strchr(debug_string, '$'))
+    string = strdup(debug_string);
+  else
+    string = silc_string_regexify(debug_string);
+  len = strlen(string);
+  if (len >= sizeof(silclog.debug_string))
+    len = sizeof(silclog.debug_string) - 1;
+  memset(silclog.debug_string, 0, sizeof(silclog.debug_string));
+  strncpy(silclog.debug_string, string, len);
+  silc_free(string);
+}
+
+/* Set timestamp */
+
+void silc_log_timestamp(bool enable)
+{
+  silclog.timestamp = enable;
+}
+
+/* Set flushdelay */
+
+void silc_log_flushdelay(SilcUInt32 flushdelay)
+{
+  silclog.flushdelay = flushdelay;
+}
+
+/* Set quick logging */
+
+void silc_log_quick(bool enable)
+{
+  silclog.quick = enable;
+}
+
+/* Set debugging */
+
+void silc_log_debug(bool enable)
+{
+  silclog.debug = enable;
+}
+
+/* Set debug hexdump */
+
+void silc_log_debug_hexdump(bool enable)
+{
+  silclog.debug_hexdump = enable;
+}
+
 /* Outputs the debug message to stderr. */
 
 void silc_log_output_debug(char *file, const char *function,
                           int line, char *string)
 {
-  if (!silc_debug)
+  if (!silclog.debug)
     goto end;
 
-  if (silc_log_debug_string &&
-      !silc_string_regex_match(silc_log_debug_string, file) &&
-      !silc_string_regex_match(silc_log_debug_string, function))
+  if (!silc_string_regex_match(silclog.debug_string, file) &&
+      !silc_string_regex_match(silclog.debug_string, function))
     goto end;
 
-  if (silc_log_debug_cb) {
-    if ((*silc_log_debug_cb)(file, (char *)function, line, string,
-                            silc_log_debug_context))
+  if (silclog.debug_cb) {
+    if ((*silclog.debug_cb)(file, (char *)function, line, string,
+                           silclog.debug_context))
       goto end;
   }
 
@@ -401,18 +475,16 @@ void silc_log_output_hexdump(char *file, const char *function,
   int off, pos, count;
   unsigned char *data = (unsigned char *)data_in;
 
-  if (!silc_debug_hexdump)
+  if (!silclog.debug_hexdump)
     goto end;
 
-  if (silc_log_debug_string &&
-      !silc_string_regex_match(silc_log_debug_string, file) &&
-      !silc_string_regex_match(silc_log_debug_string, function))
+  if (!silc_string_regex_match(silclog.debug_string, file) &&
+      !silc_string_regex_match(silclog.debug_string, function))
     goto end;
 
-  if (silc_log_hexdump_cb) {
-    if ((*silc_log_hexdump_cb)(file, (char *)function, line,
-                              data_in, len, string,
-                              silc_log_hexdump_context))
+  if (silclog.hexdump_cb) {
+    if ((*silclog.hexdump_cb)(file, (char *)function, line,
+                             data_in, len, string, silclog.hexdump_context))
       goto end;
   }
 
@@ -476,45 +548,3 @@ void silc_log_output_hexdump(char *file, const char *function,
  end:
   silc_free(string);
 }
-
-/* Sets debug callbacks */
-
-void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
-                                 void *debug_context,
-                                 SilcLogHexdumpCb hexdump_cb,
-                                 void *hexdump_context)
-{
-  silc_log_debug_cb = debug_cb;
-  silc_log_debug_context = debug_context;
-  silc_log_hexdump_cb = hexdump_cb;
-  silc_log_hexdump_context = hexdump_context;
-}
-
-/* Resets debug callbacks */
-
-void silc_log_reset_debug_callbacks()
-{
-  silc_log_debug_cb = NULL;
-  silc_log_debug_context = NULL;
-  silc_log_hexdump_cb = NULL;
-  silc_log_hexdump_context = NULL;
-}
-
-/* Set current debug string */
-
-void silc_log_set_debug_string(const char *debug_string)
-{
-  char *string;
-  int len;
-  if ((strchr(debug_string, '(') && strchr(debug_string, ')')) ||
-      strchr(debug_string, '$'))
-    string = strdup(debug_string);
-  else
-    string = silc_string_regexify(debug_string);
-  len = strlen(string);
-  if (len >= sizeof(silc_log_debug_string))
-    len = sizeof(silc_log_debug_string) - 1;
-  memset(silc_log_debug_string, 0, sizeof(silc_log_debug_string));
-  strncpy(silc_log_debug_string, string, len);
-  silc_free(string);
-}
index 624120356e8dbd9a35752e7559832ac19d199aa6..af8358501e4d3bc849d6900ef031f02492b85546 100644 (file)
@@ -2,14 +2,13 @@
 
   silclog.h
 
-  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
   Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
  *
  * DESCRIPTION
  *
- *    This is the main logging channel id. There are currently four known
- *    logging channels (plus the debugging output channel), and they are
- *    ordered by importance.
- *
- *    See the source code for SILC coding conventions about how to choose
- *    the right output channel.
+ *    The log type.  This can be given to various silc_log_* routines.
  *
  * SOURCE
  */
 typedef enum {
-  /* Generic info channel file */
-  SILC_LOG_INFO,
-
-  /* This should be used for warnings and non critical failures */
-  SILC_LOG_WARNING,
-
-  /* Generic error and critical failure messages */
-  SILC_LOG_ERROR,
-
-  /* Fatal messages (usually situations that will lead to a program crash */
-  SILC_LOG_FATAL,
-
-  /* Total number logging channels */
-  SILC_LOG_MAX
+  SILC_LOG_INFO       = 1,     /* Generic info */
+  SILC_LOG_WARNING    = 2,      /* Warnings and non-critical failures */
+  SILC_LOG_ERROR      = 3,      /* Generic error and critical failure */
+  SILC_LOG_FATAL      = 4,     /* Fatal error */
 } SilcLogType;
 /***/
 
+#include "silclog_i.h"
+
 /****f* silcutil/SilcLogAPI/SilcLogCb
  *
  * SYNOPSIS
@@ -77,6 +63,7 @@ typedef enum {
  *    The logging custom callback function.  The `type' is the channel ID
  *    that triggered the event, which allows you to use the same callback
  *    function for multiple logging channels.
+ *
  *    The `message' parameter points to a null-terminated buffer containing
  *    the received message, while `context' is the caller-specified context.
  *    The message must not be modified or freed by the callback function.
@@ -101,6 +88,7 @@ typedef bool (*SilcLogCb)(SilcLogType type, char *message, void *context);
  *    corresponding offsets in the source files.  `message' points to a
  *    null-terminated buffer containing the debugging message, and `context'
  *    is the caller-specified context.
+ *
  *    The message must not be modified or freed by the callback function.
  *    If the function returns TRUE, SilcLog will assume the message as handled
  *    and won't run its default handler.
@@ -117,7 +105,8 @@ typedef bool (*SilcLogDebugCb)(char *file, char *function, int line,
  * SYNOPSIS
  *
  *    typedef bool (*SilcDebugHexdumpCb)(char *file, char *function, int line,
- *                                       unsigned char *data, SilcUInt32 data_len,
+ *                                       unsigned char *data,
+ *                                       SilcUInt32 data_len,
  *                                       char *message, void *context;
  *
  * DESCRIPTION
@@ -127,6 +116,7 @@ typedef bool (*SilcLogDebugCb)(char *file, char *function, int line,
  *    like it to be.  `file', `function', and `line' are the corresponding
  *    offsets in the source files.  `data' is the begin of the buffer that
  *    should be hexdumped, which is `data_len' bytes long.
+ *
  *    The `message' parameter points to a null-terminated buffer containing
  *    the received message, while `context' is the caller-specified context.
  *    The message must not be modified or freed by the callback function.
@@ -141,135 +131,8 @@ typedef bool (*SilcLogHexdumpCb)(char *file, char *function, int line,
                                 unsigned char *data, SilcUInt32 data_len,
                                 char *message, void *context);
 
-/* Global Variables */
-
-/****v* silcutil/SilcLogAPI/silc_log_timestamp
- *
- * NAME
- *
- *    bool silc_log_timestamp -- enable/disable fast logging timestamp
- *
- * DESCRIPTION
- *
- *    Causes SilcLog to add a timestamp as returned by silc_get_time().
- *    This may be useful for example if you run your application under a
- *    daemon helper like watchdog that adds its own timestamp.  Defaults to
- *    true.
- *
- ***/
-extern DLLAPI bool silc_log_timestamp;
-
-/****v* silcutil/SilcLogAPI/silc_log_quick
- *
- * NAME
- *
- *    bool silc_log_quick -- enable/disable fast logging output
- *
- * DESCRIPTION
- *
- *    SilcLog makes use of libc stream buffering output, which means that it
- *    saves HD activity by buffering the logging messages and writing them
- *    all together every some minutes (default is 5 minutes).
- *    Setting this variable to TRUE will force SilcLog to write messages to the
- *    filesystem as soon as they are received. This increases the CPU activity
- *    notably on bigger servers, but reduces memory usage.
- *    If you want to change the logging style on-the-fly, make sure to call
- *    silc_log_flush_all() after setting this variable to TRUE.
- *
- ***/
-extern DLLAPI bool silc_log_quick;
-
-/****v* silcutil/SilcLogAPI/silc_log_flushdelay
- *
- * NAME
- *
- *    long silc_log_flushdelay -- flushing time delay
- *
- * DESCRIPTION
- *
- *    Sets the logfiles flushing delay in seconds.  As for now, changing this
- *    value AFTER logfiles initialization won't take effect until previous
- *    delay time will expire; for example if you change from 300 seconds to
- *    60 seconds you will have to wait up to 300 seconds for this change to
- *    take effect.
- *    This value must be greater than 2 seconds.
- *
- ***/
-extern DLLAPI long silc_log_flushdelay;
-
-/****v* silcutil/SilcLogAPI/silc_debug
- *
- * NAME
- *
- *    bool silc_debug -- enable/disable debugging output
- *
- * DESCRIPTION
- *
- *    If silc_debug is set to FALSE, debugging functions won't procude any
- *    output.  This is useful when for example you compile in the debugging
- *    support but at a certain point you want to send the program in the
- *    background.
- *
- * SEE ALSO
- *    SILC_LOG_DEBUG
- *
- ***/
-extern DLLAPI bool silc_debug;
-
-/****v* silcutil/SilcLogAPI/silc_debug_hexdump
- *
- * NAME
- *
- *    bool silc_debug_hexdump -- enable/disable debugging output
- *
- * DESCRIPTION
- *
- *    If silc_debug_hexdump is set to FALSE, debugging functions won't produce
- *    any output.  This is useful when for example you compile in the debugging
- *    support but at a certain point you want to send the program in the
- *    background.
- *
- * SEE ALSO
- *    SILC_LOG_HEXDUMP
- *
- ***/
-extern DLLAPI bool silc_debug_hexdump;
-
 /* Macros */
 
-#if defined(WIN32)
-#ifndef __FUNCTION__
-#define __FUNCTION__ ""
-#endif
-#endif
-
-/****d* silcutil/SilcLogAPI/SILC_ENABLE_DEBUG
- *
- * NAME
- *
- *    #define SILC_ENABLE_DEBUG
- *
- * DESCRIPTION
- *
- *    Use this macro to enable the debugging in your application.  If
- *    SILC was compiled with debugging enabled, this macro enables it.
- *    Use this macro in your application's main header, or in place where
- *    you need to enable the debugging.
- *
- * NOTES
- *
- *    You still can control the debugging with silc_debug variable, on
- *    whether to actually print the debugging or not.  This macro is
- *    used to enable debugging, not to say it is printed or not.
- *
- * SOURCE
- */
-#define SILC_ENABLE_DEBUG      \
-  #ifndef SILC_DEBUG           \
-  #define SILC_DEBUG 1         \
-  #endif
-/***/
-
 /****d* silcutil/SilcLogAPI/SILC_LOG_INFO
  *
  * NAME
@@ -364,19 +227,19 @@ extern DLLAPI bool silc_debug_hexdump;
  *    This is a special wrapper to the debugging output (usually stderr).
  *    The standard behaviour is the same as SILC_LOG_INFO, with the difference
  *    that this macro also depends on the global define SILC_DEBUG.
+ *
  *    Undefining SILC_DEBUG causes these functions to be defined to an empty
  *    value, thus removing all debug logging calls from the compiled
  *    application.
- *    This macro is also affected by the global variable silc_debug.
  *
  * SOURCE
  */
 #if defined(SILC_DEBUG)
-#define SILC_LOG_DEBUG(fmt) silc_log_output_debug(__FILE__, \
-                               __FUNCTION__, \
-                               __LINE__, \
+#define SILC_LOG_DEBUG(fmt) silc_log_output_debug(__FILE__,    \
+                               __FUNCTION__,                   \
+                               __LINE__,                       \
                                silc_format fmt)
-#define SILC_NOT_IMPLEMENTED(string) \
+#define SILC_NOT_IMPLEMENTED(string)                                   \
   SILC_LOG_INFO(("*********** %s: NOT IMPLEMENTED YET", string));
 #else
 #define SILC_LOG_DEBUG(fmt) do { } while(0)
@@ -424,30 +287,29 @@ extern DLLAPI bool silc_debug_hexdump;
 
 /* Prototypes */
 
-/****f* silcutil/SilcLogAPI/silc_log_output
+/****f* silcutil/SilcLogAPI/silc_log_set_file
  *
  * SYNOPSIS
  *
- *    void silc_log_output(SilcLogType type, char *string);
+ *    bool silc_log_set_file(SilcLogType type, char *filename,
+ *                           SilcUInt32 maxsize,
+ *                           SilcSchedule scheduler);
  *
  * DESCRIPTION
  *
- *    This is the main function for logging output. Please note that you
- *    should rather use one of the logging wrapper macros.
- *
- *    If you really want to use this function, its usage is quite simple.
- *    The `type' parameter identifies the channel to use, while the `string'
- *    parameter must be a dynamic allocated (null-terminated) buffer, because
- *    it will be freed at the end of this function, for internal reasons.
- *    If there are registered callbacks for the specified type, this function
- *    will first trigger those callbacks.  The callback functions must NOT
- *    free or modify the original buffer.
+ *    Sets `filename', which can be maximum `maxsize' bytes long, as the new
+ *    logging file for the channel `type'.  If you specify an illegal filename
+ *    a warning message is printed and FALSE is returned.  In this case
+ *    logging settings are not changed.
  *
- * SEE ALSO
- *    SILC_LOG_INFO, SILC_LOG_WARNING, SILC_LOG_ERROR, SILC_LOG_FATAL
+ *    You can disable logging for a channel by specifying NULL filename, the
+ *    maxsize in this case is not important.  The `scheduler' parameter is
+ *    needed by the internal logging to allow buffered output and thus to
+ *    save HD activity.
  *
  ***/
-void silc_log_output(SilcLogType type, char *string);
+bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
+                      SilcSchedule scheduler);
 
 /****f* silcutil/SilcLogAPI/silc_log_get_file
  *
@@ -468,30 +330,6 @@ void silc_log_output(SilcLogType type, char *string);
  ***/
 char *silc_log_get_file(SilcLogType type);
 
-/****f* silcutil/SilcLogAPI/silc_log_set_file
- *
- * SYNOPSIS
- *
- *    bool silc_log_set_file(SilcLogType type, char *filename,
- *                           SilcUInt32 maxsize,
- *                           SilcSchedule scheduler);
- *
- * DESCRIPTION
- *
- *    Sets `filename', which can be maximum `maxsize' bytes long, as the new
- *    logging file for the channel `type'.  If you specify an illegal filename
- *    a warning message is printed and FALSE is returned.  In this case
- *    logging settings are not changed.
- *
- *    You can disable logging for a channel by specifying NULL filename, the
- *    maxsize in this case is not important.  The `scheduler' parameter is
- *    needed by the internal logging to allow buffered output and thus to
- *    save HD activity.
- *
- ***/
-bool silc_log_set_file(SilcLogType type, char *filename, SilcUInt32 maxsize,
-                      SilcSchedule scheduler);
-
 /****f* silcutil/SilcLogAPI/silc_log_set_callback
  *
  * SYNOPSIS
@@ -530,7 +368,7 @@ void silc_log_set_callback(SilcLogType type, SilcLogCb cb, void *context);
  *    rather need to call silc_log_set_debug_callbacks() with NULL callbacks.
  *
  ***/
-void silc_log_reset_callbacks();
+void silc_log_reset_callbacks(void);
 
 /****f* silcutil/SilcLogAPI/silc_log_flush_all
  *
@@ -547,7 +385,7 @@ void silc_log_reset_callbacks();
  *    silc_log_quick
  *
  ***/
-void silc_log_flush_all();
+void silc_log_flush_all(void);
 
 /****f* silcutil/SilcLogAPI/silc_log_reset_all
  *
@@ -559,52 +397,12 @@ void silc_log_flush_all();
  *
  *    Forces all logging channels to close and reopen their streams.  Useful
  *    for example after a SIGHUP signal.
+ *
  *    Please note that this function could generate some warning messages if
  *    one or more logging channels point to an illegal filename.
  *
  ***/
-void silc_log_reset_all();
-
-/****f* silcutil/SilcLogAPI/silc_log_output_debug
- *
- * SYNOPSIS
- *
- *    void silc_log_output_debug(char *file, const char *function,
- *                               int line, char *string);
- *
- * DESCRIPTION
- *
- *    This is the main function for debug output.  Please note that you should
- *    rather use the wrapper macro SILC_LOG_DEBUG.
- *    If you want to use it anyway, the `file', `function', and `line' are the
- *    corresponding offsets in the source files, while `string' must be a
- *    dynamic allocated (null-terminated) buffer.
- *
- ***/
-void silc_log_output_debug(char *file, const char *function,
-                          int line, char *string);
-
-/****f* silcutil/SilcLogAPI/silc_log_output_hexdump
- *
- * SYNOPSIS
- *
- *    void silc_log_output_hexdump(char *file, char *function,
- *                                 int line, void *data_in,
- *                                 SilcUInt32 len, char *string);
- *
- * DESCRIPTION
- *
- *    This is the main function for hexdump output.  Please note that you
- *    should rather use the wrapper macro SILC_LOG_HEXDUMP.
- *    If you want to use it anyway, the `file', `function', and `line' are the
- *    corresponding offsets in the source files, `data_in' is the beginning
- *    of the buffer you wish to hexdump, which is `len' bytes long.
- *    `string' must be a dynamic allocated (null-terminated) buffer.
- *
- ***/
-void silc_log_output_hexdump(char *file, const char *function,
-                            int line, void *data_in,
-                            SilcUInt32 len, char *string);
+void silc_log_reset_all(void);
 
 /****f* silcutil/SilcLogAPI/silc_log_set_debug_callbacks
  *
@@ -621,15 +419,13 @@ void silc_log_output_hexdump(char *file, const char *function,
  *    output, that will be called with the `debug_context' parameter.
  *    When SilcLog receives a debug message, it will trigger the callback
  *    function.  If the callback function returns TRUE SilcLog will assume
- *    the input as handled and won't run its default handler.
- *    `hexdump_cb' and `hexdump_context' works the same way, except that they
- *    are referred to SILC_LOG_HEXDUMP requests.
- *    You can disable/remove a callback by setting it to NULL.
- *    If set, each callback function must be either in the form described by
- *    SilcLogDebugCb or SilcLogHexdumpCb.
+ *    the input as handled and won't run its default handler.  The `hexdump_cb'
+ *    and `hexdump_context' works the same way, except that they are referred
+ *    to SILC_LOG_HEXDUMP requests.
  *
- * SEE ALSO
- *    SilcLogDebugCb,  SilcLogHexdumpCb
+ *    You can disable/remove a callback by setting it to NULL.  If set, each
+ *    callback function must be either in the form described by SilcLogDebugCb
+ *    or SilcLogHexdumpCb.
  *
  ***/
 void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
@@ -637,6 +433,19 @@ void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
                                  SilcLogHexdumpCb hexdump_cb,
                                  void *hexdump_context);
 
+/****f* silcutil/SilcLogAPI/silc_log_reset_debug_callbacks
+ *
+ * SYNOPSIS
+ *
+ *    void silc_log_reset_debug_callbacks();
+ *
+ * DESCRIPTION
+ *
+ *    Resets debug callbacks set with silc_log_set_debug_callbacks.
+ *
+ ***/
+void silc_log_reset_debug_callbacks(void);
+
 /****f* silcutil/SilcLogAPI/silc_log_set_debug_string
  *
  * SYNOPSIS
@@ -652,4 +461,91 @@ void silc_log_set_debug_callbacks(SilcLogDebugCb debug_cb,
  ***/
 void silc_log_set_debug_string(const char *debug_string);
 
+/****f* silcutil/SilcLogAPI/silc_log_timestamp
+ *
+ * NAME
+ *
+ *    void silc_log_timestamp(bool enable);
+ *
+ * DESCRIPTION
+ *
+ *    Use timestamp in log messages.  Set `enable' to TRUE to enable
+ *    timestamp and to FALSE to disable it.  Default is TRUE.
+ *
+ ***/
+void silc_log_timestamp(bool enable);
+
+/****f* silcutil/SilcLogAPI/silc_log_flushdelay
+ *
+ * NAME
+ *
+ *    void silc_log_flushdelay(SilcUInt32 flushdelay);
+ *
+ * DESCRIPTION
+ *
+ *    Sets the logfiles flushing delay in seconds.  Default is 300 seconds.
+ *
+ ***/
+void silc_log_flushdelay(SilcUInt32 flushdelay);
+
+/****f* silcutil/SilcLogAPI/silc_log_quick
+ *
+ * NAME
+ *
+ *    void silc_log_quick(bool enable);
+ *
+ * DESCRIPTION
+ *
+ *    SilcLog makes use of libc stream buffering output, which means that it
+ *    saves HD activity by buffering the logging messages and writing them
+ *    all together every some minutes (default is 5 minutes).
+ *
+ *    Setting `enable' to TRUE will force SilcLog to write messages to the
+ *    filesystem as soon as they are received. This increases the CPU activity
+ *    notably on bigger servers, but reduces memory usage.
+ *
+ *    If you want to change the logging style on-the-fly, make sure to call
+ *    silc_log_flush_all() after setting `enable'  to TRUE.
+ *
+ *    Default is FALSE.
+ *
+ ***/
+void silc_log_quick(bool enable);
+
+/****v* silcutil/SilcLogAPI/silc_log_debug
+ *
+ * NAME
+ *
+ *    void silc_log_debug(bool enable);
+ *
+ * DESCRIPTION
+ *
+ *    If `enable' is set to FALSE, debugging functions won't procude any
+ *    output and if set to TRUE prints debug messages to stderr.  Default
+ *    is FALSE.
+ *
+ * SEE ALSO
+ *    SILC_LOG_DEBUG
+ *
+ ***/
+void silc_log_debug(bool enable);
+
+/****v* silcutil/SilcLogAPI/silc_log_debug_hexdump
+ *
+ * NAME
+ *
+ *    void silc_log_debug_hexdump(bool enable);
+ *
+ * DESCRIPTION
+ *
+ *    If `enable' is set to FALSE, debugging functions won't produce
+ *    any output anf if set to TRUE prints hexdump debug message to
+ *    stderr.  Default is FALSE.
+ *
+ * SEE ALSO
+ *    SILC_LOG_HEXDUMP
+ *
+ ***/
+void silc_log_debug_hexdump(bool enable);
+
 #endif /* !SILCLOG_H */
diff --git a/lib/silcutil/silclog_i.h b/lib/silcutil/silclog_i.h
new file mode 100644 (file)
index 0000000..2615635
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+
+  silclog_i.h
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2005 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  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 General Public License for more details.
+
+*/
+
+#ifndef SILCLOG_I_H
+#define SILCLOG_I_H
+
+#ifndef SILCLOG_H
+#error "Do not include this header directly"
+#endif
+
+#if defined(WIN32)
+#ifndef __FUNCTION__
+#define __FUNCTION__ ""
+#endif
+#endif
+
+void silc_log_output(SilcLogType type, char *string);
+void silc_log_output_debug(char *file, const char *function,
+                          int line, char *string);
+void silc_log_output_hexdump(char *file, const char *function,
+                            int line, void *data_in,
+                            SilcUInt32 len, char *string);
+
+#endif /* SILCLOG_I_H */
index ca5e806682d90d49b3cae46011f540efb0a67ad5..19b4863f61790e8be92b5f40b67cd27b880cc0e9 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
   silcmutex.h
+
   Author: Pekka Riikonen <priikone@silcnet.org>
-  Copyright (C) 2001 Pekka Riikonen
+
+  Copyright (C) 2001 - 2005 Pekka Riikonen
+
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -23,7 +22,7 @@
  * DESCRIPTION
  *
  * Interface for the SILC Mutex locking implementation. This is platform
- * independent mutual exclusion interface for applications that need 
+ * independent mutual exclusion interface for applications that need
  * concurrency control.
  *
  ***/
@@ -34,7 +33,7 @@
 /****s* silcutil/SilcMutexAPI/SilcMutex
  *
  * NAME
- * 
+ *
  *    typedef struct SilcMutexStruct *SilcMutex;
  *
  * DESCRIPTION
@@ -49,7 +48,7 @@ typedef struct SilcMutexStruct *SilcMutex;
 /****d* silcutil/SilcMutexAPI/SILC_MUTEX_DEFINE
  *
  * NAME
- * 
+ *
  *    #define SILC_MUTEX_DEFINE(name) ...
  *
  * DESCRIPTION
@@ -87,7 +86,8 @@ bool silc_mutex_alloc(SilcMutex *mutex);
  *
  * DESCRIPTION
  *
- *    Free SILC Mutex object and frees all allocated memory.
+ *    Free SILC Mutex object and frees all allocated memory.  If `mutex'
+ *    is NULL this function has no effect.
  *
  ***/
 void silc_mutex_free(SilcMutex mutex);
@@ -102,7 +102,8 @@ void silc_mutex_free(SilcMutex mutex);
  *
  *    Locks the mutex. If the mutex is locked by another thread the
  *    current thread will block until the other thread has issued
- *    silc_mutex_unlock for the mutex.
+ *    silc_mutex_unlock for the mutex.  If `mutex' is NULL this function
+ *    has no effect.
  *
  * NOTES
  *
@@ -122,7 +123,8 @@ void silc_mutex_lock(SilcMutex mutex);
  * DESCRIPTION
  *
  *    Unlocks the mutex and thus releases it for another thread that
- *    may be waiting for the lock.
+ *    may be waiting for the lock.  If `mutex' is NULL this function
+ *    has no effect.
  *
  * NOTES
  *
index d083656eba63e379357d64acdc60848ec9aad701..a77311cde20b4b2aca836d6fe62a3415d898c040 100644 (file)
@@ -8,8 +8,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 9dd5acd26bd454c5adbdcffe7f88755bae43bca8..062eddfd1cbcd2cf7531af684a16b1912e1df49e 100644 (file)
@@ -4,12 +4,11 @@
  
   Author: Pekka Riikonen <priikone@silcnet.org>
  
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 67a6640aaa2ebd116100d2afa0cb54533233400c..a0a34d238618315dd6337838232c720aedaa338c 100644 (file)
@@ -2,14 +2,13 @@
 
   silcprotocol.c
 
-  Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+  Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 74393280160567cc87cc216e695f287d3943f85a..9f8706d9dd803a190fb458f08af1b1f36f91db22 100644 (file)
@@ -4,12 +4,11 @@
  
   Author: Pekka Riikonen <priikone@silcnet.org>
  
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 5ea2ebf00a743da144358d6fd9c506face1902c2..169f4535d275646112b0ab364dfb0b32e4da2aa0 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1998 - 2003 Pekka Riikonen
+  Copyright (C) 1998 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -607,6 +607,16 @@ bool silc_schedule_one(SilcSchedule schedule, int timeout_usecs)
     return FALSE;
   }
 
+  /* If the task queues aren't initialized or we aren't valid anymore
+     we will return */
+  if ((!schedule->fd_queue && !schedule->timeout_queue
+       && !schedule->generic_queue) || schedule->valid == FALSE) {
+    SILC_LOG_DEBUG(("Scheduler not valid anymore, exiting"));
+    if (!schedule->is_locked)
+      SILC_SCHEDULE_UNLOCK(schedule);
+    return FALSE;
+  }
+
   /* Calculate next timeout for silc_select(). This is the timeout value
      when at earliest some of the timeout tasks expire. */
   silc_mutex_lock(schedule->timeout_queue->lock);
index c7a8697edce282a0c399c672896b88eb90d3e3c2..be24c41a20c8df5864d258a288381264dffe3688 100644 (file)
@@ -2,16 +2,13 @@
   
   silcschedule.h
  
-  COPYRIGHT
   Author: Pekka Riikonen <priikone@silcnet.org>
  
-  Copyright (C) 1998 - 2001 Pekka Riikonen
+  Copyright (C) 1998 - 2005 Pekka Riikonen
  
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
  
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 7e2b6026cf14bf95a228cdd2a127b64b4ea78b86..88a15a95733dd8327c597af08d07df3aa6ce0100 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 06becee09d32015feba4500786eb995d27ede943..c1ecf92d4801e0b58c45c9d0a9f1b1ba5d2057a7 100644 (file)
@@ -1,16 +1,15 @@
 /*
 
   silcmutex.h
+
   Author: Pekka Riikonen <priikone@silcnet.org>
-  Copyright (C) 2001 Pekka Riikonen
+
+  Copyright (C) 2001 - 2005 Pekka Riikonen
+
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -24,7 +23,7 @@
  *
  * Interface for SILC Thread implementation. This is platform independent
  * interface of threads for applications that need concurrent execution
- * with the application's main thread. The threads created with this 
+ * with the application's main thread. The threads created with this
  * interface executes concurrently with the calling thread.
  *
  ***/
@@ -37,7 +36,7 @@
 /****s* silcutil/SilcThreadAPI/SilcThread
  *
  * NAME
- * 
+ *
  *    typedef struct SilcThreadStruct *SilcThread;
  *
  * DESCRIPTION
@@ -72,7 +71,7 @@ typedef void *(*SilcThreadStart)(void *context);
  *
  * SYNOPSIS
  *
- *    SilcThread silc_thread_create(SilcThreadStart start_func, 
+ *    SilcThread silc_thread_create(SilcThreadStart start_func,
  *                                  void *context, bool waitable);
  * DESCRIPTION
  *
index e0025733ca7578c29af6defb258a0d749c9fa8c8..8462ffbda05b2777e484fbc866b449f90db1c1a7 100644 (file)
 
 AUTOMAKE_OPTIONS = 1.0 no-dependencies foreign
 
-bin_PROGRAMS =         test_silcstrutil test_silcstringprep test_silchashtable
+bin_PROGRAMS =         test_silcstrutil test_silcstringprep test_silchashtable \
+       test_silclist
 
 test_silcstrutil_SOURCES = test_silcstrutil.c
 test_silcstringprep_SOURCES = test_silcstringprep.c
 test_silchashtable_SOURCES = test_silchashtable.c
+test_silclist_SOURCES = test_silclist.c
 
 LIBS = $(SILC_COMMON_LIBS)
 LDADD = -L.. -L../.. -lsilc
diff --git a/lib/silcutil/tests/test_silclist.c b/lib/silcutil/tests/test_silclist.c
new file mode 100644 (file)
index 0000000..93aad06
--- /dev/null
@@ -0,0 +1,86 @@
+/* SilcList tests */
+
+#include "silcincludes.h"
+
+struct foo {
+  int i;
+  struct foo *next;
+};
+
+int main(int argc, char **argv)
+{
+  bool success = FALSE;
+  SilcList list;
+  struct foo *f, *f1, *f2, *f3;
+
+  if (argc > 1 && !strcmp(argv[1], "-d")) {
+    silc_debug = 1;
+    silc_debug_hexdump = 1;
+    silc_log_set_debug_string("*list*");
+  }
+
+  silc_list_init(list, struct foo, next);
+  f1 = silc_calloc(1, sizeof(*f1));
+  if (!f1)
+    goto err;
+  f1->i = 1;
+  f2 = silc_calloc(1, sizeof(*f2));
+  if (!f2)
+    goto err;
+  f2->i = 2;
+  f3 = silc_calloc(1, sizeof(*f3));
+  if (!f3)
+    goto err;
+  f3->i = 3;
+
+  silc_list_add(list, f1);
+  silc_list_add(list, f2);
+  silc_list_add(list, f3);
+
+  SILC_LOG_DEBUG(("f1=%p", f1));
+  SILC_LOG_DEBUG(("f2=%p", f2));
+  SILC_LOG_DEBUG(("f3=%p", f3));
+
+  silc_list_start(list);
+  while ((f = silc_list_get(list)) != SILC_LIST_END) {
+    SILC_LOG_DEBUG(("entry %d, %p, next=%p", f->i, f, f->next));
+  }
+
+  silc_list_start(list);
+  silc_list_del(list, f1);
+  while ((f = silc_list_get(list)) != SILC_LIST_END) {
+    SILC_LOG_DEBUG(("entry %d, %p, next=%p", f->i, f, f->next));
+  }
+  silc_list_del(list, f3);
+  while ((f = silc_list_get(list)) != SILC_LIST_END) {
+    SILC_LOG_DEBUG(("entry %d, %p, next=%p", f->i, f, f->next));
+  }
+  silc_list_del(list, f2);
+  while ((f = silc_list_get(list)) != SILC_LIST_END) {
+    SILC_LOG_DEBUG(("entry %d, %p, next=%p", f->i, f, f->next));
+  }
+
+  silc_list_add(list, f1);
+  silc_list_add(list, f2);
+  silc_list_add(list, f3);
+
+  silc_list_start(list);
+  while ((f = silc_list_get(list)) != SILC_LIST_END) {
+    SILC_LOG_DEBUG(("entry %d, %p, next=%p", f->i, f, f->next));
+  }
+
+  silc_list_del(list, f2);
+
+  silc_list_start(list);
+  while ((f = silc_list_get(list)) != SILC_LIST_END) {
+    SILC_LOG_DEBUG(("entry %d, %p, next=%p", f->i, f, f->next));
+  }
+
+  success = TRUE;
+
+ err:
+  SILC_LOG_DEBUG(("Testing was %s", success ? "SUCCESS" : "FAILURE"));
+  fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
+
+  return success;
+}
index f7b4faf81078facbe9bf9244cad13d352080ffe5..dcf9466273040b88205fb2f287ca565101e954d2 100644 (file)
@@ -52,12 +52,30 @@ int main(int argc, char **argv)
 {
   bool success = FALSE;
   unsigned char *s1, *s2, *s3, *s4;
-  int l;
-
-  if (argc > 1 && !strcmp(argv[1], "-d")) {
-    silc_debug = 1;
-    silc_debug_hexdump = 1;
-    silc_log_set_debug_string("*strutil*");
+  int l, opt;
+
+  while ((opt = getopt(argc, argv, "hVd")) != EOF) {
+      switch(opt) {
+        case 'h':
+          printf("usage: test_silcstrutil\n");
+         exit(0);
+          break;
+        case 'V':
+          printf("Secure Internet Live Conferencing\n");
+          exit(0);
+          break;
+        case 'd':
+          silc_debug = TRUE;
+         silc_debug_hexdump = TRUE;
+          if (optarg)
+            silc_log_set_debug_string(optarg);
+         else
+           silc_log_set_debug_string("*strutil*");
+          break;
+       default:
+         exit(1);
+         break;
+      }
   }
 
   /* Failure tests */
index d6eb0f233f973dd63e51d183b29b5ad577fb4696..1336eaeea7d57592db62d2983d3f4dda6efca471 100644 (file)
@@ -4,13 +4,12 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -45,27 +44,33 @@ bool silc_mutex_alloc(SilcMutex *mutex)
 void silc_mutex_free(SilcMutex mutex)
 {
 #ifdef SILC_THREADS
-  pthread_mutex_destroy(&mutex->mutex);
-  silc_free(mutex);
+  if (mutex) {
+    pthread_mutex_destroy(&mutex->mutex);
+    silc_free(mutex);
+  }
 #endif /* SILC_THREADS */
 }
 
 void silc_mutex_lock(SilcMutex mutex)
 {
 #ifdef SILC_THREADS
-  if (pthread_mutex_lock(&mutex->mutex))
-    assert(FALSE);
-  assert(mutex->locked == 0);
-  mutex->locked = 1;
+  if (mutex) {
+    if (pthread_mutex_lock(&mutex->mutex))
+      assert(FALSE);
+    assert(mutex->locked == 0);
+    mutex->locked = 1;
+  }
 #endif /* SILC_THREADS */
 }
 
 void silc_mutex_unlock(SilcMutex mutex)
 {
 #ifdef SILC_THREADS
-  assert(mutex->locked == 1);
-  mutex->locked = 0;
-  if (pthread_mutex_unlock(&mutex->mutex))
-    assert(FALSE);
+  if (mutex) {
+    assert(mutex->locked == 1);
+    mutex->locked = 0;
+    if (pthread_mutex_unlock(&mutex->mutex))
+      assert(FALSE);
+  }
 #endif /* SILC_THREADS */
 }
index d2e52e936a1d75ff444926ab27e8d6e75bbc949d..f997196dca340dae737e5ca26786281211f48be9 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 575c54a894a8b8d4f09210b11d8c0ed9cc0d0df9..94f23f168ff50b4f4e7a04b474302cbcc3032899 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 592661649d4ded3542bb414027626201755773b5..75a6adcabf7c262471f89179e6fdd20d99dc8f3e 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 11c03c9c8e354ff7ca985f7f4a603f9e0412e9bd..09e8e90ab01774d1edd5db1f1d13d80cb14c85eb 100644 (file)
@@ -4,13 +4,12 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  
+  the Free Software Foundation; version 2 of the License.
+
   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
@@ -22,9 +21,9 @@
 #include "silcincludes.h"
 
 /* SILC Mutex structure */
-struct SilcMutexStruct {       
+struct SilcMutexStruct {
 #ifdef SILC_THREADS
-  CRITICAL_SECTION mutex;  
+  CRITICAL_SECTION mutex;
   BOOL locked;
 #else
   void *tmp;
@@ -34,8 +33,8 @@ struct SilcMutexStruct {
 bool silc_mutex_alloc(SilcMutex *mutex)
 {
 #ifdef SILC_THREADS
-  *mutex = silc_calloc(1, sizeof(**mutex));  
-  InitializeCriticalSection(&((*mutex)->mutex));  
+  *mutex = silc_calloc(1, sizeof(**mutex));
+  InitializeCriticalSection(&((*mutex)->mutex));
 #endif /* SILC_THREADS */
   return TRUE;
 }
@@ -43,25 +42,31 @@ bool silc_mutex_alloc(SilcMutex *mutex)
 void silc_mutex_free(SilcMutex mutex)
 {
 #ifdef SILC_THREADS
-  DeleteCriticalSection(&mutex->mutex);
-  silc_free(mutex);
+  if (mutex) {
+    DeleteCriticalSection(&mutex->mutex);
+    silc_free(mutex);
+  }
 #endif /* SILC_THREADS */
 }
 
 void silc_mutex_lock(SilcMutex mutex)
 {
 #ifdef SILC_THREADS
-  EnterCriticalSection(&mutex->mutex);    
-  assert(mutex->locked == FALSE);
-  mutex->locked = TRUE;
+  if (mutex) {
+    EnterCriticalSection(&mutex->mutex);
+    assert(mutex->locked == FALSE);
+    mutex->locked = TRUE;
+  }
 #endif /* SILC_THREADS */
 }
 
 void silc_mutex_unlock(SilcMutex mutex)
 {
 #ifdef SILC_THREADS
-  assert(mutex->locked == TRUE);
-  mutex->locked = FALSE;
-  LeaveCriticalSection(&mutex->mutex);       
+  if (mutex) {
+    assert(mutex->locked == TRUE);
+    mutex->locked = FALSE;
+    LeaveCriticalSection(&mutex->mutex);
+  }
 #endif /* SILC_THREADS */
 }
index fd7542dd5fc9508aa8c6dcadf7b7fadc13623fd5..0bcd038dcc130de44b798611fa7bd1c3c3fb11ff 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index c3dedee37270ebcd574a59be92023d798fafed3e..383ececa98a37f09f54595899e8d820d7ed2711e 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 55f37e56fa6307f6feab57c5471fb9ed4d3a35e8..abc3523721cb9b294314290dfe9e41b93e88d544 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index ca2a211207c9baf3feec507151d2eb5f4d99a63d..7d5c62d2f7dde3784e1cbd6911c3f78dd0cb2d05 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -61,7 +60,9 @@ SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
   thread->start_func = start_func;
   thread->context = context;
   thread->waitable = waitable;
-  thread->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)silc_thread_win32_start, (void *)thread, 0, &id);
+  thread->thread =
+    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)silc_thread_win32_start,
+                (void *)thread, 0, &id);
 
   if (!thread->thread) {
     SILC_LOG_ERROR(("Could not create new thread"));
@@ -113,7 +114,7 @@ SilcThread silc_thread_self(void)
   }
 
   return (SilcThread)self;
-#else
+       #else
   return NULL;
 #endif
 }
@@ -130,9 +131,7 @@ bool silc_thread_wait(SilcThread thread, void **exit_value)
 
   /* The thread is waitable thus we will free all memory after the
      WaitForSingleObject returns, the thread is destroyed after that. */
-
-  /* 2 sec timeout, otherwise we would run to infinite loop some cases.. */
-  if (WaitForSingleObject(self->thread, 2000) == WAIT_TIMEOUT)
+  if (WaitForSingleObject(self->thread, 2500) == WAIT_TIMEOUT)
     TerminateThread(self->thread, 0);
 
   silc_free(self);
index 0fb3f204755132a8dd01ebccf7e455a3e7af7490..7bc2d69a98981964d1109786057a0bf657252052 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 2001 Pekka Riikonen
+  Copyright (C) 2001 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index c09c9af2859360d42ddb402dac3883e9566d73de..3fe9452afe96a069536cf6866e90cb1bfa0a2c68 100755 (executable)
@@ -3,6 +3,6 @@
 cat << EOF > tmp.php
 <?php \$page="$4"; \$dest="$1"; \$type="$3"; require "$2"; ?>
 EOF
-php -f tmp.php >$5.tmp
-mv $5.tmp $5
+php -f tmp.php >"$5".tmp
+mv "$5".tmp "$5"
 rm -f tmp.php
index 7b3d1298d137efa57415829c5043dc8fc8482e18..f17fbbb92f9e91476ea44284e980a19a4eeb1a22 100644 (file)
@@ -7,8 +7,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 999fcb16a6d0f30dea96a8aaba250eae3fdbfaa0..ae7f4493190a6ef4cbc8bdf9a3fa799abdedb771 100644 (file)
@@ -7,8 +7,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index a263d059c7d808ec5ed275df3e8b454889bf0758..b425a7916a7b5f7bf4d0e130ee61e0e914a8f71c 100644 (file)
@@ -7,8 +7,7 @@
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
index 9f7bffcea37b942ee9d6c6fc55c8051752820af1..8425249ec14c828c0fb9f2fc2e139b764bed43c7 100755 (executable)
@@ -104,7 +104,7 @@ if [ "$TYPE" = "HTML" ]; then
   for i in $dfiles
   do
     # Get library name
-    name=`grep "@LIBRARY=" $i |cut -d=  -f2`
+    name=`grep "@LIBRARY=" $i |cut -d=  -f2-`
     fname=`grep "@FILENAME=" $i |cut -d=  -f2`
     links=`grep "@LINK=" $i |cut -d=  -f2 |cut -d:  -f1`
 
@@ -113,7 +113,7 @@ if [ "$TYPE" = "HTML" ]; then
     echo "<a href="$fname"><img src="box.gif" border="0" alt="">$name</a><br />" >>$DST/index.tmpl
     for k in $links
     do
-      n=`grep $k $i |cut -d=  -f2 |cut -d:  -f2`
+      n=`grep $k $i |cut -d=  -f2 |cut -d:  -f2-`
       echo "<li><a href="$k">$n</a>" >>$DST/$fname.links
       echo "&nbsp;&nbsp;&nbsp; <a href="$k"><img src="box2.gif" border="0" alt="">$n</a><br />" >>$DST/index.tmpl
     done
@@ -170,7 +170,7 @@ if [ "$TYPE" = "HTML" ]; then
     files=`find $DST -name ""$i"-*.html"`
     for k in $files
     do
-      sh gen.sh $DST gen_index.php 0 $k $k
+      sh gen.sh $DST gen_index.php 0 "$k" "$k"
     done
 
     rm -f $DST/$i-index.tmpl
@@ -180,7 +180,7 @@ if [ "$TYPE" = "HTML" ]; then
   for i in $dfiles
   do
     # Get library name
-    name=`grep "@LIBRARY=" $i |cut -d=  -f2`
+    name=`grep "@LIBRARY=" $i |cut -d=  -f2-`
     fname=`grep "@FILENAME=" $i |cut -d=  -f2`
 
     # Generate links for this library
index e47325b028e83a12802335aecd0316736d053e11..611cd6bc595798e5860e5dc0dc5ed20615038f2e 100644 (file)
@@ -98,7 +98,7 @@ EXPORTS
        silc_command_set_command @ 323 ;\r
        silc_command_set_ident @ 324 ;\r
        silc_config_open @ 327 ;\r
-       silc_debug @ 328 DATA ;\r
+       silc_log_debug @ 328;\r
        silc_pem_decode @ 329 ;\r
        silc_default_ciphers @ 330 DATA ;\r
        silc_default_hash @ 331 DATA ;\r
@@ -522,10 +522,10 @@ EXPORTS
        silc_log_reset_all @ 844 ;\r
        silc_log_flush_all @ 845 ;\r
        silc_log_get_file @ 846 ;\r
-       silc_log_quick @ 847 DATA ;\r
-       silc_log_flushdelay @ 848 DATA ;\r
+       silc_log_quick @ 847;\r
+       silc_log_flushdelay @ 848;\r
        silc_hash_table_list_reset @ 849 ;\r
-       silc_debug_hexdump @ 850 DATA ;\r
+       silc_log_debug_hexdump @ 850;\r
        silc_memdup @ 851 ;\r
        silc_command_get_status @ 852 ;\r
        silc_utf8_encode @ 853 ;\r
index fcc2d87f55de8a06fb5e74b4781088216fe12ad0..f5988af3a0df67f4c7197b912a1aed06fa01f1dd 100644 (file)
@@ -251,29 +251,13 @@ SOURCE=..\..\lib\silcutil\win32\silcwin32util.c
 # Begin Group "silcmath"\r
 \r
 # PROP Default_Filter ""\r
-# Begin Group "mpi"\r
-\r
-# PROP Default_Filter ""\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mpi.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mplogic.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mpmontg.c\r
-# End Source File\r
-# End Group\r
 # Begin Source File\r
 \r
 SOURCE=..\..\lib\silcmath\modinv.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mp_mpi.c\r
+SOURCE=..\..\lib\silcmath\mp_tma.c\r
 # End Source File\r
 # Begin Source File\r
 \r
@@ -283,6 +267,10 @@ SOURCE=..\..\lib\silcmath\mpbin.c
 \r
 SOURCE=..\..\lib\silcmath\silcprimegen.c\r
 # End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\silcmath\tma.c\r
+# End Source File\r
 # End Group\r
 # Begin Group "silccrypt"\r
 \r
@@ -558,50 +546,30 @@ SOURCE=..\..\lib\silcutil\silcvcard.h
 # End Group\r
 # Begin Group "silcmath No. 1"\r
 \r
-# PROP Default_Filter ""\r
-# Begin Group "mpi No. 1"\r
-\r
 # PROP Default_Filter ""\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mpi\logtab.h\r
+SOURCE=..\..\lib\silcmath\mp_tma.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mpi\montmulf.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE="..\..\lib\silcmath\mpi\mpi-config.h"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE="..\..\lib\silcmath\mpi\mpi-priv.h"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mpi.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mplogic.h\r
+SOURCE=..\..\lib\silcmath\silcmath.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mpi\mpprime.h\r
+SOURCE=..\..\lib\silcmath\silcmp.h\r
 # End Source File\r
-# End Group\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mp_mpi.h\r
+SOURCE=..\..\lib\silcmath\tma.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\silcmath.h\r
+SOURCE=..\..\lib\silcmath\tma_class.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\silcmp.h\r
+SOURCE=..\..\lib\silcmath\tma_superclass.h\r
 # End Source File\r
 # End Group\r
 # Begin Group "silccrypt No. 1"\r
index 4e28dc8e32779b62d8b57bcabeda5d25f05b1638..b87f99d93386d78f0e6a213b32402c1080fedeac 100644 (file)
@@ -231,29 +231,13 @@ SOURCE=..\..\lib\silcutil\win32\silcwin32util.c
 # Begin Group "silcmath"\r
 \r
 # PROP Default_Filter ""\r
-# Begin Group "mpi"\r
-\r
-# PROP Default_Filter ""\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mpi.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mplogic.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mpmontg.c\r
-# End Source File\r
-# End Group\r
 # Begin Source File\r
 \r
 SOURCE=..\..\lib\silcmath\modinv.c\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mp_mpi.c\r
+SOURCE=..\..\lib\silcmath\mp_tma.c\r
 # End Source File\r
 # Begin Source File\r
 \r
@@ -263,6 +247,10 @@ SOURCE=..\..\lib\silcmath\mpbin.c
 \r
 SOURCE=..\..\lib\silcmath\silcprimegen.c\r
 # End Source File\r
+# Begin Source File\r
+\r
+SOURCE=..\..\lib\silcmath\tma.c\r
+# End Source File\r
 # End Group\r
 # Begin Group "silccrypt"\r
 \r
@@ -514,50 +502,30 @@ SOURCE=..\..\lib\silcutil\silcvcard.h
 # End Group\r
 # Begin Group "silcmath No. 1"\r
 \r
-# PROP Default_Filter ""\r
-# Begin Group "mpi No. 1"\r
-\r
 # PROP Default_Filter ""\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mpi\logtab.h\r
+SOURCE=..\..\lib\silcmath\mp_tma.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mpi\montmulf.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE="..\..\lib\silcmath\mpi\mpi-config.h"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE="..\..\lib\silcmath\mpi\mpi-priv.h"\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mpi.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=..\..\lib\silcmath\mpi\mplogic.h\r
+SOURCE=..\..\lib\silcmath\silcmath.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mpi\mpprime.h\r
+SOURCE=..\..\lib\silcmath\silcmp.h\r
 # End Source File\r
-# End Group\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\mp_mpi.h\r
+SOURCE=..\..\lib\silcmath\tma.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\silcmath.h\r
+SOURCE=..\..\lib\silcmath\tma_class.h\r
 # End Source File\r
 # Begin Source File\r
 \r
-SOURCE=..\..\lib\silcmath\silcmp.h\r
+SOURCE=..\..\lib\silcmath\tma_superclass.h\r
 # End Source File\r
 # End Group\r
 # Begin Group "silccrypt No. 1"\r
index eb0d689113690c9056e7e5c0071c9338ec51100c..8df6a66b58ace4407c7552e4eb1f37bc07566a63 100644 (file)
@@ -67,7 +67,7 @@
 
 /* MP library */
 /* #undef SILC_MP_GMP */
-#define SILC_MP_NSS_MPI 1
+#define SILC_MP_SILCMATH 1
 
 /* Redefs for SOCKS5 library */
 /* macros/curses checks */