gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] 01/02: -update mustach


From: gnunet
Subject: [taler-exchange] 01/02: -update mustach
Date: Mon, 18 Mar 2024 13:30:28 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

commit 9468d2a769c726c9612f383f785501933f330232
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon Mar 18 13:14:51 2024 +0100

    -update mustach
---
 contrib/gana                                     |   2 +-
 contrib/uncrustify_precommit                     |   2 +-
 contrib/wallet-core                              |   2 +-
 src/templating/AUTHORS                           |   4 +
 src/templating/CHANGELOG.md                      | 150 +++++++
 src/templating/README.md                         |  16 +-
 src/templating/dotest.sh                         |  20 +
 src/templating/mustach-cjson.c                   |  35 +-
 src/templating/mustach-cjson.h                   |   2 +-
 src/templating/mustach-jansson.c                 |  36 +-
 src/templating/mustach-json-c.c                  |  37 +-
 src/templating/mustach-original-Makefile         |  20 +-
 src/templating/mustach-tool.c                    |   2 +
 src/templating/mustach-wrap.c                    |  48 ++-
 src/templating/mustach.1.gz                      | Bin 0 -> 742 bytes
 src/templating/mustach.1.scd                     |  60 +++
 src/templating/mustach.c                         |   7 +-
 src/templating/pkgcfgs                           |  35 ++
 src/templating/test-specs/test-specs-cjson.ref   | 425 ++++++++++++++++++
 src/templating/test-specs/test-specs-jansson.ref | 429 +++++++++++++++++++
 src/templating/test-specs/test-specs-json-c.ref  | 425 ++++++++++++++++++
 src/templating/test-specs/test-specs.c           | 520 +++++++++++++++++++++++
 src/templating/test1/Makefile                    |   7 +-
 src/templating/test1/must                        |   6 +
 src/templating/test1/resu.ref                    |  41 ++
 src/templating/test1/vg.ref                      |  14 +
 src/templating/test2/Makefile                    |   7 +-
 src/templating/test2/resu.ref                    |   7 +
 src/templating/test2/vg.ref                      |  14 +
 src/templating/test3/Makefile                    |   7 +-
 src/templating/test3/resu.ref                    |  13 +
 src/templating/test3/vg.ref                      |  14 +
 src/templating/test4/Makefile                    |   7 +-
 src/templating/test4/resu.ref                    |  50 +++
 src/templating/test4/vg.ref                      |  14 +
 src/templating/test5/Makefile                    |   7 +-
 src/templating/test5/resu.ref                    |  38 ++
 src/templating/test5/vg.ref                      |  14 +
 src/templating/test6/Makefile                    |   7 +-
 src/templating/test6/resu.ref                    |  93 ++++
 src/templating/test6/test-custom-write.c         |   2 +
 src/templating/test6/vg.ref                      |  14 +
 src/templating/test7/base.mustache               |   2 +
 src/templating/test7/json                        |   8 +
 src/templating/test7/node.mustache               |   4 +
 src/templating/test7/resu.ref                    |   7 +
 src/templating/test7/vg.ref                      |  14 +
 src/templating/test8/.gitignore                  |   2 +
 src/templating/test8/json                        |   8 +
 src/templating/test8/must                        |   6 +
 src/templating/test8/resu.ref                    |   6 +
 src/templating/test8/vg.ref                      |  14 +
 52 files changed, 2627 insertions(+), 97 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index 2b581279..53d09928 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 2b581279ae67a1068b07a8c010ac1ab7b85e18df
+Subproject commit 53d0992890e1ebb8f8c6bd747533abe157baec66
diff --git a/contrib/uncrustify_precommit b/contrib/uncrustify_precommit
index faffcec9..d0a64ef7 100755
--- a/contrib/uncrustify_precommit
+++ b/contrib/uncrustify_precommit
@@ -4,7 +4,7 @@
 exec 1>&2
 
 RET=0
-changed=$(git diff --cached --name-only | grep -v mustach | grep -v 
templating/test./ | grep -v valgrind.h)
+changed=$(git diff --cached --name-only | grep -v mustach | grep -v 
templating/test | grep -v valgrind.h)
 crustified=""
 
 for f in $changed;
diff --git a/contrib/wallet-core b/contrib/wallet-core
index c0f30699..35212ac5 160000
--- a/contrib/wallet-core
+++ b/contrib/wallet-core
@@ -1 +1 @@
-Subproject commit c0f3069970e24d1fa9e308347350d6e5221aed88
+Subproject commit 35212ac57bfe5625fcf574b0fd2d9baf395dc4c0
diff --git a/src/templating/AUTHORS b/src/templating/AUTHORS
index b440c24e..b2042848 100644
--- a/src/templating/AUTHORS
+++ b/src/templating/AUTHORS
@@ -5,6 +5,7 @@ Contributors:
  Abhishek Mishra
  Atlas
  Ben Beasley
+ Dominik Kummer
  Gabriel Zachmann
  Harold L Marzan
  Kurt Jung
@@ -15,6 +16,7 @@ Contributors:
  Ryan Fox
  Sami Kerola
  Sijmen J. Mulder
+ Steve-Chavez
  Tomasz Sieprawski
 
 Packagers:
@@ -27,6 +29,8 @@ Thanks to issue submitters:
  @fabbe
  Johann Oskarsson
  Mark Bucciarelli
+ Nigel Hathaway
  Paul Wisehart
+ Tarik @tr001
  Thierry Fournier
  SASU OKFT
