gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated (8a6d67a3 -> 21648351)


From: gnunet
Subject: [taler-exchange] branch master updated (8a6d67a3 -> 21648351)
Date: Mon, 18 Mar 2024 13:30:27 +0100

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

grothoff pushed a change to branch master
in repository exchange.

    from 8a6d67a3 ci: ensure deb version strings are use commit ref
     new 9468d2a7 -update mustach
     new 21648351 migrate test logic

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 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/run-original-tests.sh             |   3 +
 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/{test1 => test8}/.gitignore       |   0
 src/templating/test8/json                        |   8 +
 src/templating/test8/must                        |   6 +
 src/templating/test8/resu.ref                    |   6 +
 src/templating/test8/vg.ref                      |  14 +
 53 files changed, 2628 insertions(+), 97 deletions(-)
 create mode 100644 src/templating/CHANGELOG.md
 create mode 100755 src/templating/dotest.sh
 create mode 100644 src/templating/mustach.1.gz
 create mode 100644 src/templating/mustach.1.scd
 create mode 100644 src/templating/pkgcfgs
 create mode 100644 src/templating/test-specs/test-specs-cjson.ref
 create mode 100644 src/templating/test-specs/test-specs-jansson.ref
 create mode 100644 src/templating/test-specs/test-specs-json-c.ref
 create mode 100644 src/templating/test-specs/test-specs.c
 create mode 100644 src/templating/test1/resu.ref
 create mode 100644 src/templating/test1/vg.ref
 create mode 100644 src/templating/test2/resu.ref
 create mode 100644 src/templating/test2/vg.ref
 create mode 100644 src/templating/test3/resu.ref
 create mode 100644 src/templating/test3/vg.ref
 create mode 100644 src/templating/test4/resu.ref
 create mode 100644 src/templating/test4/vg.ref
 create mode 100644 src/templating/test5/resu.ref
 create mode 100644 src/templating/test5/vg.ref
 create mode 100644 src/templating/test6/resu.ref
 create mode 100644 src/templating/test6/vg.ref
 create mode 100644 src/templating/test7/base.mustache
 create mode 100644 src/templating/test7/json
 create mode 100644 src/templating/test7/node.mustache
 create mode 100644 src/templating/test7/resu.ref
 create mode 100644 src/templating/test7/vg.ref
 copy src/templating/{test1 => test8}/.gitignore (100%)
 create mode 100644 src/templating/test8/json
 create mode 100644 src/templating/test8/must
 create mode 100644 src/templating/test8/resu.ref
 create mode 100644 src/templating/test8/vg.ref

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/run-original-tests.sh 
b/src/templating/run-original-tests.sh
index f183736b..09420c4e 100755
--- a/src/templating/run-original-tests.sh
+++ b/src/templating/run-original-tests.sh
@@ -7,7 +7,10 @@ set -eu
 
 export CFLAGS="-g"
 
+make clean
 make -f mustach-original-Makefile mustach || exit 77
 make -f mustach-original-Makefile clean || true
 make -f mustach-original-Makefile basic-tests
 make -f mustach-original-Makefile clean || true
+make clean
+make
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/test1/.gitignore b/src/templating/test8/.gitignore
similarity index 100%
copy from src/templating/test1/.gitignore
copy to src/templating/test8/.gitignore
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]