mustach: sync with most recent mustach upstream changes

Git: https://gitlab.com/jobol/mustach.git
Commit: 3a694bdc6cdd374358a30949206e315ed3428cf9
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2019-03-26 21:00:40 +00:00
parent 008e9f17c1
commit 4f64902a9e
No known key found for this signature in database
GPG key ID: 0D46FEF7E61DBB46
3 changed files with 110 additions and 37 deletions

View file

@ -441,7 +441,7 @@ int mustach_dhcpd_pools(struct conf_t *state)
case MUSTACH_ERROR_BAD_SEPARATORS: case MUSTACH_ERROR_BAD_SEPARATORS:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: bad separator"); error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: bad separator");
break; break;
case MUSTACH_ERROR_TOO_DEPTH: case MUSTACH_ERROR_TOO_DEEP:
error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: too deep"); error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: too deep");
break; break;
case MUSTACH_ERROR_CLOSING: case MUSTACH_ERROR_CLOSING:

View file

@ -30,6 +30,76 @@
#define NAME_LENGTH_MAX 1024 #define NAME_LENGTH_MAX 1024
#define DEPTH_MAX 256 #define DEPTH_MAX 256
#if !defined(NO_OPEN_MEMSTREAM)
static FILE *memfile_open(char **buffer, size_t *size)
{
return open_memstream(buffer, size);
}
static void memfile_abort(FILE *file, char **buffer, size_t *size)
{
fclose(file);
free(*buffer);
*buffer = NULL;
*size = 0;
}
static int memfile_close(FILE *file, char **buffer, size_t *size)
{
int rc;
/* adds terminating null */
rc = fputc(0, file) ? MUSTACH_ERROR_SYSTEM : 0;
fclose(file);
if (rc == 0)
/* removes terminating null of the length */
(*size)--;
else {
free(*buffer);
*buffer = NULL;
*size = 0;
}
return rc;
}
#else
static FILE *memfile_open(char **buffer, size_t *size)
{
return tmpfile();
}
static void memfile_abort(FILE *file, char **buffer, size_t *size)
{
fclose(file);
*buffer = NULL;
*size = 0;
}
static int memfile_close(FILE *file, char **buffer, size_t *size)
{
int rc;
size_t s;
char *b;
s = (size_t)ftell(file);
b = malloc(s + 1);
if (b == NULL) {
rc = MUSTACH_ERROR_SYSTEM;
errno = ENOMEM;
s = 0;
} else {
rewind(file);
if (1 == fread(b, s, 1, file)) {
rc = 0;
b[s] = 0;
} else {
rc = MUSTACH_ERROR_SYSTEM;
free(b);
b = NULL;
s = 0;
}
}
*buffer = b;
*size = s;
return rc;
}
#endif
static int getpartial(struct mustach_itf *itf, void *closure, const char *name, char **result) static int getpartial(struct mustach_itf *itf, void *closure, const char *name, char **result)
{ {
int rc; int rc;
@ -37,26 +107,22 @@ static int getpartial(struct mustach_itf *itf, void *closure, const char *name,
size_t size; size_t size;
*result = NULL; *result = NULL;
file = open_memstream(result, &size); file = memfile_open(result, &size);
if (file == NULL) if (file == NULL)
rc = MUSTACH_ERROR_SYSTEM; rc = MUSTACH_ERROR_SYSTEM;
else { else {
rc = itf->put(closure, name, 0, file); rc = itf->put(closure, name, 0, file);
if (rc == 0) if (rc < 0)
/* adds terminating null */ memfile_abort(file, result, &size);
rc = fputc(0, file) ? MUSTACH_ERROR_SYSTEM : 0; else
fclose(file); rc = memfile_close(file, result, &size);
if (rc < 0) {
free(*result);
*result = NULL;
}
} }
return rc; return rc;
} }
static int process(const char *template, struct mustach_itf *itf, void *closure, FILE *file, const char *opstr, const char *clstr) static int process(const char *template, struct mustach_itf *itf, void *closure, FILE *file, const char *opstr, const char *clstr)
{ {
char name[NAME_LENGTH_MAX + 1], *partial, c; char name[NAME_LENGTH_MAX + 1], *partial, c, *tmp;
const char *beg, *term; const char *beg, *term;
struct { const char *name, *again; size_t length; int emit, entered; } stack[DEPTH_MAX]; struct { const char *name, *again; size_t length; int emit, entered; } stack[DEPTH_MAX];
size_t oplen, cllen, len, l; size_t oplen, cllen, len, l;
@ -112,8 +178,10 @@ static int process(const char *template, struct mustach_itf *itf, void *closure,
default: default:
while (len && isspace(beg[0])) { beg++; len--; } while (len && isspace(beg[0])) { beg++; len--; }
while (len && isspace(beg[len-1])) len--; while (len && isspace(beg[len-1])) len--;
#if defined(NO_EXTENSION_FOR_MUSTACH) || defined(NO_ALLOW_EMPTY_TAG)
if (len == 0) if (len == 0)
return MUSTACH_ERROR_EMPTY_TAG; return MUSTACH_ERROR_EMPTY_TAG;
#endif
if (len > NAME_LENGTH_MAX) if (len > NAME_LENGTH_MAX)
return MUSTACH_ERROR_TAG_TOO_LONG; return MUSTACH_ERROR_TAG_TOO_LONG;
memcpy(name, beg, len); memcpy(name, beg, len);
@ -134,19 +202,25 @@ static int process(const char *template, struct mustach_itf *itf, void *closure,
for (l = 0; l < len && !isspace(beg[l]) ; l++); for (l = 0; l < len && !isspace(beg[l]) ; l++);
if (l == len) if (l == len)
return MUSTACH_ERROR_BAD_SEPARATORS; return MUSTACH_ERROR_BAD_SEPARATORS;
opstr = strndupa(beg, l); oplen = l;
tmp = alloca(oplen + 1);
memcpy(tmp, beg, oplen);
tmp[oplen] = 0;
opstr = tmp;
while (l < len && isspace(beg[l])) l++; while (l < len && isspace(beg[l])) l++;
if (l == len) if (l == len)
return MUSTACH_ERROR_BAD_SEPARATORS; return MUSTACH_ERROR_BAD_SEPARATORS;
clstr = strndupa(beg + l, len - l); cllen = len - l;
oplen = strlen(opstr); tmp = alloca(cllen + 1);
cllen = strlen(clstr); memcpy(tmp, beg + l, cllen);
tmp[cllen] = 0;
clstr = tmp;
break; break;
case '^': case '^':
case '#': case '#':
/* begin section */ /* begin section */
if (depth == DEPTH_MAX) if (depth == DEPTH_MAX)
return MUSTACH_ERROR_TOO_DEPTH; return MUSTACH_ERROR_TOO_DEEP;
rc = emit; rc = emit;
if (rc) { if (rc) {
rc = itf->enter(closure, name); rc = itf->enter(closure, name);
@ -234,24 +308,15 @@ int mustach(const char *template, struct mustach_itf *itf, void *closure, char *
*result = NULL; *result = NULL;
if (size == NULL) if (size == NULL)
size = &s; size = &s;
file = open_memstream(result, size); file = memfile_open(result, size);
if (file == NULL) { if (file == NULL)
rc = MUSTACH_ERROR_SYSTEM; rc = MUSTACH_ERROR_SYSTEM;
errno = ENOMEM;
} else {
rc = fmustach(template, itf, closure, file);
if (rc == 0)
/* adds terminating null */
rc = fputc(0, file) ? MUSTACH_ERROR_SYSTEM : 0;
fclose(file);
if (rc >= 0)
/* removes terminating null of the length */
(*size)--;
else { else {
free(*result); rc = fmustach(template, itf, closure, file);
*result = NULL; if (rc < 0)
*size = 0; memfile_abort(file, result, size);
} else
rc = memfile_close(file, result, size);
} }
return rc; return rc;
} }

View file

@ -29,12 +29,17 @@
* *
* The functions enter and next should return 0 or 1. * The functions enter and next should return 0 or 1.
* *
* All other functions should normally return 0. * All other functions should normally return 0. If it returns
* a negative value, it means an error that stop the process
* and that is reported to the caller.
* *
* @start: Starts the mustach processing of the closure * @start: Starts the mustach processing of the closure
* 'start' is optional (can be NULL) * 'start' is optional (can be NULL)
* *
* @put: Writes the value of 'name' to 'file' with 'escape' or not * @put: Writes the value of 'name' to 'file' with 'escape' or not
* As an extension (see NO_ALLOW_EMPTY_TAG), the 'name' can be
* the empty string. In that later case an implemntation can
* return MUSTACH_ERROR_EMPTY_TAG to refuse empty names.
* *
* @enter: Enters the section of 'name' if possible. * @enter: Enters the section of 'name' if possible.
* Musts return 1 if entered or 0 if not entered. * Musts return 1 if entered or 0 if not entered.
@ -64,14 +69,17 @@ struct mustach_itf {
#define MUSTACH_ERROR_EMPTY_TAG -3 #define MUSTACH_ERROR_EMPTY_TAG -3
#define MUSTACH_ERROR_TAG_TOO_LONG -4 #define MUSTACH_ERROR_TAG_TOO_LONG -4
#define MUSTACH_ERROR_BAD_SEPARATORS -5 #define MUSTACH_ERROR_BAD_SEPARATORS -5
#define MUSTACH_ERROR_TOO_DEPTH -6 #define MUSTACH_ERROR_TOO_DEEP -6
#define MUSTACH_ERROR_CLOSING -7 #define MUSTACH_ERROR_CLOSING -7
#define MUSTACH_ERROR_BAD_UNESCAPE_TAG -8 #define MUSTACH_ERROR_BAD_UNESCAPE_TAG -8
/* compatibility with older bad name */
#define MUSTACH_ERROR_TOO_DEPTH MUSTACH_ERROR_TOO_DEEP
/** /**
* fmustach - Renders the mustache 'template' in 'file' for 'itf' and 'closure'. * fmustach - Renders the mustache 'template' in 'file' for 'itf' and 'closure'.
* *
* @template: the template string to instantiate * @template: the template string to instanciate
* @itf: the interface to the functions that mustach calls * @itf: the interface to the functions that mustach calls
* @closure: the closure to pass to functions called * @closure: the closure to pass to functions called
* @file: the file where to write the result * @file: the file where to write the result
@ -84,7 +92,7 @@ extern int fmustach(const char *template, struct mustach_itf *itf, void *closure
/** /**
* fmustach - Renders the mustache 'template' in 'fd' for 'itf' and 'closure'. * fmustach - Renders the mustache 'template' in 'fd' for 'itf' and 'closure'.
* *
* @template: the template string to instantiate * @template: the template string to instanciate
* @itf: the interface to the functions that mustach calls * @itf: the interface to the functions that mustach calls
* @closure: the closure to pass to functions called * @closure: the closure to pass to functions called
* @fd: the file descriptor number where to write the result * @fd: the file descriptor number where to write the result
@ -97,7 +105,7 @@ extern int fdmustach(const char *template, struct mustach_itf *itf, void *closur
/** /**
* fmustach - Renders the mustache 'template' in 'result' for 'itf' and 'closure'. * fmustach - Renders the mustache 'template' in 'result' for 'itf' and 'closure'.
* *
* @template: the template string to instantiate * @template: the template string to instanciate
* @itf: the interface to the functions that mustach calls * @itf: the interface to the functions that mustach calls
* @closure: the closure to pass to functions called * @closure: the closure to pass to functions called
* @result: the pointer receiving the result when 0 is returned * @result: the pointer receiving the result when 0 is returned