summaryrefslogtreecommitdiff
path: root/src/templating/mustach-tool.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/templating/mustach-tool.c')
-rw-r--r--src/templating/mustach-tool.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/templating/mustach-tool.c b/src/templating/mustach-tool.c
new file mode 100644
index 000000000..5f28c1f58
--- /dev/null
+++ b/src/templating/mustach-tool.c
@@ -0,0 +1,258 @@
+/*
+ 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 <libgen.h>
+
+#include "mustach-wrap.h"
+
+static const size_t BLOCKSIZE = 8192;
+
+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",
+ "undefined tag",
+ "too much template nesting"
+};
+
+static const char *errmsg = 0;
+static int flags = 0;
+static FILE *output = 0;
+
+static void help(char *prog)
+{
+ char *name = basename(prog);
+#define STR_INDIR(x) #x
+#define STR(x) STR_INDIR(x)
+ printf("%s version %s\n", name, STR(VERSION));
+#undef STR
+#undef STR_INDIR
+ printf(
+ "\n"
+ "USAGE:\n"
+ " %s [FLAGS] <json-file> <mustach-templates...>\n"
+ "\n"
+ "FLAGS:\n"
+ " -h, --help Prints help information\n"
+ " -s, --strict Error when a tag is undefined\n"
+ "\n"
+ "ARGS: (if a file is -, read standard input)\n"
+ " <json-file> JSON file with input data\n"
+ " <mustach-templates...> Template files to instantiate\n",
+ name);
+ exit(0);
+}
+
+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;
+}
+
+static int load_json(const char *filename);
+static int process(const char *content, size_t length);
+static void close_json();
+
+int main(int ac, char **av)
+{
+ char *t, *f;
+ char *prog = *av;
+ int s;
+ size_t length;
+
+ (void)ac; /* unused */
+ flags = Mustach_With_AllExtensions;
+ output = stdout;
+
+ for( ++av ; av[0] && av[0][0] == '-' && av[0][1] != 0 ; av++) {
+ if (!strcmp(*av, "-h") || !strcmp(*av, "--help"))
+ help(prog);
+ if (!strcmp(*av, "-s") || !strcmp(*av, "--strict"))
+ flags |= Mustach_With_ErrorUndefined;
+ }
+ if (*av) {
+ f = (av[0][0] == '-' && !av[0][1]) ? "/dev/stdin" : av[0];
+ s = load_json(f);
+ if (s < 0) {
+ fprintf(stderr, "Can't load json file %s\n", av[0]);
+ if(errmsg)
+ fprintf(stderr, " reason: %s\n", errmsg);
+ exit(1);
+ }
+ while(*++av) {
+ t = readfile(*av, &length);
+ s = process(t, length);
+ free(t);
+ if (s != MUSTACH_OK) {
+ s = -s;
+ if (s < 1 || s >= (int)(sizeof errors / sizeof * errors))
+ s = 0;
+ fprintf(stderr, "Template error %s (file %s)\n", errors[s], *av);
+ }
+ }
+ close_json();
+ }
+ return 0;
+}
+
+#define MUSTACH_TOOL_JSON_C 1
+#define MUSTACH_TOOL_JANSSON 2
+#define MUSTACH_TOOL_CJSON 3
+
+#if TOOL == MUSTACH_TOOL_JSON_C
+
+#include "mustach-json-c.h"
+
+static struct json_object *o;
+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(const char *content, size_t length)
+{
+ return mustach_json_c_file(content, length, o, flags, output);
+}
+static void close_json()
+{
+ json_object_put(o);
+}
+
+#elif TOOL == MUSTACH_TOOL_JANSSON
+
+#include "mustach-jansson.h"
+
+static json_t *o;
+static json_error_t e;
+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(const char *content, size_t length)
+{
+ return mustach_jansson_file(content, length, o, flags, output);
+}
+static void close_json()
+{
+ json_decref(o);
+}
+
+#elif TOOL == MUSTACH_TOOL_CJSON
+
+#include "mustach-cjson.h"
+
+static cJSON *o;
+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(const char *content, size_t length)
+{
+ return mustach_cJSON_file(content, length, o, flags, output);
+}
+static void close_json()
+{
+ cJSON_Delete(o);
+}
+
+#else
+#error "no defined json library"
+#endif