diff --git a/src/templating/CHANGELOG.md b/src/templating/CHANGELOG.md
new file mode 100644
index 00000000..6024189e
--- /dev/null
+++ b/src/templating/CHANGELOG.md
@@ -0,0 +1,150 @@
+next
+----
+
+Fix:
+ - selection of subitem by index (#47)
+ - get latest iterated key when getting key name (#52)
+ - allow tests without valgrind
+
+1.2.6 (2024-01-08)
+------------------
+
+Fix:
+ - improve naming (#42)
+ - magical spaces in recursive partials (#43)
+ - installation when tool isn't built
+ - correct detection of falsey values (#45)
+
+Minor:
+ - update to newer reference tests
+
+1.2.5 (2023-02-18)
+------------------
+Fix:
+ - Don't override CFLAGS in Makefile
+ - Use of $(INSTALL) in Makefile for setting options
+
+Minor:
+ - Orthograf of 'instantiate'
+
+1.2.4 (2023-01-02)
+------------------
+Fix:
+ - Latent SIGSEGV using cJSON
+
+1.2.3 (2022-12-21)
+------------------
+
+New:
+ - Flag Mustach_With_ErrorUndefined (and option --strict for the tool)
+   for returning a requested tag is not defined
+ - Test of specifications in separate directory
+
+Fix:
+ - Version printing is now okay
+ - Compiling libraries on Darwin (no soname but install_name)
+ - Compiling test6 with correct flags
+ - Update test from specifications
+ - Better use of valgrind reports
+
+1.2.2 (2021-10-28)
+------------------
+
+Fix:
+ - SONAME of libmustach-json-c.so
+
+1.2.1 (2021-10-19)
+------------------
+
+New:
+ - Add SONAME in libraries.
+ - Flag Mustach_With_PartialDataFirst to switch the
+   policy of resolving partials.
+
+Fix:
+ - Identification of types in cJSON
+
+1.2.0 (2021-08-24)
+------------------
+
+New:
+ - Add hook 'mustach_wrap_get_partial' for handling partials.
+ - Add test of mustache specifications https://github.com/mustache/spec.
+
+Changes:
+ - Mustach_With_SingleDot is always set.
+ - Mustach_With_IncPartial is always set.
+ - Mustach_With_AllExtensions is changed to use currently known extensions.
+ - Output of tests changed.
+ - Makefile improved.
+ - Partials are first searched as file then in current selection.
+ - Improved management of delimiters.
+
+Fixes:
+ - Improved output accordingly to https://github.com/mustache/spec:
+   - escaping of quote "
+   - interpolating null with empty string
+   - removal of empty lines with standalone tag
+   - don't enter section if null
+   - indentation of partials
+ - comment improved for get of mustach_wrap_itf.
+
+1.1.1 (2021-08-19)
+------------------
+Fixes:
+ - Avoid conflicting with getopt.
+ - Remove unexpected build artifact.
+ - Handle correctly a size of 0.
+
+1.1.0 (2021-05-01)
+------------------
+New:
+ - API refactored to take lengths to ease working with partial or 
+   non-NULL-terminated strings. (ABI break)
+
+Fixes:
+ - Use correct int type for jansson (json_int_t instead of int64_t).
+ - JSON output of different backends is now the same.
+
+1.0 (2021-04-28, retracted)
+---------------------------
+Legal:
+ - License changed to ISC.
+
+Fixes:
+ - Possible data leak in memfile_open() by clearing buffers.
+ - Fix build on Solaris-likes by including alloca.h.
+ - Fix Windows build by including malloc.h, using size_t instead of
+   ssize_t, and using the standard ternary operator syntax.
+ - Fix JSON in test3 by using double quote characters.
+ - Fix installation in alternative directories such as
+   /opt/pkg/lib on macOS by setting install_name.
+ - Normalise return values in compare() implementations.
+
+New:
+ - Support for cJSON and jansson libraries.
+ - Version info now embedded at build time and shown with mustach(1) 
+   usage.
+ - Versioned so-names (e.g. libxlsx.so.1.0).
+ - BINDIR, LIBDIR and INCLUDEDIR variables in Makefile.
+ - New mustach-wrap.{c,h} to ease implementation new libraries,
+   extracted and refactored from the existing implementations.
+ - Makefile now supports 3 modes: single libmustach (default), split
+   libmustache-core etc, and both.
+ - Any or all backends (json-c, jansson, etc) can be enabled at compile
+   time. By default, all available libraries are used.
+ - mustach(1) can use any JSON backend instead of only json-c.
+ - MUSTACH_COMPATIBLE_0_99 can be defined for backwards source
+   compatibility.
+ - 'No extensions' can now be set Mustach_With_NoExtensions instead of
+   passing 0.
+ - pkgconfig (.pc) file for library.
+ - Manual page for mustach(1).
+
+Changed:
+ - Many renames.
+ - Maximum tag length increased from 1024 to 4096.
+ - Other headers include json-c.h instead of using forward declarations.
+ - mustach(1) reads from /dev/stdin instead of fd 0.
+ - Several structures are now taken as const.
+ - New/changed Makefile targets.
diff --git a/src/templating/README.md b/src/templating/README.md
index 7034ef99..324c9a86 100644
--- a/src/templating/README.md
+++ b/src/templating/README.md
@@ -5,7 +5,7 @@ template specification.
 
 The main site for `mustach` is on [gitlab](https://gitlab.com/jobol/mustach).
 
-The simplest way to use mustach is to copy the files **mustach.h** and 
**mustach.c**
+The simpliest way to use mustach is to copy the files **mustach.h** and 
**mustach.c**
 directly into your project and use it.
 
 If you are using one of the JSON libraries listed below, you can get extended 
feature
@@ -85,7 +85,7 @@ It then outputs the result of applying the templates files to 
the JSON file.
 ### Portability
 
 Some system does not provide *open_memstream*. In that case, tell your
-preferred compiler to declare the preprocessor symbol **NO_OPEN_MEMSTREAM**.
+prefered compiler to declare the preprocessor symbol **NO_OPEN_MEMSTREAM**.
 Example:
 
        CFLAGS=-DNO_OPEN_MEMSTREAM make
@@ -154,6 +154,13 @@ The libraries that can be produced are:
 There is no dependencies of a library to an other. This is intended and doesn't
 hurt today because the code is small.
 
+### Testing
+
+The makefile offers the way to execute basic tests. Just type `make test`.
+
+By default, if valgrind is available, tests are using it. It can be disabled
+by typing `make test valgrind=no` or `NOVALGRIND=1 make test`.
+
 ## Extensions
 
 The current implementation provides extensions to specifications of 
**mustache**.
@@ -163,7 +170,7 @@ Here is the summary.
 
      Flag name                     | Description
     
-------------------------------+------------------------------------------------
-     Mustach_With_Colon            | Explicit tag substitution with colon
+     Mustach_With_Colon            | Explicit tag substition with colon
      Mustach_With_EmptyTag         | Empty Tag Allowed
     
-------------------------------+------------------------------------------------
      Mustach_With_Equal            | Value Testing Equality
@@ -180,7 +187,7 @@ For the details, see below.
 
 ### Explicit Tag Substitution With Colon (Mustach_With_Colon)
 
-In somecases the name of the key used for substitution begins with a
+In somecases the name of the key used for substition begins with a
 character reserved for mustach: one of `#`, `^`, `/`, `&`, `{`, `>` and `=`.
 
 This extension introduces the special character `:` to explicitly
@@ -311,3 +318,4 @@ The table below summarize the changes.
      fdmustach_json_c | mustach_json_c_fd
      mustach_json_c   | mustach_json_c_mem
      mustach_json_c   | mustach_json_c_write
+
diff --git a/src/templating/dotest.sh b/src/templating/dotest.sh
new file mode 100755
index 00000000..99ff8b20
--- /dev/null
+++ b/src/templating/dotest.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+mustach=${mustach:-../mustach}
+echo starting test
+if test "$NOVALGRIND" = 1
+then
+       $mustach "$@" > resu.last
+else
+       valgrind $mustach "$@" > resu.last 2> vg.last
+       sed -i 's:^==[0-9]*== ::' vg.last
+       awk '/^ *total heap usage: .* allocs, .* frees,.*/{if($$4-$$6)exit(1)}' 
vg.last || echo "ERROR! Alloc/Free issue"
+fi
+if diff -w resu.ref resu.last
+then
+       echo "result ok"
+else
+       echo "ERROR! Result differs"
+fi
+echo
+
diff --git a/src/templating/mustach-cjson.c b/src/templating/mustach-cjson.c
index 48b97e7d..ee65c803 100644
--- a/src/templating/mustach-cjson.c
+++ b/src/templating/mustach-cjson.c
@@ -6,7 +6,9 @@
  SPDX-License-Identifier: ISC
 */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include <stdio.h>
 #include <string.h>
@@ -90,11 +92,21 @@ static int sel(void *closure, const char *name)
 static int subsel(void *closure, const char *name)
 {
        struct expl *e = closure;
-       cJSON *o;
-       int r;
+       cJSON *o = NULL;
+       int r = 0;
 
-       o = cJSON_GetObjectItemCaseSensitive(e->selection, name);
-       r = o != NULL;
+       if (cJSON_IsObject(e->selection)) {
+               o = cJSON_GetObjectItemCaseSensitive(e->selection, name);
+               r = o != NULL;
+       }
+       else if (cJSON_IsArray(e->selection) && *name) {
+               char *end;
+               int idx = (int)strtol(name, &end, 10);
+               if (!*end && idx >= 0 && idx < 
cJSON_GetArraySize(e->selection)) {
+                       o = cJSON_GetArrayItem(e->selection, idx);
+                       r = 1;
+               }
+       }
        if (r)
                e->selection = o;
        return r;
@@ -125,7 +137,10 @@ static int enter(void *closure, int objiter)
                e->stack[e->depth].obj = o->child;
                e->stack[e->depth].next = o->child->next;
                e->stack[e->depth].cont = o;
-       } else if ((cJSON_IsObject(o) && o->child == NULL) || (! 
cJSON_IsFalse(o) && ! cJSON_IsNull(o))) {
+       } else if ((cJSON_IsObject(o) && o->child != NULL)
+               || cJSON_IsTrue(o)
+               || (cJSON_IsString(o) && cJSON_GetStringValue(o)[0] != '\0')
+               || (cJSON_IsNumber(o) && cJSON_GetNumberValue(o) != 0)) {
                e->stack[e->depth].obj = o;
                e->stack[e->depth].cont = NULL;
                e->stack[e->depth].next = NULL;
@@ -170,11 +185,15 @@ static int get(void *closure, struct mustach_sbuf *sbuf, 
int key)
 {
        struct expl *e = closure;
        const char *s;
+       int d;
 
        if (key) {
-               s = e->stack[e->depth].is_objiter
-                       ? e->stack[e->depth].obj->string
-                       : "";
+               s = "";
+               for (d = e->depth ; d >= 0 ; d--)
+                       if (e->stack[d].is_objiter) {
+                               s = e->stack[d].obj->string;
+                               break;
+                       }
        }
        else if (cJSON_IsString(e->selection))
                s = e->selection->valuestring;
diff --git a/src/templating/mustach-cjson.h b/src/templating/mustach-cjson.h
index ae0d818c..e049415f 100644
--- a/src/templating/mustach-cjson.h
+++ b/src/templating/mustach-cjson.h
@@ -10,7 +10,7 @@
 #define _mustach_cJSON_h_included_
 
 /*
- * mustach-json-c is intended to make integration of cJSON
+ * mustach-cjson is intended to make integration of cJSON
  * library by providing integrated functions.
  */
 
diff --git a/src/templating/mustach-jansson.c b/src/templating/mustach-jansson.c
index 3ce0e0a8..d9b50b57 100644
--- a/src/templating/mustach-jansson.c
+++ b/src/templating/mustach-jansson.c
@@ -6,7 +6,9 @@
  SPDX-License-Identifier: ISC
 */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include <stdio.h>
 #include <string.h>
@@ -94,11 +96,21 @@ static int sel(void *closure, const char *name)
 static int subsel(void *closure, const char *name)
 {
        struct expl *e = closure;
-       json_t *o;
-       int r;
+       json_t *o = NULL;
+       int r = 0;
 
-       o = json_object_get(e->selection, name);
-       r = o != NULL;
+       if (json_is_object(e->selection)) {
+               o = json_object_get(e->selection, name);
+               r = o != NULL;
+       }
+       else if (json_is_array(e->selection)) {
+               char *end;
+               size_t idx = (size_t)strtol(name, &end, 10);
+               if (!*end && idx < json_array_size(e->selection)) {
+                       o = json_array_get(e->selection, idx);
+                       r = 1;
+               }               
+       }
        if (r)
                e->selection = o;
        return r;
@@ -130,7 +142,11 @@ static int enter(void *closure, int objiter)
                e->stack[e->depth].cont = o;
                e->stack[e->depth].obj = json_array_get(o, 0);
                e->stack[e->depth].index = 0;
-       } else if ((json_is_object(o) && json_object_size(0)) || 
(!json_is_false(o) && !json_is_null(o))) {
+       } else if ((json_is_object(o) && json_object_size(o))
+                || json_is_true(o)
+               || (json_is_string(o) && json_string_length(o) > 0)
+               || (json_is_integer(o) && json_integer_value(o) != 0)
+               || (json_is_real(o) && json_real_value(o) != 0)) {
                e->stack[e->depth].count = 1;
                e->stack[e->depth].cont = NULL;
                e->stack[e->depth].obj = o;
@@ -182,11 +198,15 @@ static int get(void *closure, struct mustach_sbuf *sbuf, 
int key)
 {
        struct expl *e = closure;
        const char *s;
+       int d;
 
        if (key) {
-               s = e->stack[e->depth].is_objiter
-                       ? json_object_iter_key(e->stack[e->depth].iter)
-                       : "";
+               s = "";
+               for (d = e->depth ; d >= 0 ; d--)
+                       if (e->stack[d].is_objiter) {
+                               s = json_object_iter_key(e->stack[d].iter);
+                               break;
+                       }
        }
        else if (json_is_string(e->selection))
                s = json_string_value(e->selection);
diff --git a/src/templating/mustach-json-c.c b/src/templating/mustach-json-c.c
index a21a113f..75251c07 100644
--- a/src/templating/mustach-json-c.c
+++ b/src/templating/mustach-json-c.c
@@ -6,7 +6,9 @@
  SPDX-License-Identifier: ISC
 */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include <stdio.h>
 #include <string.h>
@@ -87,10 +89,19 @@ static int sel(void *closure, const char *name)
 static int subsel(void *closure, const char *name)
 {
        struct expl *e = closure;
-       struct json_object *o;
-       int r;
-
-       r = json_object_object_get_ex(e->selection, name, &o);
+       struct json_object *o = NULL;
+       int r = 0;
+
+       if (json_object_is_type(e->selection, json_type_object))
+               r = json_object_object_get_ex(e->selection, name, &o);
+       else if (json_object_is_type(e->selection, json_type_array)) {
+               char *end;
+               size_t idx = (size_t)strtol(name, &end, 10);
+               if (!*end && idx < json_object_array_length(e->selection)) {
+                       o = json_object_array_get_idx(e->selection, idx);
+                       r = 1;
+               }
+       }
        if (r)
                e->selection = o;
        return r;
@@ -124,7 +135,8 @@ static int enter(void *closure, int objiter)
                e->stack[e->depth].cont = o;
                e->stack[e->depth].obj = json_object_array_get_idx(o, 0);
                e->stack[e->depth].index = 0;
-       } else if (json_object_is_type(o, json_type_object) || 
json_object_get_boolean(o)) {
+       } else if ((json_object_is_type(o, json_type_object) && 
json_object_object_length(o) > 0)
+               || json_object_get_boolean(o)) {
                e->stack[e->depth].count = 1;
                e->stack[e->depth].cont = NULL;
                e->stack[e->depth].obj = o;
@@ -176,11 +188,16 @@ static int get(void *closure, struct mustach_sbuf *sbuf, 
int key)
 {
        struct expl *e = closure;
        const char *s;
-
-       if (key)
-               s = e->stack[e->depth].is_objiter
-                       ? json_object_iter_peek_name(&e->stack[e->depth].iter)
-                       : "";
+       int d;
+
+       if (key) {
+               s = "";
+               for (d = e->depth ; d >= 0 ; d--)
+                       if (e->stack[d].is_objiter) {
+                               s = 
json_object_iter_peek_name(&e->stack[d].iter);
+                               break;
+                       }
+       }
        else
                switch (json_object_get_type(e->selection)) {
                case json_type_string:
diff --git a/src/templating/mustach-original-Makefile 
b/src/templating/mustach-original-Makefile
index e902b2c7..6d90f33d 100644
--- a/src/templating/mustach-original-Makefile
+++ b/src/templating/mustach-original-Makefile
@@ -1,7 +1,7 @@
 # version
 MAJOR := 1
 MINOR := 2
-REVIS := 4
+REVIS := 6
 
 # installation settings
 DESTDIR ?=
@@ -214,7 +214,9 @@ mustach-jansson.o: mustach-jansson.c mustach.h 
mustach-wrap.h mustach-jansson.h
 .PHONY: install
 install: all
        $(INSTALL) -d $(DESTDIR)$(BINDIR)
-       $(INSTALL) -m0755 mustach       $(DESTDIR)$(BINDIR)/
+       if test "${tool}" != "none"; then \
+               $(INSTALL) -m0755 mustach $(DESTDIR)$(BINDIR)/; \
+       fi
        $(INSTALL) -d $(DESTDIR)$(INCLUDEDIR)/mustach
        $(INSTALL) -m0644 $(HEADERS)    $(DESTDIR)$(INCLUDEDIR)/mustach
        $(INSTALL) -d $(DESTDIR)$(LIBDIR)
@@ -236,6 +238,13 @@ uninstall:
        rm -rf $(DESTDIR)$(INCLUDEDIR)/mustach
 
 # testing
+ifeq ($(valgrind),no)
+ NOVALGRIND := 1
+else
+ NOVALGRIND := $(shell which -s valgrind && echo 0 || echo 1)
+endif
+export NOVALGRIND
+
 .PHONY: test test-basic test-specs
 test: basic-tests spec-tests
 
@@ -245,7 +254,9 @@ basic-tests: mustach
        @$(MAKE) -C test3 test
        @$(MAKE) -C test4 test
        @$(MAKE) -C test5 test
-#      @$(MAKE) -C test6 test
+       @$(MAKE) -C test6 test
+       @$(MAKE) -C test7 test
+       @$(MAKE) -C test8 test
 
 spec-tests: $(TESTSPECS)
 
@@ -291,6 +302,8 @@ clean:
        @$(MAKE) -C test4 clean
        @$(MAKE) -C test5 clean
        @$(MAKE) -C test6 clean
+       @$(MAKE) -C test7 clean
+       @$(MAKE) -C test8 clean
 
 # manpage
 .PHONY: manuals
@@ -298,3 +311,4 @@ manuals: mustach.1.gz
 
 mustach.1.gz: mustach.1.scd
        if which scdoc >/dev/null 2>&1; then scdoc < mustach.1.scd | gzip > 
mustach.1.gz; fi
+
diff --git a/src/templating/mustach-tool.c b/src/templating/mustach-tool.c
index 83a0813e..e2a5c1f4 100644
--- a/src/templating/mustach-tool.c
+++ b/src/templating/mustach-tool.c
@@ -6,7 +6,9 @@
  SPDX-License-Identifier: ISC
 */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include <stdlib.h>
 #include <stdio.h>
diff --git a/src/templating/mustach-wrap.c b/src/templating/mustach-wrap.c
index 75cc9d1f..869713c8 100644
--- a/src/templating/mustach-wrap.c
+++ b/src/templating/mustach-wrap.c
@@ -6,7 +6,9 @@
  SPDX-License-Identifier: ISC
 */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -227,20 +229,20 @@ static enum sel sel(struct wrap *w, const char *name)
        return result;
 }
 
-static int start(void *closure)
+static int start_callback(void *closure)
 {
        struct wrap *w = closure;
        return w->itf->start ? w->itf->start(w->closure) : MUSTACH_OK;
 }
 
-static void stop(void *closure, int status)
+static void stop_callback(void *closure, int status)
 {
        struct wrap *w = closure;
        if (w->itf->stop)
                w->itf->stop(w->closure, status);
 }
 
-static int write(struct wrap *w, const char *buffer, size_t size, FILE *file)
+static int emit(struct wrap *w, const char *buffer, size_t size, FILE *file)
 {
        int r;
 
@@ -251,7 +253,7 @@ static int write(struct wrap *w, const char *buffer, size_t 
size, FILE *file)
        return r;
 }
 
-static int emit(void *closure, const char *buffer, size_t size, int escape, 
FILE *file)
+static int emit_callback(void *closure, const char *buffer, size_t size, int 
escape, FILE *file)
 {
        struct wrap *w = closure;
        int r;
@@ -261,7 +263,7 @@ static int emit(void *closure, const char *buffer, size_t 
size, int escape, FILE
        if (w->emitcb)
                r = w->emitcb(file, buffer, size, escape);
        else if (!escape)
-               r = write(w, buffer, size, file);
+               r = emit(w, buffer, size, file);
        else {
                i = 0;
                r = MUSTACH_OK;
@@ -270,13 +272,13 @@ static int emit(void *closure, const char *buffer, size_t 
size, int escape, FILE
                        while (i < size && (car = buffer[i]) != '<' && car != 
'>' && car != '&' && car != '"')
                                i++;
                        if (i != s)
-                               r = write(w, &buffer[s], i - s, file);
+                               r = emit(w, &buffer[s], i - s, file);
                        if (i < size && r == MUSTACH_OK) {
                                switch(car) {
-                               case '<': r = write(w, "&lt;", 4, file); break;
-                               case '>': r = write(w, "&gt;", 4, file); break;
-                               case '&': r = write(w, "&amp;", 5, file); break;
-                               case '"': r = write(w, "&quot;", 6, file); 
break;
+                               case '<': r = emit(w, "&lt;", 4, file); break;
+                               case '>': r = emit(w, "&gt;", 4, file); break;
+                               case '&': r = emit(w, "&amp;", 5, file); break;
+                               case '"': r = emit(w, "&quot;", 6, file); break;
                                }
                                i++;
                        }
@@ -285,20 +287,20 @@ static int emit(void *closure, const char *buffer, size_t 
size, int escape, FILE
        return r;
 }
 
-static int enter(void *closure, const char *name)
+static int enter_callback(void *closure, const char *name)
 {
        struct wrap *w = closure;
        enum sel s = sel(w, name);
        return s == S_none ? 0 : w->itf->enter(w->closure, s & S_objiter);
 }
 
-static int next(void *closure)
+static int next_callback(void *closure)
 {
        struct wrap *w = closure;
        return w->itf->next(w->closure);
 }
 
-static int leave(void *closure)
+static int leave_callback(void *closure)
 {
        struct wrap *w = closure;
        return w->itf->leave(w->closure);
@@ -312,7 +314,7 @@ static int getoptional(struct wrap *w, const char *name, 
struct mustach_sbuf *sb
        return w->itf->get(w->closure, sbuf, s & S_objiter);
 }
 
-static int get(void *closure, const char *name, struct mustach_sbuf *sbuf)
+static int get_callback(void *closure, const char *name, struct mustach_sbuf 
*sbuf)
 {
        struct wrap *w = closure;
        if (getoptional(w, name, sbuf) <= 0) {
@@ -374,7 +376,7 @@ static int get_partial_from_file(const char *name, struct 
mustach_sbuf *sbuf)
        return MUSTACH_ERROR_SYSTEM;
 }
 
-static int partial(void *closure, const char *name, struct mustach_sbuf *sbuf)
+static int partial_callback(void *closure, const char *name, struct 
mustach_sbuf *sbuf)
 {
        struct wrap *w = closure;
        int rc;
@@ -397,15 +399,15 @@ static int partial(void *closure, const char *name, 
struct mustach_sbuf *sbuf)
 }
 
 const struct mustach_itf mustach_wrap_itf = {
-       .start = start,
+       .start = start_callback,
        .put = NULL,
-       .enter = enter,
-       .next = next,
-       .leave = leave,
-       .partial = partial,
-       .get = get,
-       .emit = emit,
-       .stop = stop
+       .enter = enter_callback,
+       .next = next_callback,
+       .leave = leave_callback,
+       .partial = partial_callback,
+       .get = get_callback,
+       .emit = emit_callback,
+       .stop = stop_callback
 };
 
 static void wrap_init(struct wrap *wrap, const struct mustach_wrap_itf *itf, 
void *closure, int flags, mustach_emit_cb_t *emitcb, mustach_write_cb_t 
*writecb)
diff --git a/src/templating/mustach.1.gz b/src/templating/mustach.1.gz
new file mode 100644
index 00000000..15b8a905
Binary files /dev/null and b/src/templating/mustach.1.gz differ
diff --git a/src/templating/mustach.1.scd b/src/templating/mustach.1.scd
new file mode 100644
index 00000000..af4f08ef
--- /dev/null
+++ b/src/templating/mustach.1.scd
@@ -0,0 +1,60 @@
+mustach(1)
+
+# NAME
+
+mustach - Mustache templating command line engine
+
+# SYNOPSIS
+
+*mustach* [-s|--strict] JSON TEMPLATE...
+
+# DESCRIPTION
+
+Instanciate the TEMPLATE files accordingly to the JSON file.
+
+If one of the given files is *-*, the standard input is used.
+
+Option *--strict* make mustach fail if a tag is not found.
+
+# EXAMPLE
+
+A typical Mustache template file: *temp.must*
+
+```
+Hello {{name}}
+You have just won {{value}} dollars!
+{{#in_ca}}
+Well, {{taxed_value}} dollars, after taxes.
+{{/in_ca}}
+```
+
+Given a JSON file: *inst.json*
+
+```
+{
+  "name": "Chris",
+  "value": 10000,
+  "taxed_value": 6000,
+  "in_ca": true
+}
+```
+
+Calling the command *mustach inst.json temp.must*
+will produce the following output:
+
+```
+Hello Chris
+You have just won 10000 dollars!
+Well, 6000.0 dollars, after taxes.
+```
+
+# LINK
+
+Site of *mustach*, the *C* implementation: https://gitlab.com/jobol/mustach
+
+*Mustache format*: http://mustache.github.io/mustache.5.html
+
+Main site for *Mustache*: http://mustache.github.io/
+
+JSON: https://www.json.org/
+
diff --git a/src/templating/mustach.c b/src/templating/mustach.c
index 548c3822..9f992c73 100644
--- a/src/templating/mustach.c
+++ b/src/templating/mustach.c
@@ -6,7 +6,9 @@
  SPDX-License-Identifier: ISC
 */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -272,6 +274,7 @@ static int process(const char *template, size_t length, 
struct iwrap *iwrap, FIL
                                template += l;
                                stdalone = 1;
                                pref.len = 0;
+                               pref.prefix = prefix;
                        }
                        else if (!isspace(c)) {
                                if (stdalone == 2 && enabled) {
@@ -280,6 +283,7 @@ static int process(const char *template, size_t length, 
struct iwrap *iwrap, FIL
                                                return rc;
                                        pref.len = 0;
                                        stdalone = 0;
+                                       pref.prefix = NULL;
                                }
                                if (c == *opstr && end - beg >= (ssize_t)oplen) 
{
                                        for (l = 1 ; l < oplen && beg[l] == 
opstr[l] ; l++);
@@ -360,6 +364,7 @@ get_name:
                        if (rc < 0)
                                return rc;
                        pref.len = 0;
+                       pref.prefix = NULL;
                }
                switch(c) {
                case '!':
@@ -485,7 +490,7 @@ int mustach_file(const char *template, size_t length, const 
struct mustach_itf *
        /* process */
        rc = itf->start ? itf->start(closure) : 0;
        if (rc == 0)
-               rc = process(template, length, &iwrap, file, 0);
+               rc = process(template, length, &iwrap, file, NULL);
        if (itf->stop)
                itf->stop(closure, rc);
        return rc;
diff --git a/src/templating/pkgcfgs b/src/templating/pkgcfgs
new file mode 100644
index 00000000..c3e84dc0
--- /dev/null
+++ b/src/templating/pkgcfgs
@@ -0,0 +1,35 @@
+==libmustach.pc==
+Name: libmustach
+Version: VERSION
+Description: C Mustach single library
+Cflags: -Imustach
+Libs: -lmustach
+
+==libmustach-core.pc==
+Name: libmustach-core
+Version: VERSION
+Description: C Mustach core library
+Cflags: -Imustach
+Libs: -lmustach-core
+
+==libmustach-cjson.pc==
+Name: libmustach-cjson
+Version: VERSION
+Description: C Mustach library for cJSON
+Cflags: -Imustach
+Libs: -lmustach-cjson
+
+==libmustach-json-c.pc==
+Name: libmustach-json-c
+Version: VERSION
+Description: C Mustach library for json-c
+Cflags: -Imustach
+Libs: -lmustach-json-c
+
+==libmustach-jansson.pc==
+Name: libmustach-jansson
+Version: VERSION
+Description: C Mustach library for jansson
+Cflags: -Imustach
+Libs: -lmustach-jansson
+
diff --git a/src/templating/test-specs/test-specs-cjson.ref 
b/src/templating/test-specs/test-specs-cjson.ref
new file mode 100644
index 00000000..8897c66c
--- /dev/null
+++ b/src/templating/test-specs/test-specs-cjson.ref
@@ -0,0 +1,425 @@
+
+loading test-specs/spec/specs/comments.json
+processing file test-specs/spec/specs/comments.json
+[0] Inline
+       Comment blocks should be removed from the template.
+       => SUCCESS
+[1] Multiline
+       Multiline comments should be permitted.
+       => SUCCESS
+[2] Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[3] Indented Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[4] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[5] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[6] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[7] Multiline Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[8] Indented Multiline Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[9] Indented Inline
+       Inline comments should not strip whitespace
+       => SUCCESS
+[10] Surrounding Whitespace
+       Comment removal should preserve surrounding whitespace.
+       => SUCCESS
+[11] Variable Name Collision
+       Comments must never render, even if variable with same name exists.
+       => SUCCESS
+
+loading test-specs/spec/specs/delimiters.json
+processing file test-specs/spec/specs/delimiters.json
+[0] Pair Behavior
+       The equals sign (used on both sides) should permit delimiter changes.
+       => SUCCESS
+[1] Special Characters
+       Characters with special meaning regexen should be valid delimiters.
+       => SUCCESS
+[2] Sections
+       Delimiters set outside sections should persist.
+       => SUCCESS
+[3] Inverted Sections
+       Delimiters set outside inverted sections should persist.
+       => SUCCESS
+[4] Partial Inheritence
+       Delimiters set in a parent template should not affect a partial.
+       => SUCCESS
+[5] Post-Partial Behavior
+       Delimiters set in a partial should not affect the parent template.
+       => SUCCESS
+[6] Surrounding Whitespace
+       Surrounding whitespace should be left untouched.
+       => SUCCESS
+[7] Outlying Whitespace (Inline)
+       Whitespace should be left untouched.
+       => SUCCESS
+[8] Standalone Tag
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[9] Indented Standalone Tag
+       Indented standalone lines should be removed from the template.
+       => SUCCESS
+[10] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[11] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[12] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[13] Pair with Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/interpolation.json
+processing file test-specs/spec/specs/interpolation.json
+[0] No Interpolation
+       Mustache-free templates should render as-is.
+       => SUCCESS
+[1] Basic Interpolation
+       Unadorned tags should interpolate content into the template.
+       => SUCCESS
+[2] HTML Escaping
+       Basic interpolation should be HTML escaped.
+       => SUCCESS
+[3] Triple Mustache
+       Triple mustaches should interpolate without HTML escaping.
+       => SUCCESS
+[4] Ampersand
+       Ampersand should interpolate without HTML escaping.
+       => SUCCESS
+[5] Basic Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[6] Triple Mustache Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[7] Ampersand Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[8] Basic Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[9] Triple Mustache Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[10] Ampersand Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[11] Basic Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[12] Triple Mustache Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[13] Ampersand Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[14] Basic Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[15] Triple Mustache Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[16] Ampersand Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[17] Dotted Names - Basic Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[18] Dotted Names - Triple Mustache Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[19] Dotted Names - Ampersand Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[20] Dotted Names - Arbitrary Depth
+       Dotted names should be functional to any level of nesting.
+       => SUCCESS
+[21] Dotted Names - Broken Chains
+       Any falsey value prior to the last part of the name should yield ''.
+       => SUCCESS
+[22] Dotted Names - Broken Chain Resolution
+       Each part of a dotted name should resolve only against its parent.
+       => SUCCESS
+[23] Dotted Names - Initial Resolution
+       The first part of a dotted name should resolve as any other name.
+       => SUCCESS
+[24] Dotted Names - Context Precedence
+       Dotted names should be resolved against former resolutions.
+       => SUCCESS
+[25] Implicit Iterators - Basic Interpolation
+       Unadorned tags should interpolate content into the template.
+       => SUCCESS
+[26] Implicit Iterators - HTML Escaping
+       Basic interpolation should be HTML escaped.
+       => SUCCESS
+[27] Implicit Iterators - Triple Mustache
+       Triple mustaches should interpolate without HTML escaping.
+       => SUCCESS
+[28] Implicit Iterators - Ampersand
+       Ampersand should interpolate without HTML escaping.
+       => SUCCESS
+[29] Implicit Iterators - Basic Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[30] Interpolation - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[31] Triple Mustache - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[32] Ampersand - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[33] Interpolation - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[34] Triple Mustache - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[35] Ampersand - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[36] Interpolation With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+[37] Triple Mustache With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+[38] Ampersand With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/inverted.json
+processing file test-specs/spec/specs/inverted.json
+[0] Falsey
+       Falsey sections should have their contents rendered.
+       => SUCCESS
+[1] Truthy
+       Truthy sections should have their contents omitted.
+       => SUCCESS
+[2] Null is falsey
+       Null is falsey.
+       => SUCCESS
+[3] Context
+       Objects and hashes should behave like truthy values.
+       => SUCCESS
+[4] List
+       Lists should behave like truthy values.
+       => SUCCESS
+[5] Empty List
+       Empty lists should behave like falsey values.
+       => SUCCESS
+[6] Doubled
+       Multiple inverted sections per template should be permitted.
+       => SUCCESS
+[7] Nested (Falsey)
+       Nested falsey sections should have their contents rendered.
+       => SUCCESS
+[8] Nested (Truthy)
+       Nested truthy sections should be omitted.
+       => SUCCESS
+[9] Context Misses
+       Failed context lookups should be considered falsey.
+       => SUCCESS
+[10] Dotted Names - Truthy
+       Dotted names should be valid for Inverted Section tags.
+       => SUCCESS
+[11] Dotted Names - Falsey
+       Dotted names should be valid for Inverted Section tags.
+       => SUCCESS
+[12] Dotted Names - Broken Chains
+       Dotted names that cannot be resolved should be considered falsey.
+       => SUCCESS
+[13] Surrounding Whitespace
+       Inverted sections should not alter surrounding whitespace.
+       => SUCCESS
+[14] Internal Whitespace
+       Inverted should not alter internal whitespace.
+       => SUCCESS
+[15] Indented Inline Sections
+       Single-line sections should not alter surrounding whitespace.
+       => SUCCESS
+[16] Standalone Lines
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[17] Standalone Indented Lines
+       Standalone indented lines should be removed from the template.
+       => SUCCESS
+[18] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[19] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[20] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[21] Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/partials.json
+processing file test-specs/spec/specs/partials.json
+[0] Basic Behavior
+       The greater-than operator should expand to the named partial.
+       => SUCCESS
+[1] Failed Lookup
+       The empty string should be used when the named partial is not found.
+       => SUCCESS
+[2] Context
+       The greater-than operator should operate within the current context.
+       => SUCCESS
+[3] Recursion
+       The greater-than operator should properly recurse.
+       => SUCCESS
+[4] Nested
+       The greater-than operator should work from within partials.
+       => SUCCESS
+[5] Surrounding Whitespace
+       The greater-than operator should not alter surrounding whitespace.
+       => SUCCESS
+[6] Inline Indentation
+       Whitespace should be left untouched.
+       => SUCCESS
+[7] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[8] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[9] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[10] Standalone Indentation
+       Each line of the partial should be indented before rendering.
+       => SUCCESS
+[11] Padding Whitespace
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/sections.json
+processing file test-specs/spec/specs/sections.json
+[0] Truthy
+       Truthy sections should have their contents rendered.
+       => SUCCESS
+[1] Falsey
+       Falsey sections should have their contents omitted.
+       => SUCCESS
+[2] Null is falsey
+       Null is falsey.
+       => SUCCESS
+[3] Context
+       Objects and hashes should be pushed onto the context stack.
+       => SUCCESS
+[4] Parent contexts
+       Names missing in the current context are looked up in the stack.
+       => SUCCESS
+[5] Variable test
+       Non-false sections have their value at the top of context,
+accessible as {{.}} or through the parent context. This gives
+a simple way to display content conditionally if a variable exists.
+
+       => SUCCESS
+[6] List Contexts
+       All elements on the context stack should be accessible within lists.
+       => SUCCESS
+[7] Deeply Nested Contexts
+       All elements on the context stack should be accessible.
+       => SUCCESS
+[8] List
+       Lists should be iterated; list items should visit the context stack.
+       => SUCCESS
+[9] Empty List
+       Empty lists should behave like falsey values.
+       => SUCCESS
+[10] Doubled
+       Multiple sections per template should be permitted.
+       => SUCCESS
+[11] Nested (Truthy)
+       Nested truthy sections should have their contents rendered.
+       => SUCCESS
+[12] Nested (Falsey)
+       Nested falsey sections should be omitted.
+       => SUCCESS
+[13] Context Misses
+       Failed context lookups should be considered falsey.
+       => SUCCESS
+[14] Implicit Iterator - String
+       Implicit iterators should directly interpolate strings.
+       => SUCCESS
+[15] Implicit Iterator - Integer
+       Implicit iterators should cast integers to strings and interpolate.
+       => SUCCESS
+[16] Implicit Iterator - Decimal
+       Implicit iterators should cast decimals to strings and interpolate.
+       => SUCCESS
+[17] Implicit Iterator - Array
+       Implicit iterators should allow iterating over nested arrays.
+       => SUCCESS
+[18] Implicit Iterator - HTML Escaping
+       Implicit iterators with basic interpolation should be HTML escaped.
+       => SUCCESS
+[19] Implicit Iterator - Triple mustache
+       Implicit iterators in triple mustache should interpolate without HTML 
escaping.
+       => SUCCESS
+[20] Implicit Iterator - Ampersand
+       Implicit iterators in an Ampersand tag should interpolate without HTML 
escaping.
+       => SUCCESS
+[21] Implicit Iterator - Root-level
+       Implicit iterators should work on root-level lists.
+       => SUCCESS
+[22] Dotted Names - Truthy
+       Dotted names should be valid for Section tags.
+       => SUCCESS
+[23] Dotted Names - Falsey
+       Dotted names should be valid for Section tags.
+       => SUCCESS
+[24] Dotted Names - Broken Chains
+       Dotted names that cannot be resolved should be considered falsey.
+       => SUCCESS
+[25] Surrounding Whitespace
+       Sections should not alter surrounding whitespace.
+       => SUCCESS
+[26] Internal Whitespace
+       Sections should not alter internal whitespace.
+       => SUCCESS
+[27] Indented Inline Sections
+       Single-line sections should not alter surrounding whitespace.
+       => SUCCESS
+[28] Standalone Lines
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[29] Indented Standalone Lines
+       Indented standalone lines should be removed from the template.
+       => SUCCESS
+[30] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[31] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[32] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[33] Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+summary:
+  error   0
+  differ  0
+  success 133
diff --git a/src/templating/test-specs/test-specs-jansson.ref 
b/src/templating/test-specs/test-specs-jansson.ref
new file mode 100644
index 00000000..a1cef19c
--- /dev/null
+++ b/src/templating/test-specs/test-specs-jansson.ref
@@ -0,0 +1,429 @@
+
+loading test-specs/spec/specs/comments.json
+processing file test-specs/spec/specs/comments.json
+[0] Inline
+       Comment blocks should be removed from the template.
+       => SUCCESS
+[1] Multiline
+       Multiline comments should be permitted.
+       => SUCCESS
+[2] Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[3] Indented Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[4] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[5] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[6] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[7] Multiline Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[8] Indented Multiline Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[9] Indented Inline
+       Inline comments should not strip whitespace
+       => SUCCESS
+[10] Surrounding Whitespace
+       Comment removal should preserve surrounding whitespace.
+       => SUCCESS
+[11] Variable Name Collision
+       Comments must never render, even if variable with same name exists.
+       => SUCCESS
+
+loading test-specs/spec/specs/delimiters.json
+processing file test-specs/spec/specs/delimiters.json
+[0] Pair Behavior
+       The equals sign (used on both sides) should permit delimiter changes.
+       => SUCCESS
+[1] Special Characters
+       Characters with special meaning regexen should be valid delimiters.
+       => SUCCESS
+[2] Sections
+       Delimiters set outside sections should persist.
+       => SUCCESS
+[3] Inverted Sections
+       Delimiters set outside inverted sections should persist.
+       => SUCCESS
+[4] Partial Inheritence
+       Delimiters set in a parent template should not affect a partial.
+       => SUCCESS
+[5] Post-Partial Behavior
+       Delimiters set in a partial should not affect the parent template.
+       => SUCCESS
+[6] Surrounding Whitespace
+       Surrounding whitespace should be left untouched.
+       => SUCCESS
+[7] Outlying Whitespace (Inline)
+       Whitespace should be left untouched.
+       => SUCCESS
+[8] Standalone Tag
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[9] Indented Standalone Tag
+       Indented standalone lines should be removed from the template.
+       => SUCCESS
+[10] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[11] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[12] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[13] Pair with Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/interpolation.json
+processing file test-specs/spec/specs/interpolation.json
+[0] No Interpolation
+       Mustache-free templates should render as-is.
+       => SUCCESS
+[1] Basic Interpolation
+       Unadorned tags should interpolate content into the template.
+       => SUCCESS
+[2] HTML Escaping
+       Basic interpolation should be HTML escaped.
+       => SUCCESS
+[3] Triple Mustache
+       Triple mustaches should interpolate without HTML escaping.
+       => SUCCESS
+[4] Ampersand
+       Ampersand should interpolate without HTML escaping.
+       => SUCCESS
+[5] Basic Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[6] Triple Mustache Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[7] Ampersand Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[8] Basic Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[9] Triple Mustache Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[10] Ampersand Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[11] Basic Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[12] Triple Mustache Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[13] Ampersand Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[14] Basic Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[15] Triple Mustache Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[16] Ampersand Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[17] Dotted Names - Basic Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[18] Dotted Names - Triple Mustache Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[19] Dotted Names - Ampersand Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[20] Dotted Names - Arbitrary Depth
+       Dotted names should be functional to any level of nesting.
+       => SUCCESS
+[21] Dotted Names - Broken Chains
+       Any falsey value prior to the last part of the name should yield ''.
+       => SUCCESS
+[22] Dotted Names - Broken Chain Resolution
+       Each part of a dotted name should resolve only against its parent.
+       => SUCCESS
+[23] Dotted Names - Initial Resolution
+       The first part of a dotted name should resolve as any other name.
+       => SUCCESS
+[24] Dotted Names - Context Precedence
+       Dotted names should be resolved against former resolutions.
+       => SUCCESS
+[25] Implicit Iterators - Basic Interpolation
+       Unadorned tags should interpolate content into the template.
+       => SUCCESS
+[26] Implicit Iterators - HTML Escaping
+       Basic interpolation should be HTML escaped.
+       => SUCCESS
+[27] Implicit Iterators - Triple Mustache
+       Triple mustaches should interpolate without HTML escaping.
+       => SUCCESS
+[28] Implicit Iterators - Ampersand
+       Ampersand should interpolate without HTML escaping.
+       => SUCCESS
+[29] Implicit Iterators - Basic Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[30] Interpolation - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[31] Triple Mustache - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[32] Ampersand - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[33] Interpolation - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[34] Triple Mustache - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[35] Ampersand - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[36] Interpolation With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+[37] Triple Mustache With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+[38] Ampersand With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/inverted.json
+processing file test-specs/spec/specs/inverted.json
+[0] Falsey
+       Falsey sections should have their contents rendered.
+       => SUCCESS
+[1] Truthy
+       Truthy sections should have their contents omitted.
+       => SUCCESS
+[2] Null is falsey
+       Null is falsey.
+       => SUCCESS
+[3] Context
+       Objects and hashes should behave like truthy values.
+       => SUCCESS
+[4] List
+       Lists should behave like truthy values.
+       => SUCCESS
+[5] Empty List
+       Empty lists should behave like falsey values.
+       => SUCCESS
+[6] Doubled
+       Multiple inverted sections per template should be permitted.
+       => SUCCESS
+[7] Nested (Falsey)
+       Nested falsey sections should have their contents rendered.
+       => SUCCESS
+[8] Nested (Truthy)
+       Nested truthy sections should be omitted.
+       => SUCCESS
+[9] Context Misses
+       Failed context lookups should be considered falsey.
+       => SUCCESS
+[10] Dotted Names - Truthy
+       Dotted names should be valid for Inverted Section tags.
+       => SUCCESS
+[11] Dotted Names - Falsey
+       Dotted names should be valid for Inverted Section tags.
+       => SUCCESS
+[12] Dotted Names - Broken Chains
+       Dotted names that cannot be resolved should be considered falsey.
+       => SUCCESS
+[13] Surrounding Whitespace
+       Inverted sections should not alter surrounding whitespace.
+       => SUCCESS
+[14] Internal Whitespace
+       Inverted should not alter internal whitespace.
+       => SUCCESS
+[15] Indented Inline Sections
+       Single-line sections should not alter surrounding whitespace.
+       => SUCCESS
+[16] Standalone Lines
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[17] Standalone Indented Lines
+       Standalone indented lines should be removed from the template.
+       => SUCCESS
+[18] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[19] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[20] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[21] Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/partials.json
+processing file test-specs/spec/specs/partials.json
+[0] Basic Behavior
+       The greater-than operator should expand to the named partial.
+       => SUCCESS
+[1] Failed Lookup
+       The empty string should be used when the named partial is not found.
+       => SUCCESS
+[2] Context
+       The greater-than operator should operate within the current context.
+       => SUCCESS
+[3] Recursion
+       The greater-than operator should properly recurse.
+       => SUCCESS
+[4] Nested
+       The greater-than operator should work from within partials.
+       => SUCCESS
+[5] Surrounding Whitespace
+       The greater-than operator should not alter surrounding whitespace.
+       => SUCCESS
+[6] Inline Indentation
+       Whitespace should be left untouched.
+       => SUCCESS
+[7] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[8] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[9] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[10] Standalone Indentation
+       Each line of the partial should be indented before rendering.
+       => SUCCESS
+[11] Padding Whitespace
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/sections.json
+processing file test-specs/spec/specs/sections.json
+[0] Truthy
+       Truthy sections should have their contents rendered.
+       => SUCCESS
+[1] Falsey
+       Falsey sections should have their contents omitted.
+       => SUCCESS
+[2] Null is falsey
+       Null is falsey.
+       => SUCCESS
+[3] Context
+       Objects and hashes should be pushed onto the context stack.
+       => SUCCESS
+[4] Parent contexts
+       Names missing in the current context are looked up in the stack.
+       => SUCCESS
+[5] Variable test
+       Non-false sections have their value at the top of context,
+accessible as {{.}} or through the parent context. This gives
+a simple way to display content conditionally if a variable exists.
+
+       => SUCCESS
+[6] List Contexts
+       All elements on the context stack should be accessible within lists.
+       => SUCCESS
+[7] Deeply Nested Contexts
+       All elements on the context stack should be accessible.
+       => SUCCESS
+[8] List
+       Lists should be iterated; list items should visit the context stack.
+       => SUCCESS
+[9] Empty List
+       Empty lists should behave like falsey values.
+       => SUCCESS
+[10] Doubled
+       Multiple sections per template should be permitted.
+       => SUCCESS
+[11] Nested (Truthy)
+       Nested truthy sections should have their contents rendered.
+       => SUCCESS
+[12] Nested (Falsey)
+       Nested falsey sections should be omitted.
+       => SUCCESS
+[13] Context Misses
+       Failed context lookups should be considered falsey.
+       => SUCCESS
+[14] Implicit Iterator - String
+       Implicit iterators should directly interpolate strings.
+       => SUCCESS
+[15] Implicit Iterator - Integer
+       Implicit iterators should cast integers to strings and interpolate.
+       => SUCCESS
+[16] Implicit Iterator - Decimal
+       Implicit iterators should cast decimals to strings and interpolate.
+       => DIFFERS
+       ..     
DATA[{"list":[1.1000000000000001,2.2000000000000002,3.2999999999999998,4.4000000000000004,5.5]}]
+       .. TEMPLATE["{{#list}}({{.}}){{/list}}"]
+       .. EXPECTED["(1.1)(2.2)(3.3)(4.4)(5.5)"]
+       ..      
GOT["(1.1000000000000001)(2.2000000000000002)(3.2999999999999998)(4.4000000000000004)(5.5)"]
+[17] Implicit Iterator - Array
+       Implicit iterators should allow iterating over nested arrays.
+       => SUCCESS
+[18] Implicit Iterator - HTML Escaping
+       Implicit iterators with basic interpolation should be HTML escaped.
+       => SUCCESS
+[19] Implicit Iterator - Triple mustache
+       Implicit iterators in triple mustache should interpolate without HTML 
escaping.
+       => SUCCESS
+[20] Implicit Iterator - Ampersand
+       Implicit iterators in an Ampersand tag should interpolate without HTML 
escaping.
+       => SUCCESS
+[21] Implicit Iterator - Root-level
+       Implicit iterators should work on root-level lists.
+       => SUCCESS
+[22] Dotted Names - Truthy
+       Dotted names should be valid for Section tags.
+       => SUCCESS
+[23] Dotted Names - Falsey
+       Dotted names should be valid for Section tags.
+       => SUCCESS
+[24] Dotted Names - Broken Chains
+       Dotted names that cannot be resolved should be considered falsey.
+       => SUCCESS
+[25] Surrounding Whitespace
+       Sections should not alter surrounding whitespace.
+       => SUCCESS
+[26] Internal Whitespace
+       Sections should not alter internal whitespace.
+       => SUCCESS
+[27] Indented Inline Sections
+       Single-line sections should not alter surrounding whitespace.
+       => SUCCESS
+[28] Standalone Lines
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[29] Indented Standalone Lines
+       Indented standalone lines should be removed from the template.
+       => SUCCESS
+[30] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[31] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[32] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[33] Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+summary:
+  error   0
+  differ  1
+  success 132
diff --git a/src/templating/test-specs/test-specs-json-c.ref 
b/src/templating/test-specs/test-specs-json-c.ref
new file mode 100644
index 00000000..8897c66c
--- /dev/null
+++ b/src/templating/test-specs/test-specs-json-c.ref
@@ -0,0 +1,425 @@
+
+loading test-specs/spec/specs/comments.json
+processing file test-specs/spec/specs/comments.json
+[0] Inline
+       Comment blocks should be removed from the template.
+       => SUCCESS
+[1] Multiline
+       Multiline comments should be permitted.
+       => SUCCESS
+[2] Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[3] Indented Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[4] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[5] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[6] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[7] Multiline Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[8] Indented Multiline Standalone
+       All standalone comment lines should be removed.
+       => SUCCESS
+[9] Indented Inline
+       Inline comments should not strip whitespace
+       => SUCCESS
+[10] Surrounding Whitespace
+       Comment removal should preserve surrounding whitespace.
+       => SUCCESS
+[11] Variable Name Collision
+       Comments must never render, even if variable with same name exists.
+       => SUCCESS
+
+loading test-specs/spec/specs/delimiters.json
+processing file test-specs/spec/specs/delimiters.json
+[0] Pair Behavior
+       The equals sign (used on both sides) should permit delimiter changes.
+       => SUCCESS
+[1] Special Characters
+       Characters with special meaning regexen should be valid delimiters.
+       => SUCCESS
+[2] Sections
+       Delimiters set outside sections should persist.
+       => SUCCESS
+[3] Inverted Sections
+       Delimiters set outside inverted sections should persist.
+       => SUCCESS
+[4] Partial Inheritence
+       Delimiters set in a parent template should not affect a partial.
+       => SUCCESS
+[5] Post-Partial Behavior
+       Delimiters set in a partial should not affect the parent template.
+       => SUCCESS
+[6] Surrounding Whitespace
+       Surrounding whitespace should be left untouched.
+       => SUCCESS
+[7] Outlying Whitespace (Inline)
+       Whitespace should be left untouched.
+       => SUCCESS
+[8] Standalone Tag
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[9] Indented Standalone Tag
+       Indented standalone lines should be removed from the template.
+       => SUCCESS
+[10] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[11] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[12] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[13] Pair with Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/interpolation.json
+processing file test-specs/spec/specs/interpolation.json
+[0] No Interpolation
+       Mustache-free templates should render as-is.
+       => SUCCESS
+[1] Basic Interpolation
+       Unadorned tags should interpolate content into the template.
+       => SUCCESS
+[2] HTML Escaping
+       Basic interpolation should be HTML escaped.
+       => SUCCESS
+[3] Triple Mustache
+       Triple mustaches should interpolate without HTML escaping.
+       => SUCCESS
+[4] Ampersand
+       Ampersand should interpolate without HTML escaping.
+       => SUCCESS
+[5] Basic Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[6] Triple Mustache Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[7] Ampersand Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[8] Basic Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[9] Triple Mustache Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[10] Ampersand Decimal Interpolation
+       Decimals should interpolate seamlessly with proper significance.
+       => SUCCESS
+[11] Basic Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[12] Triple Mustache Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[13] Ampersand Null Interpolation
+       Nulls should interpolate as the empty string.
+       => SUCCESS
+[14] Basic Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[15] Triple Mustache Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[16] Ampersand Context Miss Interpolation
+       Failed context lookups should default to empty strings.
+       => SUCCESS
+[17] Dotted Names - Basic Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[18] Dotted Names - Triple Mustache Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[19] Dotted Names - Ampersand Interpolation
+       Dotted names should be considered a form of shorthand for sections.
+       => SUCCESS
+[20] Dotted Names - Arbitrary Depth
+       Dotted names should be functional to any level of nesting.
+       => SUCCESS
+[21] Dotted Names - Broken Chains
+       Any falsey value prior to the last part of the name should yield ''.
+       => SUCCESS
+[22] Dotted Names - Broken Chain Resolution
+       Each part of a dotted name should resolve only against its parent.
+       => SUCCESS
+[23] Dotted Names - Initial Resolution
+       The first part of a dotted name should resolve as any other name.
+       => SUCCESS
+[24] Dotted Names - Context Precedence
+       Dotted names should be resolved against former resolutions.
+       => SUCCESS
+[25] Implicit Iterators - Basic Interpolation
+       Unadorned tags should interpolate content into the template.
+       => SUCCESS
+[26] Implicit Iterators - HTML Escaping
+       Basic interpolation should be HTML escaped.
+       => SUCCESS
+[27] Implicit Iterators - Triple Mustache
+       Triple mustaches should interpolate without HTML escaping.
+       => SUCCESS
+[28] Implicit Iterators - Ampersand
+       Ampersand should interpolate without HTML escaping.
+       => SUCCESS
+[29] Implicit Iterators - Basic Integer Interpolation
+       Integers should interpolate seamlessly.
+       => SUCCESS
+[30] Interpolation - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[31] Triple Mustache - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[32] Ampersand - Surrounding Whitespace
+       Interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[33] Interpolation - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[34] Triple Mustache - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[35] Ampersand - Standalone
+       Standalone interpolation should not alter surrounding whitespace.
+       => SUCCESS
+[36] Interpolation With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+[37] Triple Mustache With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+[38] Ampersand With Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/inverted.json
+processing file test-specs/spec/specs/inverted.json
+[0] Falsey
+       Falsey sections should have their contents rendered.
+       => SUCCESS
+[1] Truthy
+       Truthy sections should have their contents omitted.
+       => SUCCESS
+[2] Null is falsey
+       Null is falsey.
+       => SUCCESS
+[3] Context
+       Objects and hashes should behave like truthy values.
+       => SUCCESS
+[4] List
+       Lists should behave like truthy values.
+       => SUCCESS
+[5] Empty List
+       Empty lists should behave like falsey values.
+       => SUCCESS
+[6] Doubled
+       Multiple inverted sections per template should be permitted.
+       => SUCCESS
+[7] Nested (Falsey)
+       Nested falsey sections should have their contents rendered.
+       => SUCCESS
+[8] Nested (Truthy)
+       Nested truthy sections should be omitted.
+       => SUCCESS
+[9] Context Misses
+       Failed context lookups should be considered falsey.
+       => SUCCESS
+[10] Dotted Names - Truthy
+       Dotted names should be valid for Inverted Section tags.
+       => SUCCESS
+[11] Dotted Names - Falsey
+       Dotted names should be valid for Inverted Section tags.
+       => SUCCESS
+[12] Dotted Names - Broken Chains
+       Dotted names that cannot be resolved should be considered falsey.
+       => SUCCESS
+[13] Surrounding Whitespace
+       Inverted sections should not alter surrounding whitespace.
+       => SUCCESS
+[14] Internal Whitespace
+       Inverted should not alter internal whitespace.
+       => SUCCESS
+[15] Indented Inline Sections
+       Single-line sections should not alter surrounding whitespace.
+       => SUCCESS
+[16] Standalone Lines
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[17] Standalone Indented Lines
+       Standalone indented lines should be removed from the template.
+       => SUCCESS
+[18] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[19] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[20] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[21] Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/partials.json
+processing file test-specs/spec/specs/partials.json
+[0] Basic Behavior
+       The greater-than operator should expand to the named partial.
+       => SUCCESS
+[1] Failed Lookup
+       The empty string should be used when the named partial is not found.
+       => SUCCESS
+[2] Context
+       The greater-than operator should operate within the current context.
+       => SUCCESS
+[3] Recursion
+       The greater-than operator should properly recurse.
+       => SUCCESS
+[4] Nested
+       The greater-than operator should work from within partials.
+       => SUCCESS
+[5] Surrounding Whitespace
+       The greater-than operator should not alter surrounding whitespace.
+       => SUCCESS
+[6] Inline Indentation
+       Whitespace should be left untouched.
+       => SUCCESS
+[7] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[8] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[9] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[10] Standalone Indentation
+       Each line of the partial should be indented before rendering.
+       => SUCCESS
+[11] Padding Whitespace
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+loading test-specs/spec/specs/sections.json
+processing file test-specs/spec/specs/sections.json
+[0] Truthy
+       Truthy sections should have their contents rendered.
+       => SUCCESS
+[1] Falsey
+       Falsey sections should have their contents omitted.
+       => SUCCESS
+[2] Null is falsey
+       Null is falsey.
+       => SUCCESS
+[3] Context
+       Objects and hashes should be pushed onto the context stack.
+       => SUCCESS
+[4] Parent contexts
+       Names missing in the current context are looked up in the stack.
+       => SUCCESS
+[5] Variable test
+       Non-false sections have their value at the top of context,
+accessible as {{.}} or through the parent context. This gives
+a simple way to display content conditionally if a variable exists.
+
+       => SUCCESS
+[6] List Contexts
+       All elements on the context stack should be accessible within lists.
+       => SUCCESS
+[7] Deeply Nested Contexts
+       All elements on the context stack should be accessible.
+       => SUCCESS
+[8] List
+       Lists should be iterated; list items should visit the context stack.
+       => SUCCESS
+[9] Empty List
+       Empty lists should behave like falsey values.
+       => SUCCESS
+[10] Doubled
+       Multiple sections per template should be permitted.
+       => SUCCESS
+[11] Nested (Truthy)
+       Nested truthy sections should have their contents rendered.
+       => SUCCESS
+[12] Nested (Falsey)
+       Nested falsey sections should be omitted.
+       => SUCCESS
+[13] Context Misses
+       Failed context lookups should be considered falsey.
+       => SUCCESS
+[14] Implicit Iterator - String
+       Implicit iterators should directly interpolate strings.
+       => SUCCESS
+[15] Implicit Iterator - Integer
+       Implicit iterators should cast integers to strings and interpolate.
+       => SUCCESS
+[16] Implicit Iterator - Decimal
+       Implicit iterators should cast decimals to strings and interpolate.
+       => SUCCESS
+[17] Implicit Iterator - Array
+       Implicit iterators should allow iterating over nested arrays.
+       => SUCCESS
+[18] Implicit Iterator - HTML Escaping
+       Implicit iterators with basic interpolation should be HTML escaped.
+       => SUCCESS
+[19] Implicit Iterator - Triple mustache
+       Implicit iterators in triple mustache should interpolate without HTML 
escaping.
+       => SUCCESS
+[20] Implicit Iterator - Ampersand
+       Implicit iterators in an Ampersand tag should interpolate without HTML 
escaping.
+       => SUCCESS
+[21] Implicit Iterator - Root-level
+       Implicit iterators should work on root-level lists.
+       => SUCCESS
+[22] Dotted Names - Truthy
+       Dotted names should be valid for Section tags.
+       => SUCCESS
+[23] Dotted Names - Falsey
+       Dotted names should be valid for Section tags.
+       => SUCCESS
+[24] Dotted Names - Broken Chains
+       Dotted names that cannot be resolved should be considered falsey.
+       => SUCCESS
+[25] Surrounding Whitespace
+       Sections should not alter surrounding whitespace.
+       => SUCCESS
+[26] Internal Whitespace
+       Sections should not alter internal whitespace.
+       => SUCCESS
+[27] Indented Inline Sections
+       Single-line sections should not alter surrounding whitespace.
+       => SUCCESS
+[28] Standalone Lines
+       Standalone lines should be removed from the template.
+       => SUCCESS
+[29] Indented Standalone Lines
+       Indented standalone lines should be removed from the template.
+       => SUCCESS
+[30] Standalone Line Endings
+       "\r\n" should be considered a newline for standalone tags.
+       => SUCCESS
+[31] Standalone Without Previous Line
+       Standalone tags should not require a newline to precede them.
+       => SUCCESS
+[32] Standalone Without Newline
+       Standalone tags should not require a newline to follow them.
+       => SUCCESS
+[33] Padding
+       Superfluous in-tag whitespace should be ignored.
+       => SUCCESS
+
+summary:
+  error   0
+  differ  0
+  success 133
diff --git a/src/templating/test-specs/test-specs.c 
b/src/templating/test-specs/test-specs.c
new file mode 100644
index 00000000..15c94a80
--- /dev/null
+++ b/src/templating/test-specs/test-specs.c
@@ -0,0 +1,520 @@
+/*
+ Author: José Bollo <jobol@nonadev.net>
+
+ https://gitlab.com/jobol/mustach
+
+ SPDX-License-Identifier: ISC
+*/
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+
+#include "mustach-wrap.h"
+
+#define TEST_JSON_C  1
+#define TEST_JANSSON 2
+#define TEST_CJSON   3
+
+static const char *errors[] = {
+       "??? unreferenced ???",
+       "system",
+       "unexpected end",
+       "empty tag",
+       "tag too long",
+       "bad separators",
+       "too depth",
+       "closing",
+       "bad unescape tag",
+       "invalid interface",
+       "item not found",
+       "partial not found"
+};
+
+const char *mustach_error_string(int status)
+{
+       return status >= 0 ? "no error"
+               : errors[status <= -(int)(sizeof errors / sizeof * errors) ? 0 
: -status];
+}
+
+static const char *errmsg = 0;
+static int flags = 0;
+static FILE *output = 0;
+
+static void help(char *prog)
+{
+       char *name = basename(prog);
+#define STR(x) #x
+       printf("%s version %s\n", name, STR(VERSION));
+#undef STR
+       printf("usage: %s test-files...\n", name);
+       exit(0);
+}
+
+#if TEST == TEST_CJSON
+
+static const size_t BLOCKSIZE = 8192;
+
+static char *readfile(const char *filename, size_t *length)
+{
+       int f;
+       struct stat s;
+       char *result;
+       size_t size, pos;
+       ssize_t rc;
+
+       result = NULL;
+       if (filename[0] == '-' &&  filename[1] == 0)
+               f = dup(0);
+       else
+               f = open(filename, O_RDONLY);
+       if (f < 0) {
+               fprintf(stderr, "Can't open file: %s\n", filename);
+               exit(1);
+       }
+
+       fstat(f, &s);
+       switch (s.st_mode & S_IFMT) {
+       case S_IFREG:
+               size = s.st_size;
+               break;
+       case S_IFSOCK:
+       case S_IFIFO:
+               size = BLOCKSIZE;
+               break;
+       default:
+               fprintf(stderr, "Bad file: %s\n", filename);
+               exit(1);
+       }
+
+       pos = 0;
+       result = malloc(size + 1);
+       do {
+               if (result == NULL) {
+                       fprintf(stderr, "Out of memory\n");
+                       exit(1);
+               }
+               rc = read(f, &result[pos], (size - pos) + 1);
+               if (rc < 0) {
+                       fprintf(stderr, "Error while reading %s\n", filename);
+                       exit(1);
+               }
+               if (rc > 0) {
+                       pos += (size_t)rc;
+                       if (pos > size) {
+                               size = pos + BLOCKSIZE;
+                               result = realloc(result, size + 1);
+                       }
+               }
+       } while(rc > 0);
+
+       close(f);
+       if (length != NULL)
+               *length = pos;
+       result[pos] = 0;
+       return result;
+}
+#endif
+
+typedef struct {
+       unsigned nerror;
+       unsigned ndiffers;
+       unsigned nsuccess;
+       unsigned ninvalid;
+} counters;
+
+static int load_json(const char *filename);
+static int process(counters *c);
+static void close_json();
+static int get_partial(const char *name, struct mustach_sbuf *sbuf);
+
+int main(int ac, char **av)
+{
+       char *f;
+       char *prog = *av;
+       int s;
+       counters c;
+
+       (void)ac; /* unused */
+       flags = Mustach_With_SingleDot | Mustach_With_IncPartial;
+       output = stdout;
+       mustach_wrap_get_partial = get_partial;
+
+       memset(&c, 0, sizeof c);
+       while (*++av) {
+               if (!strcmp(*av, "-h") || !strcmp(*av, "--help"))
+                       help(prog);
+               f = (av[0][0] == '-' && !av[0][1]) ? "/dev/stdin" : av[0];
+               fprintf(output, "\nloading %s\n", f);
+               s = load_json(f);
+               if (s < 0) {
+                       fprintf(stderr, "error when loading %s!\n", f);
+                       if(errmsg)
+                               fprintf(stderr, "   reason: %s\n", errmsg);
+                       exit(1);
+               }
+               fprintf(output, "processing file %s\n", f);
+               s = process(&c);
+               if (s < 0) {
+                       fprintf(stderr, "error bad test file %s!\n", f);
+                       exit(1);
+               }
+               close_json();
+       }
+       fprintf(output, "\nsummary:\n");
+       if (c.ninvalid)
+               fprintf(output, "  invalid %u\n", c.ninvalid);
+       fprintf(output, "  error   %u\n", c.nerror);
+       fprintf(output, "  differ  %u\n", c.ndiffers);
+       fprintf(output, "  success %u\n", c.nsuccess);
+       if (c.nerror)
+               return 2;
+       if (c.ndiffers)
+               return 1;
+       return 0;
+}
+
+void emit(FILE *f, const char *s)
+{
+       for(;;s++) {
+               switch(*s) {
+               case 0: return;
+               case '\\': fprintf(f, "\\\\"); break;
+               case '\t': fprintf(f, "\\t"); break;
+               case '\n': fprintf(f, "\\n"); break;
+               case '\r': fprintf(f, "\\r"); break;
+               default: fprintf(f, "%c", *s); break;
+               }
+       }
+}
+
+#if TEST == TEST_JSON_C
+
+#include "mustach-json-c.h"
+
+static struct json_object *o;
+
+static struct json_object *partials;
+static int get_partial(const char *name, struct mustach_sbuf *sbuf)
+{
+       struct json_object *x;
+       if (partials == NULL || !json_object_object_get_ex(partials, name, &x))
+               return MUSTACH_ERROR_PARTIAL_NOT_FOUND;
+       sbuf->value = json_object_get_string(x);
+       return MUSTACH_OK;
+}
+
+static int load_json(const char *filename)
+{
+       o = json_object_from_file(filename);
+#if JSON_C_VERSION_NUM >= 0x000D00
+       errmsg = json_util_get_last_err();
+       if (errmsg != NULL)
+               return -1;
+#endif
+       if (o == NULL) {
+               errmsg = "null json";
+               return -1;
+       }
+       return 0;
+}
+static int process(counters *c)
+{
+       const char *t, *e;
+       char *got;
+       unsigned i, n;
+       size_t length;
+       int s;
+       json_object *tests, *unit, *name, *desc, *data, *template, *expected;
+
+       if (!json_object_object_get_ex(o, "tests", &tests) || 
json_object_get_type(tests) != json_type_array)
+               return -1;
+
+       i = 0;
+       n = (unsigned)json_object_array_length(tests);
+       while (i < n) {
+               unit = json_object_array_get_idx(tests, i);
+               if (json_object_get_type(unit) != json_type_object
+                || !json_object_object_get_ex(unit, "name", &name)
+                || !json_object_object_get_ex(unit, "desc", &desc)
+                || !json_object_object_get_ex(unit, "data", &data)
+                || !json_object_object_get_ex(unit, "template", &template)
+                || !json_object_object_get_ex(unit, "expected", &expected)
+                || json_object_get_type(name) != json_type_string
+                || json_object_get_type(desc) != json_type_string
+                || json_object_get_type(template) != json_type_string
+                || json_object_get_type(expected) != json_type_string) {
+                       fprintf(stderr, "invalid test %u\n", i);
+                       c->ninvalid++;
+               }
+               else {
+                       fprintf(output, "[%u] %s\n", i, 
json_object_get_string(name));
+                       fprintf(output, "\t%s\n", json_object_get_string(desc));
+                       if (!json_object_object_get_ex(unit, "partials", 
&partials))
+                               partials = NULL;
+                       t = json_object_get_string(template);
+                       e = json_object_get_string(expected);
+                       s = mustach_json_c_mem(t, 0, data, flags, &got, 
&length);
+                       if (s == 0 && strcmp(got, e) == 0) {
+                               fprintf(output, "\t=> SUCCESS\n");
+                               c->nsuccess++;
+                       }
+                       else {
+                               if (s < 0) {
+                                       fprintf(output, "\t=> ERROR %s\n", 
mustach_error_string(s));
+                                       c->nerror++;
+                               }
+                               else {
+                                       fprintf(output, "\t=> DIFFERS\n");
+                                       c->ndiffers++;
+                               }
+                               if (partials)
+                                       fprintf(output, "\t.. PARTIALS[%s]\n", 
json_object_to_json_string_ext(partials, 0));
+                               fprintf(output, "\t..     DATA[%s]\n", 
json_object_to_json_string_ext(data, 0));
+                               fprintf(output, "\t.. TEMPLATE[");
+                               emit(output, t);
+                               fprintf(output, "]\n");
+                               fprintf(output, "\t.. EXPECTED[");
+                               emit(output, e);
+                               fprintf(output, "]\n");
+                               if (s == 0) {
+                                       fprintf(output, "\t..      GOT[");
+                                       emit(output, got);
+                                       fprintf(output, "]\n");
+                               }
+                       }
+                       free(got);
+               }
+               i++;
+       }
+       return 0;
+}
+static void close_json()
+{
+       json_object_put(o);
+}
+
+#elif TEST == TEST_JANSSON
+
+#include "mustach-jansson.h"
+
+static json_t *o;
+static json_error_t e;
+
+static json_t *partials;
+static int get_partial(const char *name, struct mustach_sbuf *sbuf)
+{
+       json_t *x;
+       if (partials == NULL || !(x = json_object_get(partials, name)))
+               return MUSTACH_ERROR_PARTIAL_NOT_FOUND;
+       sbuf->value = json_string_value(x);
+       return MUSTACH_OK;
+}
+
+static int load_json(const char *filename)
+{
+       o = json_load_file(filename, JSON_DECODE_ANY, &e);
+       if (o == NULL) {
+               errmsg = e.text;
+               return -1;
+       }
+       return 0;
+}
+static int process(counters *c)
+{
+       const char *t, *e;
+       char *got, *tmp;
+       int i, n;
+       size_t length;
+       int s;
+       json_t *tests, *unit, *name, *desc, *data, *template, *expected;
+
+       tests = json_object_get(o, "tests");
+       if (!tests || json_typeof(tests) != JSON_ARRAY)
+               return -1;
+
+       i = 0;
+       n = json_array_size(tests);
+       while (i < n) {
+               unit = json_array_get(tests, i);
+               if (!unit || json_typeof(unit) != JSON_OBJECT
+                || !(name = json_object_get(unit, "name"))
+                || !(desc = json_object_get(unit, "desc"))
+                || !(data = json_object_get(unit, "data"))
+                || !(template = json_object_get(unit, "template"))
+                || !(expected = json_object_get(unit, "expected"))
+                || json_typeof(name) != JSON_STRING
+                || json_typeof(desc) != JSON_STRING
+                || json_typeof(template) != JSON_STRING
+                || json_typeof(expected) != JSON_STRING) {
+                       fprintf(stderr, "invalid test %u\n", i);
+                       c->ninvalid++;
+               }
+               else {
+                       fprintf(output, "[%u] %s\n", i, 
json_string_value(name));
+                       fprintf(output, "\t%s\n", json_string_value(desc));
+                       partials = json_object_get(unit, "partials");
+                       t = json_string_value(template);
+                       e = json_string_value(expected);
+                       s = mustach_jansson_mem(t, 0, data, flags, &got, 
&length);
+                       if (s == 0 && strcmp(got, e) == 0) {
+                               fprintf(output, "\t=> SUCCESS\n");
+                               c->nsuccess++;
+                       }
+                       else {
+                               if (s < 0) {
+                                       fprintf(output, "\t=> ERROR %s\n", 
mustach_error_string(s));
+                                       c->nerror++;
+                               }
+                               else {
+                                       fprintf(output, "\t=> DIFFERS\n");
+                                       c->ndiffers++;
+                               }
+                               if (partials) {
+                                       tmp = json_dumps(partials, 
JSON_ENCODE_ANY | JSON_COMPACT);
+                                       fprintf(output, "\t.. PARTIALS[%s]\n", 
tmp);
+                                       free(tmp);
+                               }
+                               tmp = json_dumps(data, JSON_ENCODE_ANY | 
JSON_COMPACT);
+                               fprintf(output, "\t..     DATA[%s]\n", tmp);
+                               free(tmp);
+                               fprintf(output, "\t.. TEMPLATE[");
+                               emit(output, t);
+                               fprintf(output, "]\n");
+                               fprintf(output, "\t.. EXPECTED[");
+                               emit(output, e);
+                               fprintf(output, "]\n");
+                               if (s == 0) {
+                                       fprintf(output, "\t..      GOT[");
+                                       emit(output, got);
+                                       fprintf(output, "]\n");
+                               }
+                       }
+                       free(got);
+               }
+               i++;
+       }
+       return 0;
+}
+static void close_json()
+{
+       json_decref(o);
+}
+
+#elif TEST == TEST_CJSON
+
+#include "mustach-cjson.h"
+
+static cJSON *o;
+static cJSON *partials;
+static int get_partial(const char *name, struct mustach_sbuf *sbuf)
+{
+       cJSON *x;
+       if (partials == NULL || !(x = 
cJSON_GetObjectItemCaseSensitive(partials, name)))
+               return MUSTACH_ERROR_PARTIAL_NOT_FOUND;
+       sbuf->value = x->valuestring;
+       return MUSTACH_OK;
+}
+
+static int load_json(const char *filename)
+{
+       char *t;
+       size_t length;
+
+       t = readfile(filename, &length);
+       o = t ? cJSON_ParseWithLength(t, length) : NULL;
+       free(t);
+       return -!o;
+}
+static int process(counters *c)
+{
+       const char *t, *e;
+       char *got, *tmp;
+       int i, n;
+       size_t length;
+       int s;
+       cJSON *tests, *unit, *name, *desc, *data, *template, *expected;
+
+       tests = cJSON_GetObjectItemCaseSensitive(o, "tests");
+       if (!tests || tests->type != cJSON_Array)
+               return -1;
+
+       i = 0;
+       n = cJSON_GetArraySize(tests);
+       while (i < n) {
+               unit = cJSON_GetArrayItem(tests, i);
+               if (!unit || unit->type != cJSON_Object
+                || !(name = cJSON_GetObjectItemCaseSensitive(unit, "name"))
+                || !(desc = cJSON_GetObjectItemCaseSensitive(unit, "desc"))
+                || !(data = cJSON_GetObjectItemCaseSensitive(unit, "data"))
+                || !(template = cJSON_GetObjectItemCaseSensitive(unit, 
"template"))
+                || !(expected = cJSON_GetObjectItemCaseSensitive(unit, 
"expected"))
+                || name->type != cJSON_String
+                || desc->type != cJSON_String
+                || template->type != cJSON_String
+                || expected->type != cJSON_String) {
+                       fprintf(stderr, "invalid test %u\n", i);
+                       c->ninvalid++;
+               }
+               else {
+                       fprintf(output, "[%u] %s\n", i, name->valuestring);
+                       fprintf(output, "\t%s\n", desc->valuestring);
+                       partials = cJSON_GetObjectItemCaseSensitive(unit, 
"partials");
+                       t = template->valuestring;
+                       e = expected->valuestring;
+                       s = mustach_cJSON_mem(t, 0, data, flags, &got, &length);
+                       if (s == 0 && strcmp(got, e) == 0) {
+                               fprintf(output, "\t=> SUCCESS\n");
+                               c->nsuccess++;
+                       }
+                       else {
+                               if (s < 0) {
+                                       fprintf(output, "\t=> ERROR %s\n", 
mustach_error_string(s));
+                                       c->nerror++;
+                               }
+                               else {
+                                       fprintf(output, "\t=> DIFFERS\n");
+                                       c->ndiffers++;
+                               }
+                               if (partials) {
+                                       tmp = cJSON_PrintUnformatted(partials);
+                                       fprintf(output, "\t.. PARTIALS[%s]\n", 
tmp);
+                                       free(tmp);
+                               }
+                               tmp = cJSON_PrintUnformatted(data);
+                               fprintf(output, "\t..     DATA[%s]\n", tmp);
+                               free(tmp);
+                               fprintf(output, "\t.. TEMPLATE[");
+                               emit(output, t);
+                               fprintf(output, "]\n");
+                               fprintf(output, "\t.. EXPECTED[");
+                               emit(output, e);
+                               fprintf(output, "]\n");
+                               if (s == 0) {
+                                       fprintf(output, "\t..      GOT[");
+                                       emit(output, got);
+                                       fprintf(output, "]\n");
+                               }
+                       }
+                       free(got);
+               }
+               i++;
+       }
+       return 0;
+}
+static void close_json()
+{
+       cJSON_Delete(o);
+}
+
+#else
+#error "no defined json library"
+#endif
diff --git a/src/templating/test1/Makefile b/src/templating/test1/Makefile
index bb96b350..1a3e5791 100644
--- a/src/templating/test1/Makefile
+++ b/src/templating/test1/Makefile
@@ -1,12 +1,7 @@
 .PHONY: test clean
 
 test:
-       @echo starting test
-       @../mustach json must > resu.last 2> vg.last
-       @sed -i 's:^==[0-9]*== ::' vg.last
-       @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result 
differs"
-       @awk '/^ *total heap usage: .* allocs, .* 
frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue"
-       @echo
+       @../dotest.sh json must
 
 clean:
        rm -f resu.last vg.last
diff --git a/src/templating/test1/must b/src/templating/test1/must
index 6df52366..92d30b0b 100644
--- a/src/templating/test1/must
+++ b/src/templating/test1/must
@@ -41,3 +41,9 @@ end
 {{:\=equal}}
 {{::colon}}
 {{:>greater}}
+
+{{#repo}}
+who 0 {{who.0}}
+who 1 {{who.1}}
+who 2 {{who.2}}
+{{/repo}}
diff --git a/src/templating/test1/resu.ref b/src/templating/test1/resu.ref
new file mode 100644
index 00000000..6cd11bb2
--- /dev/null
+++ b/src/templating/test1/resu.ref
@@ -0,0 +1,41 @@
+Hello Chris
+You have just won 10000 dollars!
+Well, 6000 dollars, after taxes.
+Shown.
+  No person
+
+  <b>resque</b> reviewers:  avrel  commiters: joe  william
+  <b>hub</b> reviewers:  avrel  commiters: jack  greg
+  <b>rip</b> reviewers: joe jack  commiters:   greg
+
+  Hi Jon!
+
+=====================================
+  <b>resque</b> reviewers:  avrel  commiters: joe  william
+  <b>hub</b> reviewers:  avrel  commiters: jack  greg
+  <b>rip</b> reviewers: joe jack  commiters:   greg
+=====================================
+ggggggggg
+----3.14159----
+jjjjjjjjj
+end
+
+#
+!
+~
+~
+/ see json pointers IETF RFC 6901
+^
+=
+:
+&gt;
+
+who 0 {&quot;commiter&quot;:&quot;joe&quot;}
+who 1 {&quot;reviewer&quot;:&quot;avrel&quot;}
+who 2 {&quot;commiter&quot;:&quot;william&quot;}
+who 0 {&quot;commiter&quot;:&quot;jack&quot;}
+who 1 {&quot;reviewer&quot;:&quot;avrel&quot;}
+who 2 {&quot;commiter&quot;:&quot;greg&quot;}
+who 0 {&quot;reviewer&quot;:&quot;joe&quot;}
+who 1 {&quot;reviewer&quot;:&quot;jack&quot;}
+who 2 {&quot;commiter&quot;:&quot;greg&quot;}
diff --git a/src/templating/test1/vg.ref b/src/templating/test1/vg.ref
new file mode 100644
index 00000000..d086e59c
--- /dev/null
+++ b/src/templating/test1/vg.ref
@@ -0,0 +1,14 @@
+Memcheck, a memory error detector
+Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
+Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
+Command: ../mustach json must
+
+
+HEAP SUMMARY:
+    in use at exit: 0 bytes in 0 blocks
+  total heap usage: 111 allocs, 111 frees, 9,702 bytes allocated
+
+All heap blocks were freed -- no leaks are possible
+
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/src/templating/test2/Makefile b/src/templating/test2/Makefile
index bb96b350..1a3e5791 100644
--- a/src/templating/test2/Makefile
+++ b/src/templating/test2/Makefile
@@ -1,12 +1,7 @@
 .PHONY: test clean
 
 test:
-       @echo starting test
-       @../mustach json must > resu.last 2> vg.last
-       @sed -i 's:^==[0-9]*== ::' vg.last
-       @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result 
differs"
-       @awk '/^ *total heap usage: .* allocs, .* 
frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue"
-       @echo
+       @../dotest.sh json must
 
 clean:
        rm -f resu.last vg.last
diff --git a/src/templating/test2/resu.ref b/src/templating/test2/resu.ref
new file mode 100644
index 00000000..5a200a9b
--- /dev/null
+++ b/src/templating/test2/resu.ref
@@ -0,0 +1,7 @@
+<h1>Colors</h1>
+
+    <li><strong>red</strong></li>
+    <li><a href="#Green">green</a></li>
+    <li><a href="#Blue">blue</a></li>
+
+
diff --git a/src/templating/test2/vg.ref b/src/templating/test2/vg.ref
new file mode 100644
index 00000000..e4b4f6d3
--- /dev/null
+++ b/src/templating/test2/vg.ref
@@ -0,0 +1,14 @@
+Memcheck, a memory error detector
+Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
+Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
+Command: ../mustach json must
+
+
+HEAP SUMMARY:
+    in use at exit: 0 bytes in 0 blocks
+  total heap usage: 38 allocs, 38 frees, 5,712 bytes allocated
+
+All heap blocks were freed -- no leaks are possible
+
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/src/templating/test3/Makefile b/src/templating/test3/Makefile
index bb96b350..1a3e5791 100644
--- a/src/templating/test3/Makefile
+++ b/src/templating/test3/Makefile
@@ -1,12 +1,7 @@
 .PHONY: test clean
 
 test:
-       @echo starting test
-       @../mustach json must > resu.last 2> vg.last
-       @sed -i 's:^==[0-9]*== ::' vg.last
-       @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result 
differs"
-       @awk '/^ *total heap usage: .* allocs, .* 
frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue"
-       @echo
+       @../dotest.sh json must
 
 clean:
        rm -f resu.last vg.last
diff --git a/src/templating/test3/resu.ref b/src/templating/test3/resu.ref
new file mode 100644
index 00000000..ee6dad3f
--- /dev/null
+++ b/src/templating/test3/resu.ref
@@ -0,0 +1,13 @@
+* Chris
+* 18
+* &lt;b&gt;GitHub &amp; Co&lt;/b&gt;
+* <b>GitHub & Co</b>
+* <b>GitHub & Co</b>
+* &lt;b&gt;GitHub &amp; Co&lt;/b&gt;
+* <b>GitHub & Co</b>
+* <b>GitHub & Co</b>
+
+* <ul><li>Chris</li><li>Kross</li></ul>
+* skills: <ul><li>JavaScript</li><li>PHP</li><li>Java</li></ul>
+* age: 18
+
diff --git a/src/templating/test3/vg.ref b/src/templating/test3/vg.ref
new file mode 100644
index 00000000..21f7931e
--- /dev/null
+++ b/src/templating/test3/vg.ref
@@ -0,0 +1,14 @@
+Memcheck, a memory error detector
+Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
+Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
+Command: ../mustach json must
+
+
+HEAP SUMMARY:
+    in use at exit: 0 bytes in 0 blocks
+  total heap usage: 30 allocs, 30 frees, 5,831 bytes allocated
+
+All heap blocks were freed -- no leaks are possible
+
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/src/templating/test4/Makefile b/src/templating/test4/Makefile
index bb96b350..1a3e5791 100644
--- a/src/templating/test4/Makefile
+++ b/src/templating/test4/Makefile
@@ -1,12 +1,7 @@
 .PHONY: test clean
 
 test:
-       @echo starting test
-       @../mustach json must > resu.last 2> vg.last
-       @sed -i 's:^==[0-9]*== ::' vg.last
-       @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result 
differs"
-       @awk '/^ *total heap usage: .* allocs, .* 
frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue"
-       @echo
+       @../dotest.sh json must
 
 clean:
        rm -f resu.last vg.last
diff --git a/src/templating/test4/resu.ref b/src/templating/test4/resu.ref
new file mode 100644
index 00000000..8a71c4e8
--- /dev/null
+++ b/src/templating/test4/resu.ref
@@ -0,0 +1,50 @@
+This are extensions!!
+
+Jon
+25
+
+Fred
+The other Fred.
+
+Hello Jon
+
+
+No Harry? Hey Calahan...
+
+Hello Fred
+
+
+Hello Fred#2
+
+
+Hello Jon, 25 years
+
+Hello Henry, 27 years
+
+
+Salut Amed, 24 ans
+
+Jon: /25/25
+Henry: /27/
+Amed: 24/24/24
+
+Jon: /25/25
+Henry: /27/
+Amed: 24/24/24
+
+ (1) person: {&quot;name&quot;:&quot;Jon&quot;,&quot;age&quot;:25}
+     (2) name: Jon
+     (2) age: 25
+ (1) person.name: Fred
+ (1) person.name=Fred: The other Fred.
+ (1) persons: 
[{&quot;name&quot;:&quot;Jon&quot;,&quot;age&quot;:25,&quot;lang&quot;:&quot;en&quot;},{&quot;name&quot;:&quot;Henry&quot;,&quot;age&quot;:27,&quot;lang&quot;:&quot;en&quot;},{&quot;name&quot;:&quot;Amed&quot;,&quot;age&quot;:24,&quot;lang&quot;:&quot;fr&quot;}]
+ (1) fellows: 
{&quot;Jon&quot;:{&quot;age&quot;:25,&quot;lang&quot;:&quot;en&quot;},&quot;Henry&quot;:{&quot;age&quot;:27,&quot;lang&quot;:&quot;en&quot;},&quot;Amed&quot;:{&quot;age&quot;:24,&quot;lang&quot;:&quot;fr&quot;}}
+     (2) Jon: {&quot;age&quot;:25,&quot;lang&quot;:&quot;en&quot;}
+       (3) age: 25
+       (3) lang: en
+     (2) Henry: {&quot;age&quot;:27,&quot;lang&quot;:&quot;en&quot;}
+       (3) age: 27
+       (3) lang: en
+     (2) Amed: {&quot;age&quot;:24,&quot;lang&quot;:&quot;fr&quot;}
+       (3) age: 24
+       (3) lang: fr
diff --git a/src/templating/test4/vg.ref b/src/templating/test4/vg.ref
new file mode 100644
index 00000000..922b0676
--- /dev/null
+++ b/src/templating/test4/vg.ref
@@ -0,0 +1,14 @@
+Memcheck, a memory error detector
+Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
+Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
+Command: ../mustach json must
+
+
+HEAP SUMMARY:
+    in use at exit: 0 bytes in 0 blocks
+  total heap usage: 121 allocs, 121 frees, 14,608 bytes allocated
+
+All heap blocks were freed -- no leaks are possible
+
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/src/templating/test5/Makefile b/src/templating/test5/Makefile
index bb96b350..1a3e5791 100644
--- a/src/templating/test5/Makefile
+++ b/src/templating/test5/Makefile
@@ -1,12 +1,7 @@
 .PHONY: test clean
 
 test:
-       @echo starting test
-       @../mustach json must > resu.last 2> vg.last
-       @sed -i 's:^==[0-9]*== ::' vg.last
-       @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result 
differs"
-       @awk '/^ *total heap usage: .* allocs, .* 
frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue"
-       @echo
+       @../dotest.sh json must
 
 clean:
        rm -f resu.last vg.last
diff --git a/src/templating/test5/resu.ref b/src/templating/test5/resu.ref
new file mode 100644
index 00000000..f2a60856
--- /dev/null
+++ b/src/templating/test5/resu.ref
@@ -0,0 +1,38 @@
+=====================================
+from json
+----3.14159----
+=====================================
+not found
+=====================================
+without extension first
+must2 == BEGIN
+Hello Chris
+You have just won 10000 dollars!
+Well, 6000 dollars, after taxes.
+Shown.
+  No person
+must2 == END
+=====================================
+last with extension
+must3.mustache == BEGIN
+  <b>resque</b> reviewers:  avrel  commiters: joe  william
+  <b>hub</b> reviewers:  avrel  commiters: jack  greg
+  <b>rip</b> reviewers: joe jack  commiters:   greg
+
+  Hi Jon!
+
+=====================================
+  <b>resque</b> reviewers:  avrel  commiters: joe  william
+  <b>hub</b> reviewers:  avrel  commiters: jack  greg
+  <b>rip</b> reviewers: joe jack  commiters:   greg
+=====================================
+must3.mustache == END
+=====================================
+Ensure must3 didn't change specials
+
+  Hi Jon!
+
+%(%#person?%)%
+  Hi %(%name%)%!
+%(%/person?%)%
+
diff --git a/src/templating/test5/vg.ref b/src/templating/test5/vg.ref
new file mode 100644
index 00000000..89dc21bc
--- /dev/null
+++ b/src/templating/test5/vg.ref
@@ -0,0 +1,14 @@
+Memcheck, a memory error detector
+Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
+Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
+Command: ../mustach json must
+
+
+HEAP SUMMARY:
+    in use at exit: 0 bytes in 0 blocks
+  total heap usage: 123 allocs, 123 frees, 20,610 bytes allocated
+
+All heap blocks were freed -- no leaks are possible
+
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/src/templating/test6/Makefile b/src/templating/test6/Makefile
index 6178902c..ea4f86e7 100644
--- a/src/templating/test6/Makefile
+++ b/src/templating/test6/Makefile
@@ -5,12 +5,7 @@ test-custom-write: test-custom-write.c ../mustach-json-c.h 
../mustach-json-c.c .
        $(CC) $(CFLAGS) $(LDFLAGS) -g -o test-custom-write test-custom-write.c  
../mustach.c  ../mustach-json-c.c ../mustach-wrap.c -ljson-c
 
 test: test-custom-write
-       @echo starting test
-       @./test-custom-write json -U must -l must -x must > resu.last 2> vg.last
-       @sed -i 's:^==[0-9]*== ::' vg.last
-       @diff -w resu.ref resu.last && echo "result ok" || echo "ERROR! Result 
differs"
-       @awk '/^ *total heap usage: .* allocs, .* 
frees,.*/{if($$4-$$6)exit(1)}' vg.last || echo "ERROR! Alloc/Free issue"
-       @echo
+       @mustach=./test-custom-write ../dotest.sh json -U must -l must -x must
 
 clean:
        rm -f resu.last vg.last test-custom-write
diff --git a/src/templating/test6/resu.ref b/src/templating/test6/resu.ref
new file mode 100644
index 00000000..377eb11a
--- /dev/null
+++ b/src/templating/test6/resu.ref
@@ -0,0 +1,93 @@
+HELLO CHRIS
+YOU HAVE JUST WON 10000 DOLLARS!
+WELL, 6000 DOLLARS, AFTER TAXES.
+SHOWN.
+  NO PERSON
+
+  <B>RESQUE</B> REVIEWERS:  AVREL  COMMITERS: JOE  WILLIAM
+  <B>HUB</B> REVIEWERS:  AVREL  COMMITERS: JACK  GREG
+  <B>RIP</B> REVIEWERS: JOE JACK  COMMITERS:   GREG
+
+  HI JON!
+
+=====================================
+  <B>RESQUE</B> REVIEWERS:  AVREL  COMMITERS: JOE  WILLIAM
+  <B>HUB</B> REVIEWERS:  AVREL  COMMITERS: JACK  GREG
+  <B>RIP</B> REVIEWERS: JOE JACK  COMMITERS:   GREG
+=====================================
+GGGGGGGGG
+----3.14159----
+JJJJJJJJJ
+END
+
+#
+!
+~
+~
+/ SEE JSON POINTERS IETF RFC 6901
+^
+=
+:
+&GT;
+hello chris
+you have just won 10000 dollars!
+well, 6000 dollars, after taxes.
+shown.
+  no person
+
+  <b>resque</b> reviewers:  avrel  commiters: joe  william
+  <b>hub</b> reviewers:  avrel  commiters: jack  greg
+  <b>rip</b> reviewers: joe jack  commiters:   greg
+
+  hi jon!
+
+=====================================
+  <b>resque</b> reviewers:  avrel  commiters: joe  william
+  <b>hub</b> reviewers:  avrel  commiters: jack  greg
+  <b>rip</b> reviewers: joe jack  commiters:   greg
+=====================================
+ggggggggg
+----3.14159----
+jjjjjjjjj
+end
+
+#
+!
+~
+~
+/ see json pointers ietf rfc 6901
+^
+=
+:
+&gt;
+Hello Chris
+You have just won 10000 dollars!
+Well, 6000 dollars, after taxes.
+Shown.
+  No person
+
+  <b>resque</b> reviewers:  avrel  commiters: joe  william
+  <b>hub</b> reviewers:  avrel  commiters: jack  greg
+  <b>rip</b> reviewers: joe jack  commiters:   greg
+
+  Hi Jon!
+
+=====================================
+  <b>resque</b> reviewers:  avrel  commiters: joe  william
+  <b>hub</b> reviewers:  avrel  commiters: jack  greg
+  <b>rip</b> reviewers: joe jack  commiters:   greg
+=====================================
+ggggggggg
+----3.14159----
+jjjjjjjjj
+end
+
+#
+!
+~
+~
+/ see json pointers IETF RFC 6901
+^
+=
+:
+&gt;
diff --git a/src/templating/test6/test-custom-write.c 
b/src/templating/test6/test-custom-write.c
index 4ba953a8..20042c1e 100644
--- a/src/templating/test6/test-custom-write.c
+++ b/src/templating/test6/test-custom-write.c
@@ -16,7 +16,9 @@
  limitations under the License.
 */
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include <stdlib.h>
 #include <stdio.h>
diff --git a/src/templating/test6/vg.ref b/src/templating/test6/vg.ref
new file mode 100644
index 00000000..fb0e31bd
--- /dev/null
+++ b/src/templating/test6/vg.ref
@@ -0,0 +1,14 @@
+Memcheck, a memory error detector
+Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
+Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
+Command: ./test-custom-write json -U must -l must -x must
+
+
+HEAP SUMMARY:
+    in use at exit: 0 bytes in 0 blocks
+  total heap usage: 174 allocs, 174 frees, 24,250 bytes allocated
+
+All heap blocks were freed -- no leaks are possible
+
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/src/templating/test7/base.mustache 
b/src/templating/test7/base.mustache
new file mode 100644
index 00000000..f701e0c6
--- /dev/null
+++ b/src/templating/test7/base.mustache
@@ -0,0 +1,2 @@
+family:
+{{> node}}
diff --git a/src/templating/test7/json b/src/templating/test7/json
new file mode 100644
index 00000000..c9ee4715
--- /dev/null
+++ b/src/templating/test7/json
@@ -0,0 +1,8 @@
+{ "data": "grandparent", "children": [
+  { "data": "parent", "children": [
+    { "data": "child", "children": [] }
+  ]},
+  { "data": "parent2", "children": [
+    { "data": "child2", "children": [ { "data": "pet", "children": false } ]}
+  ]}
+]}
diff --git a/src/templating/test7/node.mustache 
b/src/templating/test7/node.mustache
new file mode 100644
index 00000000..4154b12b
--- /dev/null
+++ b/src/templating/test7/node.mustache
@@ -0,0 +1,4 @@
+<{{data}}>
+{{#children}}
+    {{> node}}
+{{/children}}
diff --git a/src/templating/test7/resu.ref b/src/templating/test7/resu.ref
new file mode 100644
index 00000000..d02b24e1
--- /dev/null
+++ b/src/templating/test7/resu.ref
@@ -0,0 +1,7 @@
+family:
+<grandparent>
+    <parent>
+        <child>
+    <parent2>
+        <child2>
+            <pet>
diff --git a/src/templating/test7/vg.ref b/src/templating/test7/vg.ref
new file mode 100644
index 00000000..032e6c44
--- /dev/null
+++ b/src/templating/test7/vg.ref
@@ -0,0 +1,14 @@
+Memcheck, a memory error detector
+Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
+Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
+Command: ../mustach json base.mustache
+
+
+HEAP SUMMARY:
+    in use at exit: 0 bytes in 0 blocks
+  total heap usage: 69 allocs, 69 frees, 36,313 bytes allocated
+
+All heap blocks were freed -- no leaks are possible
+
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
diff --git a/src/templating/test8/.gitignore b/src/templating/test8/.gitignore
new file mode 100644
index 00000000..4d897daa
--- /dev/null
+++ b/src/templating/test8/.gitignore
@@ -0,0 +1,2 @@
+resu.last
+vg.last
diff --git a/src/templating/test8/json b/src/templating/test8/json
new file mode 100644
index 00000000..04a1e4aa
--- /dev/null
+++ b/src/templating/test8/json
@@ -0,0 +1,8 @@
+{
+"val1": "",
+"val2": 0,
+"val3": false,
+"val4": null,
+"val5": [],
+"val6": 0.0
+}
diff --git a/src/templating/test8/must b/src/templating/test8/must
new file mode 100644
index 00000000..a2237443
--- /dev/null
+++ b/src/templating/test8/must
@@ -0,0 +1,6 @@
+x{{#val1}} {{.}} {{/val1}}x
+x{{#val2}} {{.}} {{/val2}}x
+x{{#val3}} {{.}} {{/val3}}x
+x{{#val4}} {{.}} {{/val4}}x
+x{{#val5}} {{.}} {{/val5}}x
+x{{#val6}} {{.}} {{/val6}}x
diff --git a/src/templating/test8/resu.ref b/src/templating/test8/resu.ref
new file mode 100644
index 00000000..e0c16e49
--- /dev/null
+++ b/src/templating/test8/resu.ref
@@ -0,0 +1,6 @@
+xx
+xx
+xx
+xx
+xx
+xx
diff --git a/src/templating/test8/vg.ref b/src/templating/test8/vg.ref
new file mode 100644
index 00000000..b5b0235f
--- /dev/null
+++ b/src/templating/test8/vg.ref
@@ -0,0 +1,14 @@
+Memcheck, a memory error detector
+Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
+Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
+Command: ../mustach json must
+
+
+HEAP SUMMARY:
+    in use at exit: 0 bytes in 0 blocks
+  total heap usage: 17 allocs, 17 frees, 4,832 bytes allocated
+
+All heap blocks were freed -- no leaks are possible
+
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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