gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-exchange] branch stable updated (f4a0ae8 -> 850d84a)


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch stable updated (f4a0ae8 -> 850d84a)
Date: Tue, 06 Jun 2017 11:32:02 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a change to branch stable
in repository exchange.

    from f4a0ae8  preventing Makefile.in generation in non existent directory
     add 83b527e  start to use extended libgnunetpq API (not finished)
     add fdec8e4  fix #5035
     add b217058  add version to keydata returned by libtalerexchange (#5035)
     add 9f7e3bb  More on RSA-KTI
     add c7c7ac6  cleaning up use of doxygen, fixing #5057
     add 1e30d60  fixing misc doxygen issues
     add ad850ce  ignore generated file
     add 59fd83b  fix memory leaks (#5050)
     add 4694810  free auditor data on shutdown (#5050)
     add 2f74a5b  fix remaining leak from #5050
     add 2daa38f  fix more leaks
     add 1d40a01  fix indentation
     add 0805088  add doxygen M4 macro
     add 850d84a  assert non-NULL

No new revisions were added by this update.

Summary of changes:
 .gitignore                                    |   2 +
 doc/doxygen/taler-exchange.doxy => Doxyfile   |  40 +-
 Makefile.am                                   |  15 +-
 configure.ac                                  |  43 +-
 contrib/gnunet.tag                            |  55 +++
 contrib/microhttpd.tag                        |  44 ++
 doc/Makefile.am                               |   2 +-
 doc/doxygen/Makefile.am                       |  18 -
 doc/paper/taler.bib                           |   2 +-
 doc/paper/taler.tex                           |  12 +-
 m4/ax_prog_doxygen.m4                         | 586 ++++++++++++++++++++++++++
 src/bank-lib/fakebank.c                       |   2 +
 src/exchange-lib/exchange_api_handle.c        |  26 +-
 src/exchange-lib/exchange_api_refresh.c       |   2 +-
 src/exchange-lib/exchange_api_reserve.c       |  70 ++-
 src/exchange-lib/test_exchange_api.c          |   3 +
 src/exchange-tools/taler-exchange-keyup.c     |   1 +
 src/exchange/taler-exchange-httpd_keystate.c  |  17 +-
 src/exchange/taler-exchange-httpd_parsing.c   |   4 +-
 src/exchange/taler-exchange-httpd_parsing.h   |   4 +-
 src/exchange/taler-exchange-httpd_responses.c |   4 +-
 src/exchange/taler-exchange-httpd_responses.h |   4 +-
 src/exchangedb/plugin_exchangedb_postgres.c   | 280 ++----------
 src/include/taler_crypto_lib.h                |   4 +-
 src/include/taler_exchange_service.h          |  12 +-
 src/pq/pq_query_helper.c                      |   8 +-
 src/util/crypto.c                             |   6 +-
 27 files changed, 925 insertions(+), 341 deletions(-)
 rename doc/doxygen/taler-exchange.doxy => Doxyfile (92%)
 create mode 100644 contrib/gnunet.tag
 create mode 100644 contrib/microhttpd.tag
 delete mode 100644 doc/doxygen/Makefile.am
 create mode 100644 m4/ax_prog_doxygen.m4

diff --git a/.gitignore b/.gitignore
index 8067993..4b4c412 100644
--- a/.gitignore
+++ b/.gitignore
@@ -83,3 +83,5 @@ doc/manual/manual.pg
 doc/manual/manual.toc
 doc/manual/manual.tp
 doc/manual/manual.vr
+contrib/taler-exchange.tag
+doxygen-doc/
diff --git a/doc/doxygen/taler-exchange.doxy b/Doxyfile
similarity index 92%
rename from doc/doxygen/taler-exchange.doxy
rename to Doxyfile
index 23c2fbe..359c720 100644
--- a/doc/doxygen/taler-exchange.doxy
+++ b/Doxyfile
@@ -5,8 +5,8 @@
 #---------------------------------------------------------------------------
 DOXYFILE_ENCODING      = UTF-8
 PROJECT_NAME           = "GNU Taler: Exchange"
-PROJECT_NUMBER         = 0.0
-OUTPUT_DIRECTORY       = .
+PROJECT_NUMBER         = 0.3
+OUTPUT_DIRECTORY       = doxygen-doc/
 CREATE_SUBDIRS         = YES
 OUTPUT_LANGUAGE        = English
 BRIEF_MEMBER_DESC      = YES
@@ -25,9 +25,8 @@ ABBREVIATE_BRIEF       = "The $name class" \
 ALWAYS_DETAILED_SEC    = NO
 INLINE_INHERITED_MEMB  = NO
 FULL_PATH_NAMES        = YES
-STRIP_FROM_PATH        = ../..
-STRIP_FROM_INC_PATH    = ../../src/include \
-                        src/include
+STRIP_FROM_PATH        = .
+STRIP_FROM_INC_PATH    = src/include
 SHORT_NAMES            = NO
 JAVADOC_AUTOBRIEF      = NO
 QT_AUTOBRIEF           = NO
@@ -79,24 +78,24 @@ FILE_VERSION_FILTER    =
 #---------------------------------------------------------------------------
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
-QUIET                  = NO
+QUIET                  = YES
 WARNINGS               = YES
 WARN_IF_UNDOCUMENTED   = YES
 WARN_IF_DOC_ERROR      = YES
-WARN_NO_PARAMDOC       = NO
+WARN_NO_PARAMDOC       = YES
 WARN_FORMAT            = "$file:$line: $text"
 WARN_LOGFILE           =
 #---------------------------------------------------------------------------
 # configuration options related to the input files
 #---------------------------------------------------------------------------
-INPUT                  = ../..
+INPUT                  = src/
 INPUT_ENCODING         = UTF-8
 FILE_PATTERNS          = *.c \
                          *.h
 RECURSIVE              = YES
 EXCLUDE                =
 EXCLUDE_SYMLINKS       = NO
-EXCLUDE_PATTERNS       = */test_* */.svn/* */perf_* */tls_test_*  */examples/* 
taler_config.h
+EXCLUDE_PATTERNS       = */test_* */.git/* */perf_* */tls_test_*  
taler_config.h
 EXCLUDE_SYMBOLS        = GNUNET_* JSON_*
 EXAMPLE_PATH           =
 EXAMPLE_PATTERNS       = *
@@ -121,11 +120,11 @@ VERBATIM_HEADERS       = NO
 #---------------------------------------------------------------------------
 ALPHABETICAL_INDEX     = YES
 COLS_IN_ALPHA_INDEX    = 5
-IGNORE_PREFIX          =
+IGNORE_PREFIX          = TALER_
 #---------------------------------------------------------------------------
 # configuration options related to the HTML output
 #---------------------------------------------------------------------------
-GENERATE_HTML          = YES
+#GENERATE_HTML          = YES
 HTML_OUTPUT            = html
 HTML_FILE_EXTENSION    = .html
 HTML_HEADER            =
@@ -148,11 +147,11 @@ TREEVIEW_WIDTH         = 250
 #---------------------------------------------------------------------------
 # configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
-GENERATE_LATEX         = NO
+#GENERATE_LATEX         = YES
 LATEX_OUTPUT           = latex
 LATEX_CMD_NAME         = latex
 MAKEINDEX_CMD_NAME     = makeindex
-COMPACT_LATEX          = NO
+COMPACT_LATEX          = YES
 PAPER_TYPE             = a4wide
 EXTRA_PACKAGES         =
 LATEX_HEADER           =
@@ -163,9 +162,9 @@ LATEX_HIDE_INDICES     = NO
 #---------------------------------------------------------------------------
 # configuration options related to the RTF output
 #---------------------------------------------------------------------------
-GENERATE_RTF           = NO
+#GENERATE_RTF           = NO
 RTF_OUTPUT             = rtf
-COMPACT_RTF            = NO
+COMPACT_RTF            = YES
 RTF_HYPERLINKS         = NO
 RTF_STYLESHEET_FILE    =
 RTF_EXTENSIONS_FILE    =
@@ -179,7 +178,7 @@ MAN_LINKS              = NO
 #---------------------------------------------------------------------------
 # configuration options related to the XML output
 #---------------------------------------------------------------------------
-GENERATE_XML           = NO
+#GENERATE_XML           = NO
 XML_OUTPUT             = xml
 XML_PROGRAMLISTING     = YES
 #---------------------------------------------------------------------------
@@ -208,15 +207,16 @@ SKIP_FUNCTION_MACROS   = YES
 #---------------------------------------------------------------------------
 # Configuration::additions related to external references
 #---------------------------------------------------------------------------
-TAGFILES               =
-GENERATE_TAGFILE       =
+TAGFILES               = contrib/gnunet.tag \
+                         contrib/microhttpd.tag
+GENERATE_TAGFILE       = contrib/taler-exchange.tag
 ALLEXTERNALS           = NO
 EXTERNAL_GROUPS        = YES
 PERL_PATH              = /usr/bin/perl
 #---------------------------------------------------------------------------
 # Configuration options related to the dot tool
 #---------------------------------------------------------------------------
-CLASS_DIAGRAMS         = YES
+CLASS_DIAGRAMS         = NO
 MSCGEN_PATH            =
 HIDE_UNDOC_RELATIONS   = YES
 HAVE_DOT               = YES
@@ -234,7 +234,7 @@ DIRECTORY_GRAPH        = YES
 DOT_IMAGE_FORMAT       = png
 DOT_PATH               =
 DOTFILE_DIRS           =
-DOT_GRAPH_MAX_NODES    = 25
+DOT_GRAPH_MAX_NODES    = 100
 MAX_DOT_GRAPH_DEPTH    = 2
 DOT_TRANSPARENT        = YES
 DOT_MULTI_TARGETS      = NO
diff --git a/Makefile.am b/Makefile.am
index 4bbc208..ab0f3ac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,10 +1,21 @@
 # This Makefile.am is in the public domain
 AM_CPPFLAGS = -I$(top_srcdir)/src/include
-SUBDIRS = src doc
+
+if DOC_ONLY
+  SUBDIRS = . doc
+else
+  SUBDIRS = . src doc
+endif
+
address@hidden@
+
 ACLOCAL_AMFLAGS = -I m4
 EXTRA_DIST = \
   AUTHORS \
-  contrib/coverage.sh
+  contrib/coverage.sh \
+  contrib/gnunet.tag \
+  contrib/microhttpd.tag \
+  Doxyfile
 
 app:
        mkdir -p $(PACKAGE)-$(VERSION)-app
diff --git a/configure.ac b/configure.ac
index e258b52..715e94e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,10 +30,30 @@ AC_CONFIG_MACRO_DIR([m4])
 
 LT_INIT
 
+DX_INIT_DOXYGEN([taler-exchange],,,
+DX_PS_FEATURE(OFF),
+DX_PDF_FEATURE(OFF),
+DX_RTF_FEATURE(OFF),
+DX_CHI_FEATURE(OFF),
+DX_XML_FEATURE(OFF))
+
+AC_MSG_CHECKING([whether to compile documentation ONLY])
+AC_ARG_ENABLE([only-doc],
+  [AS_HELP_STRING([--enable-only-doc], [only compile Taler documentation])],
+  [doc_only=${enableval}],
+  [doc_only=no])
+AC_MSG_RESULT($doc_only)
+AM_CONDITIONAL([DOC_ONLY], [test "$doc_only" = "yes"])
+
+if test "$doc_only" != yes
+then
+
 # Checks for programs.
+
 AC_PROG_CC
 AC_PROG_CC_C99
 
+
 CFLAGS="-Wall $CFLAGS"
 
 # Checks for header files.
@@ -42,7 +62,7 @@ AC_CHECK_HEADERS([stdint.h stdlib.h string.h unistd.h])
 
 # should the build process be restricted to the code required
 # for GNU Taler wallets?
-AC_MSG_CHECKING(whether to compile GNU Taler Wallet library ONLY)
+AC_MSG_CHECKING([whether to compile GNU Taler Wallet library ONLY])
 AC_ARG_ENABLE([wallet],
    [AS_HELP_STRING([--enable-wallet], [only compile for Taler wallet])],
    [wallet_only=${enableval}],
@@ -276,6 +296,7 @@ LDFLAGS=$LDFLAGS_SAVE
 LIBS=$LIBS_SAVE
 
 
+# end of wallet/no-wallet specific logic
 fi
 
 TALER_LIB_LDFLAGS="-export-dynamic -no-undefined"
@@ -296,10 +317,10 @@ AM_CONDITIONAL(HAVE_POSTGRESQL, test x$postgres = xtrue)
 LIBGNURL_CHECK_CONFIG(,7.34.0,gnurl=1,gnurl=0)
 if test "$gnurl" = 1
 then
-       AM_CONDITIONAL(HAVE_LIBGNURL, true)
+       AM_CONDITIONAL(HAVE_LIBGNURL, [true])
        AC_DEFINE([HAVE_LIBGNURL],[1],[Have libgnurl])
 else
-       AM_CONDITIONAL(HAVE_LIBGNURL, false)
+       AM_CONDITIONAL(HAVE_LIBGNURL, [false])
 fi
 
 # libcurl-gnutls
@@ -447,9 +468,23 @@ AC_TYPE_UINTMAX_T
 # Checks for library functions.
 AC_CHECK_FUNCS([strdup])
 
+else
+
+# logic if doc_only is set, make sure conditionals are still defined
+AM_CONDITIONAL([HAVE_EXPENSIVE_TESTS], [false])
+AM_CONDITIONAL([WALLET_ONLY], [false])
+AM_CONDITIONAL([HAVE_POSTGRESQL], [false])
+AM_CONDITIONAL([HAVE_LIBCURL], [false])
+AM_CONDITIONAL([HAVE_LIBGNURL], [false])
+AM_CONDITIONAL([HAVE_DEVELOPER], [false])
+AM_CONDITIONAL([USE_COVERAGE], [false])
+
+
+# end of 'doc_only'
+fi
+
 AC_CONFIG_FILES([Makefile
                  doc/Makefile
-                 doc/doxygen/Makefile
                  src/Makefile
                  src/auditor/Makefile
                  src/auditordb/Makefile
diff --git a/contrib/gnunet.tag b/contrib/gnunet.tag
new file mode 100644
index 0000000..1cf4f0d
--- /dev/null
+++ b/contrib/gnunet.tag
@@ -0,0 +1,55 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
+<tagfile>
+  <compound kind="file">
+    <name>gnunet_util_lib.h</name>
+    <path></path>
+    <filename>gnunet_util_lib.h</filename>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_YES</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_OK</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_NO</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_SYSERR</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_TIME_UNIT_FOREVER_ABS</name>
+      <anchorfile>gnunet_util_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+  </compound>
+  <compound kind="file">
+    <name>gnunet_pq_lib.h</name>
+    <path></path>
+    <filename>gnunet_pq_lib.h</filename>
+    <member kind="define">
+      <type>#define</type>
+      <name>GNUNET_PQ_query_param_end</name>
+      <anchorfile>gnunet_pq_lib.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="typedef">
+      <type>int</type>
+      <name>GNUNET_PQ_ResultConverter</name>
+      <anchorfile>gnunet_pq_lib.h</anchorfile>
+      <arglist>)(void *cls, PGresult *result, int row, const char *fname, 
size_t *dst_size, void *dst)</arglist>
+    </member>
+  </compound>
+</tagfile>
diff --git a/contrib/microhttpd.tag b/contrib/microhttpd.tag
new file mode 100644
index 0000000..de7018a
--- /dev/null
+++ b/contrib/microhttpd.tag
@@ -0,0 +1,44 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
+<tagfile>
+  <compound kind="file">
+    <name>microhttpd_lib.h</name>
+    <path></path>
+    <filename>microhttpd.h</filename>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_YES</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_NO</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_OK</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_HTTP_NO_CONTENT</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="define">
+      <type>#define</type>
+      <name>MHD_OPTION_NOTIFY_COMPLETED</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist></arglist>
+    </member>
+    <member kind="typedef">
+      <type>int</type>
+      <name>MHD_AccessHandlerCallback</name>
+      <anchorfile>microhttpd.h</anchorfile>
+      <arglist>)(void *cls, struct MHD_Connection *connection, const char 
*url, const char *method, const char *version, const char *upload_data, size_t 
*upload_data_size, void **con_cls)</arglist>
+    </member>
+  </compound>
+</tagfile>
diff --git a/doc/Makefile.am b/doc/Makefile.am
index c509f4a..f8d04db 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,6 +1,6 @@
 # This Makefile.am is in the public domain
 
-SUBDIRS = . doxygen
+SUBDIRS = .
 
 man_MANS = \
   taler-auditor.1 \
diff --git a/doc/doxygen/Makefile.am b/doc/doxygen/Makefile.am
deleted file mode 100644
index da4dbc1..0000000
--- a/doc/doxygen/Makefile.am
+++ /dev/null
@@ -1,18 +0,0 @@
-# This Makefile.am is in the public domain
-all:
-       @echo -e \
-"Generate documentation:\n" \
-"\tmake full - full documentation with dependency graphs (slow)\n" \
-"\tmake fast - fast mode without dependency graphs"
-
-full: taler-exchange.doxy
-       doxygen $<
-
-fast: taler-exchange.doxy
-       sed 's/\(HAVE_DOT.*=\).*/\1 NO/' $< | doxygen -
-
-clean:
-       rm -rf html
-
-
-EXTRA_DIST = taler-exchange.doxy
diff --git a/doc/paper/taler.bib b/doc/paper/taler.bib
index bafce49..db98865 100644
--- a/doc/paper/taler.bib
+++ b/doc/paper/taler.bib
@@ -368,7 +368,7 @@
 }
 
 
address@hidden,
address@hidden,
   author="Bellare, Mihir and Namprempre, Chanathip and Pointcheval, David and 
Semanko, Michael",
   editor="Syverson, Paul",
   chapter="The Power of RSA Inversion Oracles and the Security of Chaum's 
RSA-Based Blind Signature Scheme",
diff --git a/doc/paper/taler.tex b/doc/paper/taler.tex
index 96db7c6..bfe8987 100644
--- a/doc/paper/taler.tex
+++ b/doc/paper/taler.tex
@@ -509,7 +509,7 @@ financial reserve.  In addition, Taler includes an 
\emph{auditor} who
 assures customers and merchants that the exchange operates correctly.
 
 %\vspace{-0.3cm}
-\subsection{Security considerations}
+\subsection{Security considerations}\label{subsec:security_rough}
 %\vspace{-0.3cm}
 
 As a payment system, Taler naturally needs to make sure that coins are
@@ -559,7 +559,7 @@ limiting the exchange's financial liability.
 On the cryptographic side, a Taler exchange demands that coins use a
 full domain hash (FDH) to make so-called ``one-more forgery'' attacks
 provably hard, assuming the RSA known-target inversion problem is
-hard~\cite[Theorem 12]{RSA-HDF-KTIvCTI}.  For a withdrawn coin,
+hard~\cite[Theorem 12]{RSA-FDH-KTIvCTI}.  For a withdrawn coin,
 violating the customers anonymity cryptographically requires recognizing
 a random blinding factor from a random element of the group of
 integers modulo the denomination key's RSA modulus, which appears
@@ -1466,6 +1466,14 @@ protocol is never used.
 
 \subsection{Exculpability arguments}
 
+In \S\ref{subsec:security_rough},
+we quoted \cite[Theorem 12]{RSA-FDH-KTIvCTI} that RSA-FDH blind
+signatures are secure against ``one-more forgery'' attacks, assuming
+ the RSA known-target inversion problem is hard.
+We note as well that ``one-more forgery'' attacks cover both the
+refresh operation as well as the withdrawal operarion
+ \cite[Definition 12]{RSA-FDH-KTIvCTI,OneMoreInversion}.
+
 \begin{lemma}\label{lemma:double-spending}
 The exchange can detect, prevent, and prove double-spending.
 \end{lemma}
diff --git a/m4/ax_prog_doxygen.m4 b/m4/ax_prog_doxygen.m4
new file mode 100644
index 0000000..a371f7f
--- /dev/null
+++ b/m4/ax_prog_doxygen.m4
@@ -0,0 +1,586 @@
+# ===========================================================================
+#     https://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   DX_INIT_DOXYGEN(PROJECT-NAME, [DOXYFILE-PATH], [OUTPUT-DIR], ...)
+#   DX_DOXYGEN_FEATURE(ON|OFF)
+#   DX_DOT_FEATURE(ON|OFF)
+#   DX_HTML_FEATURE(ON|OFF)
+#   DX_CHM_FEATURE(ON|OFF)
+#   DX_CHI_FEATURE(ON|OFF)
+#   DX_MAN_FEATURE(ON|OFF)
+#   DX_RTF_FEATURE(ON|OFF)
+#   DX_XML_FEATURE(ON|OFF)
+#   DX_PDF_FEATURE(ON|OFF)
+#   DX_PS_FEATURE(ON|OFF)
+#
+# DESCRIPTION
+#
+#   The DX_*_FEATURE macros control the default setting for the given
+#   Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
+#   generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
+#   help (for MS users), 'CHI' for generating a separate .chi file by the
+#   .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
+#   output formats. The environment variable DOXYGEN_PAPER_SIZE may be
+#   specified to override the default 'a4wide' paper size.
+#
+#   By default, HTML, PDF and PS documentation is generated as this seems to
+#   be the most popular and portable combination. MAN pages created by
+#   Doxygen are usually problematic, though by picking an appropriate subset
+#   and doing some massaging they might be better than nothing. CHM and RTF
+#   are specific for MS (note that you can't generate both HTML and CHM at
+#   the same time). The XML is rather useless unless you apply specialized
+#   post-processing to it.
+#
+#   The macros mainly control the default state of the feature. The use can
+#   override the default by specifying --enable or --disable. The macros
+#   ensure that contradictory flags are not given (e.g.,
+#   --enable-doxygen-html and --enable-doxygen-chm,
+#   --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
+#   feature will be automatically disabled (with a warning) if the required
+#   programs are missing.
+#
+#   Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
+#   with the following parameters: a one-word name for the project for use
+#   as a filename base etc., an optional configuration file name (the
+#   default is '$(srcdir)/Doxyfile', the same as Doxygen's default), and an
+#   optional output directory name (the default is 'doxygen-doc'). To run
+#   doxygen multiple times for different configuration files and output
+#   directories provide more parameters: the second, forth, sixth, etc
+#   parameter are configuration file names and the third, fifth, seventh,
+#   etc parameter are output directories. No checking is done to catch
+#   duplicates.
+#
+#   Automake Support
+#
+#   The DX_RULES substitution can be used to add all needed rules to the
+#   Makefile. Note that this is a substitution without being a variable:
+#   only the @DX_RULES@ syntax will work.
+#
+#   The provided targets are:
+#
+#     doxygen-doc: Generate all doxygen documentation.
+#
+#     doxygen-run: Run doxygen, which will generate some of the
+#                  documentation (HTML, CHM, CHI, MAN, RTF, XML)
+#                  but will not do the post processing required
+#                  for the rest of it (PS, PDF).
+#
+#     doxygen-ps:  Generate doxygen PostScript documentation.
+#
+#     doxygen-pdf: Generate doxygen PDF documentation.
+#
+#   Note that by default these are not integrated into the automake targets.
+#   If doxygen is used to generate man pages, you can achieve this
+#   integration by setting man3_MANS to the list of man pages generated and
+#   then adding the dependency:
+#
+#     $(man3_MANS): doxygen-doc
+#
+#   This will cause make to run doxygen and generate all the documentation.
+#
+#   The following variable is intended for use in Makefile.am:
+#
+#     DX_CLEANFILES = everything to clean.
+#
+#   Then add this variable to MOSTLYCLEANFILES.
+#
+# LICENSE
+#
+#   Copyright (c) 2009 Oren Ben-Kiki <address@hidden>
+#   Copyright (c) 2015 Olaf Mandel <address@hidden>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 23
+
+## ----------##
+## Defaults. ##
+## ----------##
+
+DX_ENV=""
+AC_DEFUN([DX_FEATURE_doc],  ON)
+AC_DEFUN([DX_FEATURE_dot],  OFF)
+AC_DEFUN([DX_FEATURE_man],  OFF)
+AC_DEFUN([DX_FEATURE_html], ON)
+AC_DEFUN([DX_FEATURE_chm],  OFF)
+AC_DEFUN([DX_FEATURE_chi],  OFF)
+AC_DEFUN([DX_FEATURE_rtf],  OFF)
+AC_DEFUN([DX_FEATURE_xml],  OFF)
+AC_DEFUN([DX_FEATURE_pdf],  ON)
+AC_DEFUN([DX_FEATURE_ps],   ON)
+
+## --------------- ##
+## Private macros. ##
+## --------------- ##
+
+# DX_ENV_APPEND(VARIABLE, VALUE)
+# ------------------------------
+# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen and add it
+# as a substitution (but not a Makefile variable). The substitution
+# is skipped if the variable name is VERSION.
+AC_DEFUN([DX_ENV_APPEND],
+[AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])dnl
+m4_if([$1], [VERSION], [], [AC_SUBST([$1], [$2])dnl
+AM_SUBST_NOTMAKE([$1])])dnl
+])
+
+# DX_DIRNAME_EXPR
+# ---------------
+# Expand into a shell expression prints the directory part of a path.
+AC_DEFUN([DX_DIRNAME_EXPR],
+         [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
+
+# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
+# -------------------------------------
+# Expands according to the M4 (static) status of the feature.
+AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
+
+# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
+# ----------------------------------
+# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
+AC_DEFUN([DX_REQUIRE_PROG], [
+AC_PATH_TOOL([$1], [$2])
+if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
+    AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
+    AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+fi
+])
+
+# DX_TEST_FEATURE(FEATURE)
+# ------------------------
+# Expand to a shell expression testing whether the feature is active.
+AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
+
+# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
+# -------------------------------------------------
+# Verify that a required features has the right state before trying to turn on
+# the DX_CURRENT_FEATURE.
+AC_DEFUN([DX_CHECK_DEPEND], [
+test "$DX_FLAG_$1" = "$2" \
+|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
+                            requires, contradicts) doxygen-DX_CURRENT_FEATURE])
+])
+
+# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
+# ----------------------------------------------------------
+# Turn off the DX_CURRENT_FEATURE if the required feature is off.
+AC_DEFUN([DX_CLEAR_DEPEND], [
+test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
+])
+
+# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
+#                CHECK_DEPEND, CLEAR_DEPEND,
+#                REQUIRE, DO-IF-ON, DO-IF-OFF)
+# --------------------------------------------
+# Parse the command-line option controlling a feature. CHECK_DEPEND is called
+# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
+# otherwise CLEAR_DEPEND is called to turn off the default state if a required
+# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
+# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
+# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
+AC_DEFUN([DX_ARG_ABLE], [
+    AC_DEFUN([DX_CURRENT_FEATURE], [$1])
+    AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
+    AC_ARG_ENABLE(doxygen-$1,
+                  [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
+                                                      [--enable-doxygen-$1]),
+                                  DX_IF_FEATURE([$1], [don't $2], [$2]))],
+                  [
+case "$enableval" in
+#(
+y|Y|yes|Yes|YES)
+    AC_SUBST([DX_FLAG_$1], 1)
+    $3
+;; #(
+n|N|no|No|NO)
+    AC_SUBST([DX_FLAG_$1], 0)
+;; #(
+*)
+    AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
+;;
+esac
+], [
+AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
+$4
+])
+if DX_TEST_FEATURE([$1]); then
+    $5
+    :
+fi
+if DX_TEST_FEATURE([$1]); then
+    $6
+    :
+else
+    $7
+    :
+fi
+])
+
+## -------------- ##
+## Public macros. ##
+## -------------- ##
+
+# DX_XXX_FEATURE(DEFAULT_STATE)
+# -----------------------------
+AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc],  [$1])])
+AC_DEFUN([DX_DOT_FEATURE],     [AC_DEFUN([DX_FEATURE_dot], [$1])])
+AC_DEFUN([DX_MAN_FEATURE],     [AC_DEFUN([DX_FEATURE_man],  [$1])])
+AC_DEFUN([DX_HTML_FEATURE],    [AC_DEFUN([DX_FEATURE_html], [$1])])
+AC_DEFUN([DX_CHM_FEATURE],     [AC_DEFUN([DX_FEATURE_chm],  [$1])])
+AC_DEFUN([DX_CHI_FEATURE],     [AC_DEFUN([DX_FEATURE_chi],  [$1])])
+AC_DEFUN([DX_RTF_FEATURE],     [AC_DEFUN([DX_FEATURE_rtf],  [$1])])
+AC_DEFUN([DX_XML_FEATURE],     [AC_DEFUN([DX_FEATURE_xml],  [$1])])
+AC_DEFUN([DX_XML_FEATURE],     [AC_DEFUN([DX_FEATURE_xml],  [$1])])
+AC_DEFUN([DX_PDF_FEATURE],     [AC_DEFUN([DX_FEATURE_pdf],  [$1])])
+AC_DEFUN([DX_PS_FEATURE],      [AC_DEFUN([DX_FEATURE_ps],   [$1])])
+
+# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR], ...)
+# --------------------------------------------------------------
+# PROJECT also serves as the base name for the documentation files.
+# The default CONFIG-FILE is "$(srcdir)/Doxyfile" and OUTPUT-DOC-DIR is
+# "doxygen-doc".
+# More arguments are interpreted as interleaved CONFIG-FILE and
+# OUTPUT-DOC-DIR values.
+AC_DEFUN([DX_INIT_DOXYGEN], [
+
+# Files:
+AC_SUBST([DX_PROJECT], [$1])
+AC_SUBST([DX_CONFIG], ['ifelse([$2], [], [$(srcdir)/Doxyfile], [$2])'])
+AC_SUBST([DX_DOCDIR], ['ifelse([$3], [], [doxygen-doc], [$3])'])
+m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 4, m4_count($@), 2,
+      [AC_SUBST([DX_CONFIG]m4_eval(DX_i[/2]),
+                'm4_default_nblank_quoted(m4_argn(DX_i, $@),
+                                          [$(srcdir)/Doxyfile])')])])dnl
+m4_if(m4_eval(3 < m4_count($@)), 1, [m4_for([DX_i], 5, m4_count($@,), 2,
+      [AC_SUBST([DX_DOCDIR]m4_eval([(]DX_i[-1)/2]),
+                'm4_default_nblank_quoted(m4_argn(DX_i, $@),
+                                          [doxygen-doc])')])])dnl
+m4_define([DX_loop], m4_dquote(m4_if(m4_eval(3 < m4_count($@)), 1,
+          [m4_for([DX_i], 4, m4_count($@), 2, [, m4_eval(DX_i[/2])])],
+          [])))dnl
+
+# Environment variables used inside doxygen.cfg:
+DX_ENV_APPEND(SRCDIR, $srcdir)
+DX_ENV_APPEND(PROJECT, $DX_PROJECT)
+DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
+
+# Doxygen itself:
+DX_ARG_ABLE(doc, [generate any doxygen documentation],
+            [],
+            [],
+            [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
+             DX_REQUIRE_PROG([DX_PERL], perl)],
+            [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
+
+# Dot for graphics:
+DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [DX_REQUIRE_PROG([DX_DOT], dot)],
+            [DX_ENV_APPEND(HAVE_DOT, YES)
+             DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
+            [DX_ENV_APPEND(HAVE_DOT, NO)])
+
+# Man pages generation:
+DX_ARG_ABLE(man, [generate doxygen manual pages],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [],
+            [DX_ENV_APPEND(GENERATE_MAN, YES)],
+            [DX_ENV_APPEND(GENERATE_MAN, NO)])
+
+# RTF file generation:
+DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [],
+            [DX_ENV_APPEND(GENERATE_RTF, YES)],
+            [DX_ENV_APPEND(GENERATE_RTF, NO)])
+
+# XML file generation:
+DX_ARG_ABLE(xml, [generate doxygen XML documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [],
+            [DX_ENV_APPEND(GENERATE_XML, YES)],
+            [DX_ENV_APPEND(GENERATE_XML, NO)])
+
+# (Compressed) HTML help generation:
+DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [DX_REQUIRE_PROG([DX_HHC], hhc)],
+            [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
+             DX_ENV_APPEND(GENERATE_HTML, YES)
+             DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
+            [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
+
+# Separate CHI file generation.
+DX_ARG_ABLE(chi, [generate doxygen separate compressed HTML help index file],
+            [DX_CHECK_DEPEND(chm, 1)],
+            [DX_CLEAR_DEPEND(chm, 1)],
+            [],
+            [DX_ENV_APPEND(GENERATE_CHI, YES)],
+            [DX_ENV_APPEND(GENERATE_CHI, NO)])
+
+# Plain HTML pages generation:
+DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
+            [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
+            [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
+            [],
+            [DX_ENV_APPEND(GENERATE_HTML, YES)],
+            [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
+
+# PostScript file generation:
+DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [DX_REQUIRE_PROG([DX_LATEX], latex)
+             DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+             DX_REQUIRE_PROG([DX_DVIPS], dvips)
+             DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# PDF file generation:
+DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
+            [DX_CHECK_DEPEND(doc, 1)],
+            [DX_CLEAR_DEPEND(doc, 1)],
+            [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
+             DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
+             DX_REQUIRE_PROG([DX_EGREP], egrep)])
+
+# LaTeX generation for PS and/or PDF:
+if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
+    DX_ENV_APPEND(GENERATE_LATEX, YES)
+else
+    DX_ENV_APPEND(GENERATE_LATEX, NO)
+fi
+
+# Paper size for PS and/or PDF:
+AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
+           [a4wide (default), a4, letter, legal or executive])
+case "$DOXYGEN_PAPER_SIZE" in
+#(
+"")
+    AC_SUBST(DOXYGEN_PAPER_SIZE, "")
+;; #(
+a4wide|a4|letter|legal|executive)
+    DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
+;; #(
+*)
+    AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
+;;
+esac
+
+# Rules:
+AS_IF([[test $DX_FLAG_html -eq 1]],
+[[DX_SNIPPET_html="## ------------------------------- ##
+## Rules specific for HTML output. ##
+## ------------------------------- ##
+
+DX_CLEAN_HTML = \$(DX_DOCDIR)/html]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+                \$(DX_DOCDIR]DX_i[)/html]])[
+
+"]],
+[[DX_SNIPPET_html=""]])
+AS_IF([[test $DX_FLAG_chi -eq 1]],
+[[DX_SNIPPET_chi="
+DX_CLEAN_CHI = \$(DX_DOCDIR)/\$(PACKAGE).chi]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).chi]])["]],
+[[DX_SNIPPET_chi=""]])
+AS_IF([[test $DX_FLAG_chm -eq 1]],
+[[DX_SNIPPET_chm="## ------------------------------ ##
+## Rules specific for CHM output. ##
+## ------------------------------ ##
+
+DX_CLEAN_CHM = \$(DX_DOCDIR)/chm]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/chm]])[\
+${DX_SNIPPET_chi}
+
+"]],
+[[DX_SNIPPET_chm=""]])
+AS_IF([[test $DX_FLAG_man -eq 1]],
+[[DX_SNIPPET_man="## ------------------------------ ##
+## Rules specific for MAN output. ##
+## ------------------------------ ##
+
+DX_CLEAN_MAN = \$(DX_DOCDIR)/man]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/man]])[
+
+"]],
+[[DX_SNIPPET_man=""]])
+AS_IF([[test $DX_FLAG_rtf -eq 1]],
+[[DX_SNIPPET_rtf="## ------------------------------ ##
+## Rules specific for RTF output. ##
+## ------------------------------ ##
+
+DX_CLEAN_RTF = \$(DX_DOCDIR)/rtf]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/rtf]])[
+
+"]],
+[[DX_SNIPPET_rtf=""]])
+AS_IF([[test $DX_FLAG_xml -eq 1]],
+[[DX_SNIPPET_xml="## ------------------------------ ##
+## Rules specific for XML output. ##
+## ------------------------------ ##
+
+DX_CLEAN_XML = \$(DX_DOCDIR)/xml]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/xml]])[
+
+"]],
+[[DX_SNIPPET_xml=""]])
+AS_IF([[test $DX_FLAG_ps -eq 1]],
+[[DX_SNIPPET_ps="## ----------------------------- ##
+## Rules specific for PS output. ##
+## ----------------------------- ##
+
+DX_CLEAN_PS = \$(DX_DOCDIR)/\$(PACKAGE).ps]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+              \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps]])[
+
+DX_PS_GOAL = doxygen-ps
+
+doxygen-ps: \$(DX_CLEAN_PS)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).ps: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
+       \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
+       rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
+       \$(DX_LATEX) refman.tex; \\
+       \$(DX_MAKEINDEX) refman.idx; \\
+       \$(DX_LATEX) refman.tex; \\
+       countdown=5; \\
+       while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
+                         refman.log > /dev/null 2>&1 \\
+          && test \$\$countdown -gt 0; do \\
+           \$(DX_LATEX) refman.tex; \\
+            countdown=\`expr \$\$countdown - 1\`; \\
+       done; \\
+       \$(DX_DVIPS) -o ../\$(PACKAGE).ps refman.dvi
+
+]])["]],
+[[DX_SNIPPET_ps=""]])
+AS_IF([[test $DX_FLAG_pdf -eq 1]],
+[[DX_SNIPPET_pdf="## ------------------------------ ##
+## Rules specific for PDF output. ##
+## ------------------------------ ##
+
+DX_CLEAN_PDF = \$(DX_DOCDIR)/\$(PACKAGE).pdf]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+               \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf]])[
+
+DX_PDF_GOAL = doxygen-pdf
+
+doxygen-pdf: \$(DX_CLEAN_PDF)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).pdf: \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag
+       \$(DX_V_LATEX)cd \$(DX_DOCDIR]DX_i[)/latex; \\
+       rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \\
+       \$(DX_PDFLATEX) refman.tex; \\
+       \$(DX_MAKEINDEX) refman.idx; \\
+       \$(DX_PDFLATEX) refman.tex; \\
+       countdown=5; \\
+       while \$(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \\
+                         refman.log > /dev/null 2>&1 \\
+          && test \$\$countdown -gt 0; do \\
+           \$(DX_PDFLATEX) refman.tex; \\
+           countdown=\`expr \$\$countdown - 1\`; \\
+       done; \\
+       mv refman.pdf ../\$(PACKAGE).pdf
+
+]])["]],
+[[DX_SNIPPET_pdf=""]])
+AS_IF([[test $DX_FLAG_ps -eq 1 -o $DX_FLAG_pdf -eq 1]],
+[[DX_SNIPPET_latex="## ------------------------------------------------- ##
+## Rules specific for LaTeX (shared for PS and PDF). ##
+## ------------------------------------------------- ##
+
+DX_V_LATEX = \$(_DX_v_LATEX_\$(V))
+_DX_v_LATEX_ = \$(_DX_v_LATEX_\$(AM_DEFAULT_VERBOSITY))
+_DX_v_LATEX_0 = @echo \"  LATEX \" \$][@;
+
+DX_CLEAN_LATEX = \$(DX_DOCDIR)/latex]dnl
+m4_foreach([DX_i], [m4_shift(DX_loop)], [[\\
+                 \$(DX_DOCDIR]DX_i[)/latex]])[
+
+"]],
+[[DX_SNIPPET_latex=""]])
+
+AS_IF([[test $DX_FLAG_doc -eq 1]],
+[[DX_SNIPPET_doc="## --------------------------------- ##
+## Format-independent Doxygen rules. ##
+## --------------------------------- ##
+
+${DX_SNIPPET_html}\
+${DX_SNIPPET_chm}\
+${DX_SNIPPET_man}\
+${DX_SNIPPET_rtf}\
+${DX_SNIPPET_xml}\
+${DX_SNIPPET_ps}\
+${DX_SNIPPET_pdf}\
+${DX_SNIPPET_latex}\
+DX_V_DXGEN = \$(_DX_v_DXGEN_\$(V))
+_DX_v_DXGEN_ = \$(_DX_v_DXGEN_\$(AM_DEFAULT_VERBOSITY))
+_DX_v_DXGEN_0 = @echo \"  DXGEN \" \$<;
+
+.PHONY: doxygen-run doxygen-doc \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+.INTERMEDIATE: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+doxygen-run:]m4_foreach([DX_i], [DX_loop],
+                         [[ \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag]])[
+
+doxygen-doc: doxygen-run \$(DX_PS_GOAL) \$(DX_PDF_GOAL)
+
+]m4_foreach([DX_i], [DX_loop],
+[[\$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag: \$(DX_CONFIG]DX_i[) 
\$(pkginclude_HEADERS)
+       \$(A""M_V_at)rm -rf \$(DX_DOCDIR]DX_i[)
+       \$(DX_V_DXGEN)\$(DX_ENV) DOCDIR=\$(DX_DOCDIR]DX_i[) \$(DX_DOXYGEN) 
\$(DX_CONFIG]DX_i[)
+       \$(A""M_V_at)echo Timestamp >\$][@
+
+]])dnl
+[DX_CLEANFILES = \\]
+m4_foreach([DX_i], [DX_loop],
+[[     \$(DX_DOCDIR]DX_i[)/doxygen_sqlite3.db \\
+       \$(DX_DOCDIR]DX_i[)/\$(PACKAGE).tag \\
+]])dnl
+[      -r \\
+       \$(DX_CLEAN_HTML) \\
+       \$(DX_CLEAN_CHM) \\
+       \$(DX_CLEAN_CHI) \\
+       \$(DX_CLEAN_MAN) \\
+       \$(DX_CLEAN_RTF) \\
+       \$(DX_CLEAN_XML) \\
+       \$(DX_CLEAN_PS) \\
+       \$(DX_CLEAN_PDF) \\
+       \$(DX_CLEAN_LATEX)"]],
+[[DX_SNIPPET_doc=""]])
+AC_SUBST([DX_RULES],
+["${DX_SNIPPET_doc}"])dnl
+AM_SUBST_NOTMAKE([DX_RULES])
+
+#For debugging:
+#echo DX_FLAG_doc=$DX_FLAG_doc
+#echo DX_FLAG_dot=$DX_FLAG_dot
+#echo DX_FLAG_man=$DX_FLAG_man
+#echo DX_FLAG_html=$DX_FLAG_html
+#echo DX_FLAG_chm=$DX_FLAG_chm
+#echo DX_FLAG_chi=$DX_FLAG_chi
+#echo DX_FLAG_rtf=$DX_FLAG_rtf
+#echo DX_FLAG_xml=$DX_FLAG_xml
+#echo DX_FLAG_pdf=$DX_FLAG_pdf
+#echo DX_FLAG_ps=$DX_FLAG_ps
+#echo DX_ENV=$DX_ENV
+])
diff --git a/src/bank-lib/fakebank.c b/src/bank-lib/fakebank.c
index 813d5b2..ceda4d3 100644
--- a/src/bank-lib/fakebank.c
+++ b/src/bank-lib/fakebank.c
@@ -361,6 +361,7 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
                       (json_int_t) t->serial_id);
     json_str = json_dumps (json,
                            JSON_INDENT(2));
+    json_decref (json);
     if (NULL == json_str)
     {
       GNUNET_break (0);
@@ -393,6 +394,7 @@ handle_admin_add_incoming (struct TALER_FAKEBANK_Handle *h,
  *
  * @param h the fakebank handle
  * @param connection the connection
+ * @param con_cls place to store state, not used
  * @return MHD result code
  */
 static int
diff --git a/src/exchange-lib/exchange_api_handle.c 
b/src/exchange-lib/exchange_api_handle.c
index 1caa696..590d4de 100644
--- a/src/exchange-lib/exchange_api_handle.c
+++ b/src/exchange-lib/exchange_api_handle.c
@@ -413,8 +413,7 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
     struct TALER_AuditorSignatureP auditor_sig;
     struct GNUNET_HashCode denom_h;
     const struct TALER_EXCHANGE_DenomPublicKey *dk;
-    unsigned int j;
-    struct GNUNET_JSON_Specification spec[] = {
+    struct GNUNET_JSON_Specification kspec[] = {
       GNUNET_JSON_spec_fixed_auto ("denom_pub_h",
                                    &denom_h),
       GNUNET_JSON_spec_fixed_auto ("auditor_sig",
@@ -424,14 +423,14 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
 
     if (GNUNET_OK !=
         GNUNET_JSON_parse (key,
-                           spec,
+                           kspec,
                            NULL, NULL))
       {
       GNUNET_break_op (0);
       continue;
     }
     dk = NULL;
-    for (j=0;j<key_data->num_denom_keys;j++)
+    for (unsigned int j=0;j<key_data->num_denom_keys;j++)
     {
       if (0 == memcmp (&denom_h,
                        &key_data->denom_keys[j].h_key,
@@ -468,12 +467,14 @@ parse_json_auditor (struct 
TALER_EXCHANGE_AuditorInformation *auditor,
                                     &auditor->auditor_pub.eddsa_pub))
     {
       GNUNET_break_op (0);
+      GNUNET_JSON_parse_free (spec);
       return GNUNET_SYSERR;
     }
     auditor->denom_keys[off] = dk;
     off++;
   }
   auditor->num_denom_keys = off;
+  GNUNET_JSON_parse_free (spec);
   return GNUNET_OK;
 }
 
@@ -503,7 +504,10 @@ decode_keys_json (const json_t *resp_obj,
   hash_context = GNUNET_CRYPTO_hash_context_start ();
   /* parse the master public key and issue date of the response */
   {
+    const char *ver;
     struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_string ("version",
+                               &ver),
       GNUNET_JSON_spec_fixed_auto ("master_public_key",
                                    &key_data->master_pub),
       GNUNET_JSON_spec_fixed_auto ("eddsa_sig",
@@ -519,6 +523,7 @@ decode_keys_json (const json_t *resp_obj,
             GNUNET_JSON_parse (resp_obj,
                                spec,
                                NULL, NULL));
+    key_data->version = GNUNET_strdup (ver);
   }
 
   /* parse the signing keys */
@@ -630,19 +635,26 @@ decode_keys_json (const json_t *resp_obj,
 static void
 free_key_data (struct TALER_EXCHANGE_Keys *key_data)
 {
-  unsigned int i;
-
   GNUNET_array_grow (key_data->sign_keys,
                      key_data->num_sign_keys,
                      0);
-  for (i=0;i<key_data->num_denom_keys;i++)
+  for (unsigned int i=0;i<key_data->num_denom_keys;i++)
     GNUNET_CRYPTO_rsa_public_key_free 
(key_data->denom_keys[i].key.rsa_public_key);
   GNUNET_array_grow (key_data->denom_keys,
                      key_data->num_denom_keys,
                      0);
+  for (unsigned int i=0;i<key_data->num_auditors;i++)
+  {
+    GNUNET_array_grow (key_data->auditors[i].denom_keys,
+                       key_data->auditors[i].num_denom_keys,
+                       0);
+    GNUNET_free (key_data->auditors[i].auditor_url);
+  }
   GNUNET_array_grow (key_data->auditors,
                      key_data->num_auditors,
                      0);
+  GNUNET_free_non_null (key_data->version);
+  key_data->version = NULL;
 }
 
 
diff --git a/src/exchange-lib/exchange_api_refresh.c 
b/src/exchange-lib/exchange_api_refresh.c
index 84fb3b7..79381f3 100644
--- a/src/exchange-lib/exchange_api_refresh.c
+++ b/src/exchange-lib/exchange_api_refresh.c
@@ -690,7 +690,7 @@ deserialize_melt_data (const char *buf,
  *         if the inputs are invalid (i.e. denomination key not with this 
exchange).
  *         Otherwise, pointer to a buffer of @a res_size to store persistently
  *         before proceeding to #TALER_EXCHANGE_refresh_melt().
- *         Non-null results should be freed using #GNUNET_free().
+ *         Non-null results should be freed using GNUNET_free().
  */
 char *
 TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP 
*melt_priv,
diff --git a/src/exchange-lib/exchange_api_reserve.c 
b/src/exchange-lib/exchange_api_reserve.c
index 7649ccc..4b5152c 100644
--- a/src/exchange-lib/exchange_api_reserve.c
+++ b/src/exchange-lib/exchange_api_reserve.c
@@ -409,12 +409,43 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle 
*exchange,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-
   return GNUNET_OK;
 }
 
 
 /**
+ * Free memory (potentially) allocated by #parse_reserve_history().
+ *
+ * @param rhistory result to free
+ * @param len number of entries in @a rhistory
+ */
+static void
+free_rhistory (struct TALER_EXCHANGE_ReserveHistory *rhistory,
+               unsigned int len)
+{
+  for (unsigned int i=0;i<len;i++)
+  {
+    switch (rhistory[i].type)
+    {
+    case TALER_EXCHANGE_RTT_DEPOSIT:
+      GNUNET_free_non_null (rhistory[i].details.in_details.wire_reference);
+      if (NULL != rhistory[i].details.in_details.sender_account_details)
+        json_decref (rhistory[i].details.in_details.sender_account_details);
+      break;
+    case TALER_EXCHANGE_RTT_WITHDRAWAL:
+      break;
+    case TALER_EXCHANGE_RTT_PAYBACK:
+      break;
+    case TALER_EXCHANGE_RTT_CLOSE:
+      if (NULL != rhistory[i].details.close_details.receiver_account_details)
+        json_decref 
(rhistory[i].details.close_details.receiver_account_details);
+      break;
+    }
+  }
+}
+
+
+/**
  * Function called when we're done processing the
  * HTTP /reserve/status request.
  *
@@ -468,6 +499,7 @@ handle_reserve_status_finished (void *cls,
       {
         struct TALER_EXCHANGE_ReserveHistory rhistory[len];
 
+        memset (rhistory, 0, sizeof (rhistory));
         if (GNUNET_OK !=
             parse_reserve_history (rsh->exchange,
                                    history,
@@ -479,25 +511,29 @@ handle_reserve_status_finished (void *cls,
         {
           GNUNET_break_op (0);
           response_code = 0;
-          break;
         }
-        if (0 !=
-            TALER_amount_cmp (&balance_from_history,
-                              &balance))
+        if ( (0 != response_code) &&
+             (0 !=
+              TALER_amount_cmp (&balance_from_history,
+                                &balance)) )
         {
           /* exchange cannot add up balances!? */
           GNUNET_break_op (0);
           response_code = 0;
-          break;
         }
-        rsh->cb (rsh->cb_cls,
-                 response_code,
-                TALER_EC_NONE,
-                 json,
-                 &balance,
-                 len,
-                 rhistory);
-        rsh->cb = NULL;
+        if (0 != response_code)
+        {
+          rsh->cb (rsh->cb_cls,
+                   response_code,
+                   TALER_EC_NONE,
+                   json,
+                   &balance,
+                   len,
+                   rhistory);
+          rsh->cb = NULL;
+        }
+        free_rhistory (rhistory,
+                       len);
       }
     }
     break;
@@ -796,8 +832,12 @@ reserve_withdraw_payment_required (struct 
TALER_EXCHANGE_ReserveWithdrawHandle *
                                rhistory))
     {
       GNUNET_break_op (0);
+      free_rhistory (rhistory,
+                     len);
       return GNUNET_SYSERR;
     }
+    free_rhistory (rhistory,
+                   len);
   }
 
   if (0 !=
@@ -854,7 +894,7 @@ handle_reserve_withdraw_finished (void *cls,
   case MHD_HTTP_OK:
     if (GNUNET_OK !=
         reserve_withdraw_ok (wsh,
-                          json))
+                             json))
     {
       GNUNET_break_op (0);
       response_code = 0;
diff --git a/src/exchange-lib/test_exchange_api.c 
b/src/exchange-lib/test_exchange_api.c
index c6cecc5..53bfbd1 100644
--- a/src/exchange-lib/test_exchange_api.c
+++ b/src/exchange-lib/test_exchange_api.c
@@ -1043,6 +1043,7 @@ reserve_status_cb (void *cls,
       case OC_PAYBACK:
         xrel = find_command (is,
                              rel->details.payback.ref);
+        GNUNET_assert (NULL != xrel);
         if (0 == strcmp (cmd->details.reserve_status.reserve_reference,
                          xrel->details.reserve_withdraw.reserve_reference))
         {
@@ -1917,8 +1918,10 @@ payback_cb (void *cls,
   }
   withdraw = find_command (is,
                            cmd->details.payback.ref);
+  GNUNET_assert (NULL != withdraw);
   reserve = find_command (is,
                           
withdraw->details.reserve_withdraw.reserve_reference);
+  GNUNET_assert (NULL != reserve);
   GNUNET_CRYPTO_eddsa_key_get_public 
(&reserve->details.admin_add_incoming.reserve_priv.eddsa_priv,
                                       &rp.eddsa_pub);
   switch (http_status)
diff --git a/src/exchange-tools/taler-exchange-keyup.c 
b/src/exchange-tools/taler-exchange-keyup.c
index 2f70a0d..facb832 100644
--- a/src/exchange-tools/taler-exchange-keyup.c
+++ b/src/exchange-tools/taler-exchange-keyup.c
@@ -982,6 +982,7 @@ create_wire_fee_for_method (void *cls,
       break;
     }
     GNUNET_free (amounts);
+    GNUNET_free (opt);
 
     /* handle closing fee */
     GNUNET_asprintf (&opt,
diff --git a/src/exchange/taler-exchange-httpd_keystate.c 
b/src/exchange/taler-exchange-httpd_keystate.c
index 0de85ee..3f81b2e 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -29,6 +29,20 @@
 
 
 /**
+ * Taler protocol version in the format CURRENT:REVISION:AGE
+ * as used by GNU libtool.  See
+ * 
https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
+ *
+ * Please be very careful when updating and follow
+ * 
https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html#Updating-version-info
+ * precisely.  Note that this version has NOTHING to do with the
+ * release version, and the format is NOT the same that semantic
+ * versioning uses either.
+ */
+#define TALER_PROTOCOL_VERSION "0:0:0"
+
+
+/**
  * Snapshot of the (coin and signing) keys (including private keys) of
  * the exchange.  There can be multiple instances of this struct, as it is
  * reference counted and only destroyed once the last user is done
@@ -882,7 +896,8 @@ TEH_KS_acquire_ (const char *location)
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "No valid signing key found!\n");
 
-    keys = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
+    keys = json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}",
+                      "version", TALER_PROTOCOL_VERSION,
                       "master_public_key",
                       GNUNET_JSON_from_data_auto (&TEH_master_public_key),
                       "signkeys", key_state->sign_keys_array,
diff --git a/src/exchange/taler-exchange-httpd_parsing.c 
b/src/exchange/taler-exchange-httpd_parsing.c
index e9c38eb..4d7b5ab 100644
--- a/src/exchange/taler-exchange-httpd_parsing.c
+++ b/src/exchange/taler-exchange-httpd_parsing.c
@@ -174,7 +174,7 @@ TEH_PARSE_mhd_request_arg_data (struct MHD_Connection 
*connection,
  * @return
  *    #GNUNET_YES if navigation was successful (caller is responsible
  *                for freeing allocated variable-size data using
- *                #GNUNET_JSON_parse_free() when done)
+ *                GNUNET_JSON_parse_free() when done)
  *    #GNUNET_NO if json is malformed, error response was generated
  *    #GNUNET_SYSERR on internal error
  */
@@ -221,7 +221,7 @@ TEH_PARSE_json_data (struct MHD_Connection *connection,
  * @return
  *    #GNUNET_YES if navigation was successful (caller is responsible
  *                for freeing allocated variable-size data using
- *                #GNUNET_JSON_parse_free() when done)
+ *                GNUNET_JSON_parse_free() when done)
  *    #GNUNET_NO if json is malformed, error response was generated
  *    #GNUNET_SYSERR on internal error
  */
diff --git a/src/exchange/taler-exchange-httpd_parsing.h 
b/src/exchange/taler-exchange-httpd_parsing.h
index bd705d5..9c53817 100644
--- a/src/exchange/taler-exchange-httpd_parsing.h
+++ b/src/exchange/taler-exchange-httpd_parsing.h
@@ -82,7 +82,7 @@ TEH_PARSE_post_cleanup_callback (void *con_cls);
  * @return
  *    #GNUNET_YES if navigation was successful (caller is responsible
  *                for freeing allocated variable-size data using
- *                #GNUNET_JSON_parse_free() when done)
+ *                GNUNET_JSON_parse_free() when done)
  *    #GNUNET_NO if json is malformed, error response was generated
  *    #GNUNET_SYSERR on internal error
  */
@@ -103,7 +103,7 @@ TEH_PARSE_json_data (struct MHD_Connection *connection,
  * @return
  *    #GNUNET_YES if navigation was successful (caller is responsible
  *                for freeing allocated variable-size data using
- *                #GNUNET_JSON_parse_free() when done)
+ *                GNUNET_JSON_parse_free() when done)
  *    #GNUNET_NO if json is malformed, error response was generated
  *    #GNUNET_SYSERR on internal error
  */
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index 0eebda6..01b5606 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -84,7 +84,7 @@ TEH_RESPONSE_can_compress (struct MHD_Connection *connection)
  *
  * @param[in,out] buf pointer to body to compress
  * @param[in,out] buf_size pointer to initial size of @a buf
- * @return #MHD_TES if @a buf was compressed
+ * @return #MHD_YES if @a buf was compressed
  */
 int
 TEH_RESPONSE_body_compress (void **buf,
@@ -769,7 +769,7 @@ compile_reserve_history (const struct 
TALER_EXCHANGEDB_ReserveHistory *rh,
       ret |= 1;
       GNUNET_assert (0 ==
                      json_array_append_new (json_history,
-                                            json_pack ("{s:s, s:O, s:O, s:o}",
+                                            json_pack ("{s:s, s:O, s:o, s:o}",
                                                        "type", "DEPOSIT",
                                                        
"sender_account_details", pos->details.bank->sender_account_details,
                                                        "wire_reference", 
GNUNET_JSON_from_data (pos->details.bank->wire_reference,
diff --git a/src/exchange/taler-exchange-httpd_responses.h 
b/src/exchange/taler-exchange-httpd_responses.h
index ccd1188..6a33b65 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -50,14 +50,14 @@ TEH_RESPONSE_add_global_headers (struct MHD_Response 
*response);
  *
  * @param[in,out] buf pointer to body to compress
  * @param[in,out] buf_size pointer to initial size of @a buf
- * @return #MHD_TES if @a buf was compressed
+ * @return #MHD_YES if @a buf was compressed
  */
 int
 TEH_RESPONSE_body_compress (void **buf,
                            size_t *buf_size);
 
 
-/** 
+/**
  * Is HTTP body deflate compression supported by the client?
  *
  * @param connection connection to check
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index a359f23..e251722 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -186,71 +186,6 @@ struct PostgresClosure
 
 
 /**
- * Function called by libpq whenever it wants to log something.
- * We already log whenever we care, so this function does nothing
- * and merely exists to silence the libpq logging.
- *
- * @param arg the SQL connection that was used
- * @param res information about some libpq event
- */
-static void
-pq_notice_receiver_cb (void *arg,
-                       const PGresult *res)
-{
-  /* do nothing, intentionally */
-}
-
-
-/**
- * Function called by libpq whenever it wants to log something.
- * We log those using the Taler logger.
- *
- * @param arg the SQL connection that was used
- * @param message information about some libpq event
- */
-static void
-pq_notice_processor_cb (void *arg,
-                        const char *message)
-{
-  GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
-                   "pq",
-                   "%s",
-                   message);
-}
-
-
-/**
- * Establish connection to the Postgres database
- * and initialize callbacks for logging.
- *
- * @param pc configuration to use
- * @return NULL on error
- */
-static PGconn *
-connect_to_postgres (struct PostgresClosure *pc)
-{
-  PGconn *conn;
-
-  conn = PQconnectdb (pc->connection_cfg_str);
-  if (CONNECTION_OK !=
-      PQstatus (conn))
-  {
-    TALER_LOG_ERROR ("Database connection to '%s' failed: %s\n",
-                     pc->connection_cfg_str,
-                     PQerrorMessage (conn));
-    return NULL;
-  }
-  PQsetNoticeReceiver (conn,
-                       &pq_notice_receiver_cb,
-                       conn);
-  PQsetNoticeProcessor (conn,
-                        &pq_notice_processor_cb,
-                        conn);
-  return conn;
-}
-
-
-/**
  * Drop all Taler tables.  This should only be used by testcases.
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
@@ -260,56 +195,40 @@ static int
 postgres_drop_tables (void *cls)
 {
   struct PostgresClosure *pc = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS prewire CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS payback CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS aggregation_tracking 
CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS wire_out CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS wire_fee CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS deposits CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS refresh_out CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS refresh_commit_coin 
CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS refresh_transfer_public_key 
CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS refunds CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS refresh_order CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS refresh_sessions CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS known_coins CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS reserves_close CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS reserves_out CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS reserves_in CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS reserves CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS denomination_revocations 
CASCADE;"),
+    GNUNET_PQ_make_execute ("DROP TABLE IF EXISTS denominations CASCADE;"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
   PGconn *conn;
+  int ret;
 
-  conn = connect_to_postgres (pc);
+  conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == conn)
     return GNUNET_SYSERR;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Dropping ALL tables\n");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS prewire CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS payback CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS aggregation_tracking CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS wire_out CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS wire_fee CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS deposits CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS refresh_out CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS refresh_commit_coin CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS refresh_transfer_public_key CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS refunds CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS refresh_order CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS refresh_sessions CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS known_coins CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS reserves_close CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS reserves_out CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS reserves_in CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS reserves CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS denomination_revocations CASCADE;");
-  SQLEXEC_ (conn,
-            "DROP TABLE IF EXISTS denominations CASCADE;");
-  PQfinish (conn);
-  return GNUNET_OK;
- SQLEXEC_fail:
+  ret = GNUNET_PQ_exec_statements (conn,
+                                   es);
   PQfinish (conn);
-  return GNUNET_SYSERR;
+  return ret;
 }
 
 
@@ -325,7 +244,7 @@ postgres_create_tables (void *cls)
   struct PostgresClosure *pc = cls;
   PGconn *conn;
 
-  conn = connect_to_postgres (pc);
+  conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == conn)
     return GNUNET_SYSERR;
 #define SQLEXEC(sql) SQLEXEC_(conn, sql);
@@ -1727,7 +1646,7 @@ postgres_get_session (void *cls)
 
   if (NULL != (session = pthread_getspecific (pc->db_conn_threadlocal)))
     return session;
-  db_conn = connect_to_postgres (pc);
+  db_conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == db_conn)
     return NULL;
   if (GNUNET_OK !=
@@ -1967,145 +1886,6 @@ execute_prepared_non_select (struct 
TALER_EXCHANGEDB_Session *session,
 
 
 /**
- * Function to be called with the results of a SELECT statement
- * that has returned @a num_results results.
- *
- * @param cls closure
- * @param result the postgres result
- * @param num_result the number of results in @a result
- */
-typedef void
-(*PostgresResultHandler)(void *cls,
-                         PGresult *result,
-                         unsigned int num_results);
-
-
-/**
- * Return value to indicate that there were no results but also
- * no hard failure.  Must be different from #GNUNET_OK, #GNUNET_NO
- * and #GNUNET_SYSERR.
- */
-#define NO_RESULTS 2
-
-
-/**
- * Execute a named prepared @a statement that is a SELECT statement
- * which may return multiple results in @a session using the given @a
- * params.  Returns the resulting session state.
- *
- * @param session session to execute the statement in
- * @param statement name of the statement
- * @param params parameters to give to the statement 
(#GNUNET_PQ_query_param_end-terminated)
- * @param rh function to call with the result set, NULL to ignore
- * @param rh_cls closure to pass to @a rh
- * @return #GNUNET_OK on success (@a rh was called, but possibly with 0 
results)
- *         #GNUNET_NO if the transaction had a transient failure
- *         #GNUNET_SYSERR if the transaction had a hard failure
- */
-int
-execute_prepared_multi_select (struct TALER_EXCHANGEDB_Session *session,
-                               const char *statement,
-                               const struct GNUNET_PQ_QueryParam *params,
-                               PostgresResultHandler rh,
-                               void *rh_cls)
-{
-  PGresult *result;
-  int ret;
-
-  if (GNUNET_OK != session->state)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR; /* we already failed, why keep going? */
-  }
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    statement,
-                                    params);
-  ret = update_session_from_result (session,
-                                    statement,
-                                    result);
-  if (GNUNET_OK != ret)
-  {
-    GNUNET_break (GNUNET_NO == ret);
-    PQclear (result);
-    return ret;
-  }
-  if (NULL != rh)
-    rh (rh_cls,
-        result,
-        PQntuples (result));
-  PQclear (result);
-  return ret;
-}
-
-
-/**
- * Execute a named prepared @a statement that is a SELECT statement
- * which must return a single result in @a session using the given @a
- * params.  Stores the result (if any) in @a rs, which the caller
- * must then clean up.  Returns the resulting session state.
- *
- * @param session session to execute the statement in
- * @param statement name of the statement
- * @param params parameters to give to the statement 
(#GNUNET_PQ_query_param_end-terminated)
- * @param[in,out] rs result specification to use for storing the result of the 
query
- * @return #NO_RESULTS if there were zero results but the query succeeded,
- *         #GNUNET_OK on success (exactly one result was successfully stored 
in @a rs)
- *         #GNUNET_NO if the transaction had a transient failure
- *         #GNUNET_SYSERR if the transaction had a hard failure
- */
-int
-execute_prepared_singleton_select (struct TALER_EXCHANGEDB_Session *session,
-                                   const char *statement,
-                                   const struct GNUNET_PQ_QueryParam *params,
-                                   struct GNUNET_PQ_ResultSpec *rs)
-{
-  PGresult *result;
-  int ret;
-
-  if (GNUNET_OK != session->state)
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR; /* we already failed, why keep going? */
-  }
-  result = GNUNET_PQ_exec_prepared (session->conn,
-                                    statement,
-                                    params);
-  ret = update_session_from_result (session,
-                                    statement,
-                                    result);
-  if (GNUNET_OK != ret)
-  {
-    GNUNET_break (GNUNET_NO == ret);
-    PQclear (result);
-    return ret;
-  }
-  if (0 == PQntuples (result))
-  {
-    PQclear (result);
-    return NO_RESULTS;
-  }
-  if (1 != PQntuples (result))
-  {
-    /* more than one result, but there must be at most one */
-    GNUNET_break (0);
-    PQclear (result);
-    return GNUNET_SYSERR;
-  }
-  if (GNUNET_OK !=
-      GNUNET_PQ_extract_result (result,
-                                rs,
-                                0))
-  {
-    session->state = GNUNET_SYSERR;
-    return GNUNET_SYSERR;
-  }
-  PQclear (result);
-  return GNUNET_OK;
-}
-
-
-
-/**
  * Insert a denomination key's public information into the database for
  * reference by auditors and other consistency checks.
  *
@@ -5584,7 +5364,7 @@ postgres_gc (void *cls)
   PGresult *result;
 
   now = GNUNET_TIME_absolute_get ();
-  conn = connect_to_postgres (pc);
+  conn = GNUNET_PQ_connect (pc->connection_cfg_str);
   if (NULL == conn)
     return GNUNET_SYSERR;
   if (GNUNET_OK !=
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index 9c854ab..9e9352f 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -390,7 +390,7 @@ struct TALER_TrackTransferDetails
  * @param coin_public_info the coin public info to check for validity
  * @return #GNUNET_YES if the coin is valid,
  *         #GNUNET_NO if it is invalid
- *         #GNUNET_SYSERROR if an internal error occured
+ *         #GNUNET_SYSERR if an internal error occured
  */
 int
 TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info);
@@ -409,7 +409,7 @@ struct TALER_TransferSecretP
   /**
    * Secret used to derive private inputs for refreshed coins.
    * Must be (currently) a hash as this is what
-   * #GNUNET_CRYPTO_ecc_ecdh() returns to us.
+   * GNUNET_CRYPTO_ecc_ecdh() returns to us.
    */
   struct GNUNET_HashCode key;
 };
diff --git a/src/include/taler_exchange_service.h 
b/src/include/taler_exchange_service.h
index 20f9899..9a004a4 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -154,7 +154,7 @@ struct TALER_EXCHANGE_AuditorInformation
    * should also be an auditor API for automated submission about
    * claims of misbehaving exchange providers.
    */
-  const char *auditor_url;
+  char *auditor_url;
 
   /**
    * Number of denomination keys audited by this auditor.
@@ -198,6 +198,14 @@ struct TALER_EXCHANGE_Keys
   struct TALER_EXCHANGE_AuditorInformation *auditors;
 
   /**
+   * Supported Taler protocol version by the exchange.
+   * String in the format current:revision:age using the
+   * semantics of GNU libtool.  See
+   * 
https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+   */
+  char *version;
+
+  /**
    * Length of the @e sign_keys array.
    */
   unsigned int num_sign_keys;
@@ -962,7 +970,7 @@ TALER_EXCHANGE_reserve_withdraw_cancel (struct 
TALER_EXCHANGE_ReserveWithdrawHan
  *         if the inputs are invalid (i.e. denomination key not with this 
exchange).
  *         Otherwise, pointer to a buffer of @a res_size to store persistently
  *         before proceeding to #TALER_EXCHANGE_refresh_melt().
- *         Non-null results should be freed using #GNUNET_free().
+ *         Non-null results should be freed using GNUNET_free().
  */
 char *
 TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP 
*melt_priv,
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index bbfa0ee..d6418a1 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -36,7 +36,7 @@
  * @param[out] param_lengths SQL length data to set
  * @param[out] param_formats SQL format data to set
  * @param param_length number of entries available in the @a param_values, @a 
param_lengths and @a param_formats arrays
- * @param[out] scratch buffer for dynamic allocations (to be done via 
#GNUNET_malloc()
+ * @param[out] scratch buffer for dynamic allocations (to be done via 
GNUNET_malloc()
  * @param scratch_length number of entries left in @a scratch
  * @return -1 on error, number of offsets used in @a scratch otherwise
  */
@@ -98,7 +98,7 @@ TALER_PQ_query_param_amount_nbo (const struct TALER_AmountNBO 
*x)
  * @param[out] param_lengths SQL length data to set
  * @param[out] param_formats SQL format data to set
  * @param param_length number of entries available in the @a param_values, @a 
param_lengths and @a param_formats arrays
- * @param[out] scratch buffer for dynamic allocations (to be done via 
#GNUNET_malloc()
+ * @param[out] scratch buffer for dynamic allocations (to be done via 
GNUNET_malloc()
  * @param scratch_length number of entries left in @a scratch
  * @return -1 on error, number of offsets used in @a scratch otherwise
  */
@@ -161,7 +161,7 @@ TALER_PQ_query_param_amount (const struct TALER_Amount *x)
  * @param[out] param_lengths SQL length data to set
  * @param[out] param_formats SQL format data to set
  * @param param_length number of entries available in the @a param_values, @a 
param_lengths and @a param_formats arrays
- * @param[out] scratch buffer for dynamic allocations (to be done via 
#GNUNET_malloc()
+ * @param[out] scratch buffer for dynamic allocations (to be done via 
GNUNET_malloc()
  * @param scratch_length number of entries left in @a scratch
  * @return -1 on error, number of offsets used in @a scratch otherwise
  */
@@ -178,7 +178,7 @@ qconv_json (void *cls,
 {
   const json_t *json = data;
   char *str;
-  
+
   str = json_dumps (json, JSON_COMPACT);
   if (NULL == str)
     return -1;
diff --git a/src/util/crypto.c b/src/util/crypto.c
index d20c9a9..ce5bfac 100644
--- a/src/util/crypto.c
+++ b/src/util/crypto.c
@@ -79,7 +79,7 @@ TALER_gcrypt_init ()
  * @param coin_public_info the coin public info to check for validity
  * @return #GNUNET_YES if the coin is valid,
  *         #GNUNET_NO if it is invalid
- *         #GNUNET_SYSERROR if an internal error occured
+ *         #GNUNET_SYSERR if an internal error occured
  */
 int
 TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info)
@@ -205,10 +205,10 @@ TALER_setup_fresh_coin (const struct 
TALER_TransferSecretP *secret_seed,
   p[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0  */
 
   /* FIXME: Run GNUNET_CRYPTO_ecdhe_key_create several times and inspect
-   * the output to verify that the same bits are set and cleared.  
+   * the output to verify that the same bits are set and cleared.
    * Is it worth also adding a test case that runs gcry_pk_testkey on
    * this key after first parsing it into libgcrypt's s-expression mess
-   * ala decode_private_eddsa_key from gnunet/src/util/crypto_ecc.c? 
+   * ala decode_private_eddsa_key from gnunet/src/util/crypto_ecc.c?
    * It'd run check_secret_key but not test_keys from libgcrypt/cipher/ecc.c */
 }
 

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]