<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="generator" content="Osso Notes">
    <title></title></head>
<body>
<p>----- Original message -----
<br>&gt; This implements very basic support for type hinting template strings,
<br>&gt; where those hints will be available to value-pairs too, allowing any
<br>&gt; user of either LogTemplate or value-pairs to handle different types of
<br>&gt; values than plain strings. How they handle it, is up to the callers,
<br>&gt; this patch just lays the groundwork that makes it possible to pass
<br>&gt; these hints around.
<br>&gt; 
<br>&gt; There are a few not terribly nice solutions here, namely that the type
<br>&gt; information is encoded into the first byte of the value we store while
<br>&gt; building the value-pairs set: we do this to avoid having to allocate
<br>&gt; memory separately: we'll just reuse a byte from a ScratchBuffer. This,
<br>&gt; however, is done behind the scenes, the callback functions will get
<br>&gt; the type and value information separately.
<br>&gt; 
<br>&gt; Signed-off-by: Gergely Nagy &lt;<a href="mailto:algernon@balabit.hu">algernon@balabit.hu</a>&gt;
<br>&gt; ---
<br>&gt;&nbsp; &#32;lib/cfg-grammar.y&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;|&nbsp; &nbsp; &#32;41 ++++++++++++++++++++++---
<br>&gt;&nbsp; &#32;lib/cfg-lexer.h&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;|&nbsp; &nbsp; &nbsp; &#32;5 +++
<br>&gt;&nbsp; &#32;lib/filter-expr-grammar.ym&nbsp; &nbsp; &nbsp; &#32;|&nbsp; &nbsp; &#32;18 ++++++++---
<br>&gt;&nbsp; &#32;lib/templates.c&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;|&nbsp; &nbsp; &#32;28 +++++++++++++++++
<br>&gt;&nbsp; &#32;lib/templates.h&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;|&nbsp; &nbsp; &#32;13 ++++++++
<br>&gt;&nbsp; &#32;lib/value-pairs.c&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;|&nbsp; &nbsp; &#32;67
<br>&gt; +++++++++++++++++++++++++++++++++-------- lib/value-pairs.h&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; |&nbsp; &nbsp; &nbsp; &#32;8 +++-- modules/afamqp/afamqp.c&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;|&nbsp; &nbsp; &nbsp; &#32;3 +-
<br>&gt;&nbsp; &#32;modules/afmongodb/afmongodb.c |&nbsp; &nbsp; &nbsp; &#32;2 +-
<br>&gt;&nbsp; &#32;modules/json/format-json.c&nbsp; &nbsp; &nbsp; &#32;|&nbsp; &nbsp; &nbsp; &#32;3 +-
<br>&gt;&nbsp; &#32;tests/unit/test_value_pairs.c |&nbsp; &nbsp; &nbsp; &#32;6 ++--
<br>&gt;&nbsp; &#32;11 files changed, 164 insertions(+), 30 deletions(-)
<br>&gt; 
<br>&gt; diff --git a/lib/cfg-grammar.y b/lib/cfg-grammar.y
<br>&gt; index f45d486..a275aa6 100644
<br>&gt; --- a/lib/cfg-grammar.y
<br>&gt; +++ b/lib/cfg-grammar.y
<br>&gt; @@ -370,6 +370,8 @@ ValuePairsTransformSet *last_vp_transset;
<br>&gt;&nbsp; &#32;%type&nbsp;&nbsp;&nbsp; &lt;ptr&gt; dest_item
<br>&gt;&nbsp; &#32;%type&nbsp; &nbsp; &#32;&lt;ptr&gt; dest_plugin
<br>&gt;&nbsp; &#32;
<br>&gt; +%type&nbsp; &nbsp; &#32;&lt;tpl&gt; template_content
<br>&gt; +
<br>&gt;&nbsp; &#32;%type&nbsp; &nbsp; &#32;&lt;ptr&gt; filter_content
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;%type&nbsp; &nbsp; &#32;&lt;ptr&gt; parser_content
<br>&gt; @@ -709,12 +711,23 @@ template_items
<br>&gt;&nbsp; &#32;&nbsp;&nbsp;&nbsp; |
<br>&gt;&nbsp; &#32;&nbsp;&nbsp;&nbsp; ;
<br>&gt;&nbsp; &#32;
<br>&gt; +/* START_RULES */
<br>&gt; +
<br>&gt; +template_content
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;: string&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;{ $$.str = $1; $$.typehint =
<br>&gt; NULL; } +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;| LL_IDENTIFIER '(' string ')'&nbsp; &nbsp; &#32;{ $$.str = $3;
<br>&gt; $$.typehint = $1; } +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;;
<br>&gt; +
<br>
<br>can't we move template compilation here somehow? e.g. return logtemplate as a ptr?
<br>
<br>&gt; +/* END_RULES */
<br>&gt; +
<br>&gt;&nbsp; &#32;template_item
<br>&gt; -&nbsp;&nbsp;&nbsp; : KW_TEMPLATE '(' string ')'&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<br>&gt; +&nbsp;&nbsp;&nbsp; : KW_TEMPLATE '(' template_content ')'&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;GError *error = NULL;
<br>&gt;&nbsp; &#32;
<br>&gt; -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; CHECK_ERROR(log_template_compile(last_template, $3, &amp;error), @3, "Error
<br>&gt; compiling template (%s)", error-&gt;message); -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;free($3); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;CHECK_ERROR(log_template_compile(last_template, $3.str,
<br>&gt; &amp;error), @3, "Error compiling template (%s)", error-&gt;message); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;free($3.str); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; CHECK_ERROR(log_template_set_type_hint(last_template, $3.typehint,
<br>&gt; &amp;error), @3, "Error setting the template type-hint (%s)",
<br>&gt; error-&gt;message); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; g_free($3.typehint);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;} 
<br>
<br>that way this code would be there
<br>
<br>&gt; &nbsp;&nbsp;&nbsp; | KW_TEMPLATE_ESCAPE '(' yesno ')'&nbsp;&nbsp;&nbsp; {
<br>&gt; log_template_set_escape(last_template, $3); } &nbsp;&nbsp;&nbsp; ; @@ -1065,8 +1078,26 @@
<br>&gt; vp_options &nbsp;&nbsp;&nbsp; ;&nbsp; &#32;vp_option -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;: KW_PAIR '(' string ':' string ')'&nbsp; &nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &#32;{ value_pairs_add_pair(last_value_pairs, configuration, $3, $5);
<br>&gt; free($3); free($5); } -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;| KW_PAIR '(' string string ')'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; { value_pairs_add_pair(last_value_pairs, configuration, $3, $4);
<br>&gt; free($3); free($4); } +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;: KW_PAIR '(' string ':' template_content
<br>&gt; ')' +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;{ +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;GError *error = NULL; + +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; CHECK_ERROR(value_pairs_add_pair_with_type(last_value_pairs,
<br>&gt; configuration, $3, $5.typehint, $5.str, &amp;error), +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; @5, "Error processing value-pair (%s)", error-&gt;message); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; free($3); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_free($5.typehint); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;free($5.str);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;}
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;| KW_PAIR '(' string template_content ')'
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;{
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;GError *error = NULL;
<br>&gt; +
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;CHECK_ERROR(value_pairs_add_pair_with_type(last_value_pairs,
<br>&gt; configuration, $3, $4.typehint, $4.str, &amp;error), +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; @4, "Error processing value-pair (%s)", error-&gt;message); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; free($3); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_free($4.typehint);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;free($4.str);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;}
<br>
<br>and these dupes would be gone.
<br>
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;| KW_KEY '(' string KW_REKEY '('
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;last_vp_transset = value_pairs_transform_set_new($3);
<br>&gt; diff --git a/lib/cfg-lexer.h b/lib/cfg-lexer.h
<br>&gt; index 03c8a61..2030b66 100644
<br>&gt; --- a/lib/cfg-lexer.h
<br>&gt; +++ b/lib/cfg-lexer.h
<br>&gt; @@ -65,6 +65,11 @@ typedef struct YYSTYPE
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;char *cptr;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;void *ptr;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gpointer node;
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;struct
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;{
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gchar *str;
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gchar *typehint;
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;} tpl;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;};
<br>&gt;&nbsp; &#32;} YYSTYPE;
<br>&gt;&nbsp; &#32;#define YYSTYPE_IS_TRIVIAL 1
<br>&gt; diff --git a/lib/filter-expr-grammar.ym b/lib/filter-expr-grammar.ym
<br>&gt; index 1efa651..0a61df2 100644
<br>&gt; --- a/lib/filter-expr-grammar.ym
<br>&gt; +++ b/lib/filter-expr-grammar.ym
<br>&gt; @@ -174,7 +174,7 @@ filter_simple_expr
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;}
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;$$ = node;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;}
<br>&gt; -&nbsp;&nbsp;&nbsp; | string operator string
<br>&gt; +&nbsp;&nbsp;&nbsp; | template_content operator template_content
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;LogTemplate *left, *right;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;GError *error = NULL;
<br>&gt; @@ -182,13 +182,21 @@ filter_simple_expr
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;left = log_template_new(configuration, NULL);
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;right = log_template_new(configuration, NULL);
<br>&gt; -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;success_left = log_template_compile(left, $1, &amp;error);
<br>&gt; -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;success_right = log_template_compile(right, $3, &amp;error);
<br>&gt; -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;free($1);
<br>&gt; -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;free($3);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;success_left = log_template_compile(left, $1.str, &amp;error);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;success_right = log_template_compile(right, $3.str, &amp;error);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;free($1.str);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;free($3.str);
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;CHECK_ERROR(success_left, @1, "error compiling template:
<br>&gt; %s", error-&gt;message);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;CHECK_ERROR(success_right, @3, "error
<br>&gt; compiling template: %s", error-&gt;message); 
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;CHECK_ERROR(log_template_set_type_hint(left, $1.typehint,
<br>&gt; &amp;error), @1, "error setting type hint on template: %s", error-&gt;message);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;CHECK_ERROR(log_template_set_type_hint(right, $3.typehint,
<br>&gt; &amp;error), @3, "error setting type hint on template: %s", error-&gt;message);
<br>&gt; + +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;CHECK_ERROR(left-&gt;type_hint == right-&gt;type_hint, @$,
<br>&gt; "template types (%s &lt;-&gt; %s) do not match", $1.typehint, $3.typehint); +
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_free($1.typehint); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_free($3.typehint);
<br>&gt; +
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;$$ = fop_cmp_new(left, right, $2);
<br>
<br>most of these would be gone too.
<br>
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;}
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;;
<br>&gt; diff --git a/lib/templates.c b/lib/templates.c
<br>&gt; index f62f8b8..9be8110 100644
<br>&gt; --- a/lib/templates.c
<br>&gt; +++ b/lib/templates.c
<br>&gt; @@ -886,6 +886,34 @@ parse_msg_ref(gchar **p, gint *msg_ref)
<br>&gt;&nbsp; &#32;}
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;gboolean
<br>&gt; +log_template_set_type_hint(LogTemplate *self, const gchar *hint, GError
<br>&gt; **error) +{
<br>&gt; +&nbsp; &#32;if (hint == NULL)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;return TRUE;
<br>&gt; +
<br>&gt; +&nbsp; &#32;if (strcmp(hint, "string") == 0)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;self-&gt;type_hint = TEMPLATE_TYPE_STRING;
<br>&gt; +&nbsp; &#32;else if (strcmp(hint, "int32") == 0 || strcmp(hint, "int") == 0)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;self-&gt;type_hint = TEMPLATE_TYPE_INT32;
<br>&gt; +&nbsp; &#32;else if (strcmp(hint, "int64") == 0)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;self-&gt;type_hint = TEMPLATE_TYPE_INT64;
<br>&gt; +&nbsp; &#32;else if (strcmp(hint, "datetime") == 0)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;self-&gt;type_hint = TEMPLATE_TYPE_DATETIME;
<br>&gt; +&nbsp; &#32;else if (strcmp(hint, "boolean") == 0)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;self-&gt;type_hint = TEMPLATE_TYPE_BOOLEAN;
<br>&gt; +&nbsp; &#32;else if (strcmp(hint, "default") == 0)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;self-&gt;type_hint = TEMPLATE_TYPE_DEFAULT;
<br>&gt; +&nbsp; &#32;else
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;{
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_set_error(error, LOG_TEMPLATE_ERROR, LOG_TEMPLATE_ERROR_TYPE,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;"%s", hint);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;return FALSE;
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;}
<br>&gt; +
<br>&gt; +&nbsp; &#32;return TRUE;
<br>&gt; +}
<br>
<br>I'm thinking about whether it'd make sense to configure this at runtime, and whether the list of supported values could be destination specific.
<br>
<br>&gt; +
<br>&gt; +gboolean
<br>&gt;&nbsp; &#32;log_template_compile(LogTemplate *self, const gchar *template, GError
<br>&gt; **error) {
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;gchar *start, *p;
<br>&gt; diff --git a/lib/templates.h b/lib/templates.h
<br>&gt; index ed5b688..f3ad226 100644
<br>&gt; --- a/lib/templates.h
<br>&gt; +++ b/lib/templates.h
<br>&gt; @@ -40,8 +40,19 @@ enum LogTemplateError
<br>&gt;&nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;LOG_TEMPLATE_ERROR_FAILED,
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;LOG_TEMPLATE_ERROR_COMPILE,
<br>&gt; +&nbsp; &#32;LOG_TEMPLATE_ERROR_TYPE,
<br>&gt;&nbsp; &#32;};
<br>&gt;&nbsp; &#32;
<br>&gt; +typedef enum
<br>&gt; +{
<br>&gt; +&nbsp; &#32;TEMPLATE_TYPE_STRING,
<br>&gt; +&nbsp; &#32;TEMPLATE_TYPE_BOOLEAN,
<br>&gt; +&nbsp; &#32;TEMPLATE_TYPE_INT32,
<br>&gt; +&nbsp; &#32;TEMPLATE_TYPE_INT64,
<br>&gt; +&nbsp; &#32;TEMPLATE_TYPE_DATETIME,
<br>&gt; +&nbsp; &#32;TEMPLATE_TYPE_DEFAULT,
<br>&gt; +} LogTemplateType;
<br>&gt; +
<br>
<br>default is somehow an exception here.
<br>
<br>&gt;&nbsp; &#32;/* structure that represents an expandable syslog-ng template */
<br>&gt;&nbsp; &#32;typedef struct _LogTemplate
<br>&gt;&nbsp; &#32;{
<br>&gt; @@ -54,6 +65,7 @@ typedef struct _LogTemplate
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;GlobalConfig *cfg;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;GStaticMutex arg_lock;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;GPtrArray *arg_bufs;
<br>&gt; +&nbsp; &#32;LogTemplateType type_hint;
<br>&gt;&nbsp; &#32;} LogTemplate;
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;/* template expansion options that can be influenced by the user and
<br>&gt; @@ -189,6 +201,7 @@ void tf_simple_func_free_state(gpointer state);
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;void log_template_set_escape(LogTemplate *self, gboolean enable);
<br>&gt;&nbsp; &#32;gboolean log_template_compile(LogTemplate *self, const gchar *template,
<br>&gt; GError **error); +gboolean log_template_set_type_hint(LogTemplate *self,
<br>&gt; const gchar *hint, GError **error); void log_template_format(LogTemplate
<br>&gt; *self, LogMessage *lm, LogTemplateOptions *opts, gint tz, gint32
<br>&gt; seq_num, const gchar *context_id, GString *result); void
<br>&gt; log_template_append_format(LogTemplate *self, LogMessage *lm,
<br>&gt; LogTemplateOptions *opts, gint tz, gint32 seq_num, const gchar
<br>&gt; *context_id, GString *result); void
<br>&gt; log_template_append_format_with_context(LogTemplate *self, LogMessage
<br>&gt; **messages, gint num_messages, LogTemplateOptions *opts, gint tz, gint32
<br>&gt; seq_num, const gchar *context_id, GString *result); diff --git
<br>&gt; a/lib/value-pairs.c b/lib/value-pairs.c index ee22b73..da2e391 100644
<br>&gt; --- a/lib/value-pairs.c +++ b/lib/value-pairs.c @@ -151,16 +151,30 @@
<br>&gt; value_pairs_add_glob_pattern(ValuePairs *vp, const gchar *pattern,&nbsp; &#32;
<br>&gt; vp-&gt;patterns[i] = p; }&nbsp; &#32;-void -value_pairs_add_pair(ValuePairs *vp,
<br>&gt; GlobalConfig *cfg, const gchar *key, const gchar *value) +gboolean
<br>&gt; +value_pairs_add_pair_with_type(ValuePairs *vp, GlobalConfig *cfg,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;const gchar *key, const gchar *type,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;const gchar *value, GError **error)
<br>&gt;&nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;VPPairConf *p = g_new(VPPairConf, 1);
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;p-&gt;name = g_strdup(key);
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;p-&gt;template = log_template_new(cfg, NULL);
<br>&gt; -&nbsp; &#32;log_template_compile(p-&gt;template, value, NULL);
<br>&gt; +&nbsp; &#32;log_template_compile(p-&gt;template, value, error);
<br>&gt; +&nbsp; &#32;if (error &amp;&amp; *error)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;return FALSE;
<br>&gt; +&nbsp; &#32;log_template_set_type_hint(p-&gt;template, type, error);
<br>&gt; +&nbsp; &#32;if (error &amp;&amp; *error)
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;return FALSE;
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;g_ptr_array_add(vp-&gt;vpairs, p);
<br>&gt; +&nbsp; &#32;return TRUE;
<br>&gt; +}
<br>&gt; +
<br>&gt; +void
<br>&gt; +value_pairs_add_pair(ValuePairs *vp, GlobalConfig *cfg, const gchar
<br>&gt; *key, const gchar *value) +{
<br>&gt; +&nbsp; &#32;value_pairs_add_pair_with_type(vp, cfg, key, NULL, value, NULL);
<br>&gt;&nbsp; &#32;}
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;static gchar *
<br>&gt; @@ -185,6 +199,13 @@ vp_transform_apply (ValuePairs *vp, gchar *key)
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;return ckey;
<br>&gt;&nbsp; &#32;}
<br>&gt;&nbsp; &#32;
<br>&gt; +static GString *
<br>&gt; +vp_pairs_typehint(GString *str, LogTemplateType type_hint)
<br>&gt; +{
<br>&gt; +&nbsp; &#32;g_string_append_printf(str, "%c", type_hint);
<br>&gt; +&nbsp; &#32;return str;
<br>&gt; +}
<br>&gt; +
<br>&gt;&nbsp; &#32;/* runs over the name-value pairs requested by the user (e.g. with
<br>&gt; value_pairs_add_pair) */ static void
<br>&gt;&nbsp; &#32;vp_pairs_foreach(gpointer data, gpointer user_data)
<br>&gt; @@ -196,10 +217,11 @@ vp_pairs_foreach(gpointer data, gpointer user_data)
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;ScratchBuffer *sb = scratch_buffer_acquire();
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;VPPairConf *vpc = (VPPairConf *)data;
<br>&gt;&nbsp; &#32;
<br>&gt; -&nbsp; &#32;log_template_format((LogTemplate *)vpc-&gt;template, msg, NULL,
<br>&gt; LTZ_LOCAL, -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;seq_num, NULL, sb_string(sb));
<br>&gt; +&nbsp; &#32;vp_pairs_typehint(sb_string(sb), vpc-&gt;template-&gt;type_hint);
<br>&gt; +&nbsp; &#32;log_template_append_format((LogTemplate *)vpc-&gt;template, msg, NULL,
<br>&gt; LTZ_LOCAL, +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;seq_num, NULL, sb_string(sb));
<br>&gt;&nbsp; &#32;
<br>&gt; -&nbsp; &#32;if (!sb_string(sb)-&gt;str[0])
<br>&gt; +&nbsp; &#32;if (sb_string(sb)-&gt;len == 0)
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;scratch_buffer_release(sb);
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;return;
<br>&gt; @@ -234,8 +256,13 @@ vp_msg_nvpairs_foreach(NVHandle handle, gchar *name,
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;(log_msg_is_handle_sdata(handle) &amp;&amp; (vp-&gt;scopes &amp; VPS_SDATA))) ||
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;inc)
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;{
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gchar *v = g_malloc(value_len + 2);
<br>&gt; +
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;/* NOTE: the key is a borrowed reference in the hash, and value
<br>&gt; is freed */ -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_tree_insert(scope_set, vp_transform_apply(vp,
<br>&gt; name), g_strndup(value, value_len)); +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;v[0] = 0;
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;strncpy(v + 1, value, value_len);
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;v[value_len + 1] = 0;
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_tree_insert(scope_set, vp_transform_apply(vp, name), v);
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;}
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;return FALSE;
<br>&gt; @@ -265,6 +292,7 @@ vp_merge_set(ValuePairs *vp, LogMessage *msg, gint32
<br>&gt; seq_num, ValuePairSpec *set&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;switch (set[i].type)
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;case VPT_MACRO:
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;vp_pairs_typehint(sb_string(sb), TEMPLATE_TYPE_STRING);
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;log_macro_expand(sb_string(sb), set[i].id, FALSE, NULL,
<br>&gt; LTZ_LOCAL, seq_num, NULL, msg);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;break;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;case VPT_NVPAIR:
<br>&gt; @@ -272,6 +300,7 @@ vp_merge_set(ValuePairs *vp, LogMessage *msg, gint32
<br>&gt; seq_num, ValuePairSpec *set&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;const gchar *nv;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gssize len;
<br>&gt;&nbsp; &#32;
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;vp_pairs_typehint(sb_string(sb), TEMPLATE_TYPE_STRING);
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;nv = log_msg_get_value(msg, (NVHandle) set[i].id, &amp;len);
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_string_append_len(sb_string(sb), nv, len);
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;break;
<br>&gt; @@ -280,7 +309,7 @@ vp_merge_set(ValuePairs *vp, LogMessage *msg, gint32
<br>&gt; seq_num, ValuePairSpec *set&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_assert_not_reached();
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;}
<br>&gt;&nbsp; &#32;
<br>&gt; -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;if (!sb_string(sb)-&gt;str[0])
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;if (sb_string(sb)-&gt;len == 0)
<br>&gt;&nbsp; &#32;&nbsp;&nbsp;&nbsp; continue;
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;g_tree_insert(dest, vp_transform_apply(vp, set[i].name),
<br>&gt; sb_string(sb)-&gt;str); @@ -289,12 +318,22 @@ vp_merge_set(ValuePairs *vp,
<br>&gt; LogMessage *msg, gint32 seq_num, ValuePairSpec *set&nbsp; &#32;
<br>&gt; scratch_buffer_release(sb); }
<br>&gt;&nbsp; &#32;
<br>&gt; +static gboolean
<br>&gt; +vp_foreach_helper (const gchar *name, const gchar *hinted_value,
<br>&gt; gpointer data) +{
<br>&gt; +&nbsp; &#32;VPForeachFunc func = ((gpointer *)data)[0];
<br>&gt; +&nbsp; &#32;gpointer user_data = ((gpointer *)data)[1];
<br>&gt; +
<br>&gt; +&nbsp; &#32;return func(name, (LogTemplateType)hinted_value[0], hinted_value + 1,
<br>&gt; user_data); +}
<br>&gt; +
<br>&gt;&nbsp; &#32;void
<br>&gt;&nbsp; &#32;value_pairs_foreach_sorted (ValuePairs *vp, VPForeachFunc func,
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;GCompareDataFunc compare_func,
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;LogMessage *msg, gint32 seq_num, gpointer
<br>&gt; user_data) {
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;gpointer args[] = { vp, func, msg, GINT_TO_POINTER (seq_num),
<br>&gt; user_data, NULL }; +&nbsp; &#32;gpointer helper_args[] = { func, user_data };
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;GTree *scope_set;
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;scope_set = g_tree_new_full((GCompareDataFunc)compare_func, NULL,
<br>&gt; @@ -326,7 +365,7 @@ value_pairs_foreach_sorted (ValuePairs *vp,
<br>&gt; VPForeachFunc func,&nbsp; &nbsp; &#32;g_ptr_array_foreach(vp-&gt;vpairs,
<br>&gt; (GFunc)vp_pairs_foreach, args); 
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;/* Aaand we run it through the callback! */
<br>&gt; -&nbsp; &#32;g_tree_foreach(scope_set, (GTraverseFunc)func, user_data);
<br>&gt; +&nbsp; &#32;g_tree_foreach(scope_set, (GTraverseFunc)vp_foreach_helper,
<br>&gt; helper_args); 
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;g_tree_destroy(scope_set);
<br>&gt;&nbsp; &#32;}
<br>&gt; @@ -481,7 +520,7 @@ vp_walker_name_split(vp_walk_stack_t **stack,
<br>&gt; vp_walk_state_t *state, }
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;static gboolean
<br>&gt; -value_pairs_walker(const gchar *name, const gchar *value,
<br>&gt; +value_pairs_walker(const gchar *name, LogTemplateType type, const gchar
<br>&gt; *value,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gpointer user_data)
<br>&gt;&nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;vp_walk_state_t *state = (vp_walk_state_t *)user_data;
<br>&gt; @@ -494,10 +533,14 @@ value_pairs_walker(const gchar *name, const gchar
<br>&gt; *value,&nbsp; &nbsp; &#32;key = vp_walker_name_split (&amp;st, state, name);
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;if (st)
<br>&gt; -&nbsp; &nbsp; &nbsp; &#32;result = state-&gt;process_value(key, st-&gt;prefix, value, &amp;st-&gt;data,
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;result = state-&gt;process_value(key, st-&gt;prefix,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;type, value,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;&amp;st-&gt;data,
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;state-&gt;user_data);
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;else
<br>&gt; -&nbsp; &nbsp; &nbsp; &#32;result = state-&gt;process_value(key, NULL, value, NULL,
<br>&gt; +&nbsp; &nbsp; &nbsp; &#32;result = state-&gt;process_value(key, NULL,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;type, value,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;NULL,
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;state-&gt;user_data);
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;g_free(key);
<br>&gt; diff --git a/lib/value-pairs.h b/lib/value-pairs.h
<br>&gt; index a6c9f34..0438d53 100644
<br>&gt; --- a/lib/value-pairs.h
<br>&gt; +++ b/lib/value-pairs.h
<br>&gt; @@ -27,12 +27,13 @@
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;#include "syslog-ng.h"
<br>&gt;&nbsp; &#32;#include "nvtable.h"
<br>&gt; +#include "templates.h"
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;typedef struct _ValuePairs ValuePairs;
<br>&gt; -typedef gboolean (*VPForeachFunc)(const gchar *name, const gchar
<br>&gt; *value, gpointer user_data); +typedef gboolean (*VPForeachFunc)(const
<br>&gt; gchar *name, LogTemplateType type, const gchar *value, gpointer
<br>&gt; user_data);&nbsp; &#32;typedef gboolean (*VPWalkValueCallbackFunc)(const gchar
<br>&gt; *name, const gchar *prefix, -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; const gchar *value, +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt; LogTemplateType type, const gchar *value,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gpointer *prefix_data, gpointer user_data); typedef
<br>&gt; gboolean (*VPWalkCallbackFunc)(const gchar *name,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;const gchar *prefix, gpointer *prefix_data, @@ -42,6
<br>&gt; +43,9 @@ typedef gboolean (*VPWalkCallbackFunc)(const gchar *name,
<br>&gt; gboolean value_pairs_add_scope(ValuePairs *vp, const gchar *scope); void
<br>&gt; value_pairs_add_glob_pattern(ValuePairs *vp, const gchar *pattern,
<br>&gt; gboolean include); void value_pairs_add_pair(ValuePairs *vp,
<br>&gt; GlobalConfig *cfg, const gchar *key, const gchar *value); +gboolean
<br>&gt; value_pairs_add_pair_with_type(ValuePairs *vp, GlobalConfig *cfg, +&nbsp; &nbsp; &nbsp; &nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;const gchar *key, const gchar *type, +
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;const gchar *value, GError
<br>&gt; **error);&nbsp; &#32;void value_pairs_add_transforms(ValuePairs *vp, gpointer
<br>&gt; vpts);&nbsp; &#32;diff --git a/modules/afamqp/afamqp.c b/modules/afamqp/afamqp.c
<br>&gt; index 70fd3e8..fb3a333 100644
<br>&gt; --- a/modules/afamqp/afamqp.c
<br>&gt; +++ b/modules/afamqp/afamqp.c
<br>&gt; @@ -374,7 +374,8 @@ afamqp_dd_connect(AMQPDestDriver *self, gboolean
<br>&gt; reconnect)&nbsp; &#32;*/
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;static gboolean
<br>&gt; -afamqp_vp_foreach(const gchar *name, const gchar *value,
<br>&gt; +afamqp_vp_foreach(const gchar *name,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;LogTemplateType type, const gchar *value,
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gpointer user_data)
<br>&gt;&nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;amqp_table_entry_t **entries = (amqp_table_entry_t **) ((gpointer
<br>&gt; *)user_data)[0]; diff --git a/modules/afmongodb/afmongodb.c
<br>&gt; b/modules/afmongodb/afmongodb.c index 9779097..5230d8f 100644
<br>&gt; --- a/modules/afmongodb/afmongodb.c
<br>&gt; +++ b/modules/afmongodb/afmongodb.c
<br>&gt; @@ -359,7 +359,7 @@ afmongodb_vp_obj_end(const gchar *name,
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;static gboolean
<br>&gt;&nbsp; &#32;afmongodb_vp_process_value(const gchar *name, const gchar *prefix,
<br>&gt; -&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;const gchar *value,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;LogTemplateType type, const gchar *value,
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gpointer *prefix_data, gpointer user_data)
<br>&gt;&nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;bson *o;
<br>&gt; diff --git a/modules/json/format-json.c b/modules/json/format-json.c
<br>&gt; index d654c2e..4b79701 100644
<br>&gt; --- a/modules/json/format-json.c
<br>&gt; +++ b/modules/json/format-json.c
<br>&gt; @@ -163,7 +163,8 @@ tf_json_obj_end(const gchar *name,
<br>&gt;&nbsp; &#32;}
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;static gboolean
<br>&gt; -tf_json_value(const gchar *name, const gchar *prefix, const gchar
<br>&gt; *value, +tf_json_value(const gchar *name, const gchar *prefix,
<br>&gt; +&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;LogTemplateType type, const gchar *value,
<br>&gt;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#32;gpointer *prefix_data, gpointer user_data)
<br>&gt;&nbsp; &#32;{
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;json_state_t *state = (json_state_t *)user_data;
<br>&gt; diff --git a/tests/unit/test_value_pairs.c
<br>&gt; b/tests/unit/test_value_pairs.c index ca4ba32..3fe09de 100644
<br>&gt; --- a/tests/unit/test_value_pairs.c
<br>&gt; +++ b/tests/unit/test_value_pairs.c
<br>&gt; @@ -10,7 +10,7 @@
<br>&gt;&nbsp; &#32;gboolean success = TRUE;
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &#32;gboolean
<br>&gt; -vp_keys_foreach(const gchar&nbsp; &#32;*name, const gchar *value, gpointer
<br>&gt; user_data) +vp_keys_foreach(const gchar&nbsp; &#32;*name, LogTemplateType type,
<br>&gt; const gchar *value, gpointer user_data) {
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;gpointer *args = (gpointer *) user_data;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;GList **keys = (GList **) args[0];
<br>&gt; @@ -123,7 +123,7 @@ main(int argc, char *argv[])
<br>&gt;&nbsp; &#32;
<br>&gt;&nbsp; &nbsp; &nbsp; &#32;testcase("all-nv-pairs", NULL,
<br>&gt; "<a href="mailto:.SDATA.EventData@18372.4.Data">.SDATA.EventData@18372.4.Data</a>,<a href="mailto:.SDATA.Keywords@18372.4.Keyword">.SDATA.Keywords@18372.4.Keyword</a>,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,HOST,MESSAGE,MSGID,PID,PROGRAM",
<br>&gt; NULL);&nbsp; &#32;-&nbsp; &#32;testcase("everything", NULL,
<br>&gt; "<a href="mailto:.SDATA.EventData@18372.4.Data">.SDATA.EventData@18372.4.Data</a>,<a href="mailto:.SDATA.Keywords@18372.4.Keyword">.SDATA.Keywords@18372.4.Keyword</a>,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,AMPM,BSDTAG,C_DATE,C_DAY,C_FULLDATE,C_HOUR,C_ISODATE,C_MIN,C_MONTH,C_MONTH_ABBREV,C_MONTH_NAME,C_MONTH_WEEK,C_SEC,C_STAMP,C_TZ,C_T ZOFFSET,C_UNIXTIME,C_WEEK,C_WEEKDAY,C_WEEK_DAY,C_WEEK_DAY_ABBREV,C_WEEK_DAY_NAME,C_YEAR,C_YEAR_DAY,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOUR,HOUR12,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONTH_NAME,MONTH_WEEK,MSEC,MSG,MSGHDR ,MSGID,PID,PRI,PRIORITY,PROGRAM,R_AMPM,R_DATE,R_DAY,R_FULLDATE,R_HOUR,R_HOUR12,R_ISODATE,R_MIN,R_MONTH,R_MONTH_ABBREV,R_MONTH_NAME,R_MONTH_WEEK,R_MSEC,R_SEC,R_STAMP,R_TZ,R_TZOFFSET,R_UNIXTIME,R_USEC,R_WEEK,R_WEEKDAY,R_WEEK_DAY,R_WEEK_DAY_ABBREV,R_WEEK_DAY_ NAME,R_YEAR,R_YEAR_DAY,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,SYSUPTIME,S_AMPM,S_DATE,S_DAY,S_FULLDATE,S_HOUR,S_HOUR12,S_ISODATE,S_MIN,S_MONTH,S_MONTH_ABBREV,S_MONTH_NAME,S_MONTH_WEEK,S_MSEC,S_SEC,S
<br>&gt; _STAMP,S
<br>&gt; _TZ,S_TZOFFSET,S_UNIXTIME,S_USEC,S_WEEK,S_WEEKDAY,S_WEEK_DAY,S_WEEK_DAY_ABBREV,S_WEEK_DAY_NAME,S_YEAR,S_YEAR_DAY,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,USEC,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY",
<br>&gt; NULL); +&nbsp; &#32;testcase("everything", NULL,
<br>&gt; "<a href="mailto:.SDATA.EventData@18372.4.Data">.SDATA.EventData@18372.4.Data</a>,<a href="mailto:.SDATA.Keywords@18372.4.Keyword">.SDATA.Keywords@18372.4.Keyword</a>,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,AMPM,BSDTAG,CONTEXT_ID,C_DATE,C_DAY,C_FULLDATE,C_HOUR,C_ISODATE,C_MIN,C_MONTH,C_MONTH_ABBREV,C_MONTH_NAME,C_MONTH_WEEK,C_SEC,C_STA MP,C_TZ,C_TZOFFSET,C_UNIXTIME,C_WEEK,C_WEEKDAY,C_WEEK_DAY,C_WEEK_DAY_ABBREV,C_WEEK_DAY_NAME,C_YEAR,C_YEAR_DAY,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOUR,HOUR12,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONTH_NAME,MONTH_WEEK,MSEC ,MSG,MSGHDR,MSGID,PID,PRI,PRIORITY,PROGRAM,R_AMPM,R_DATE,R_DAY,R_FULLDATE,R_HOUR,R_HOUR12,R_ISODATE,R_MIN,R_MONTH,R_MONTH_ABBREV,R_MONTH_NAME,R_MONTH_WEEK,R_MSEC,R_SEC,R_STAMP,R_TZ,R_TZOFFSET,R_UNIXTIME,R_USEC,R_WEEK,R_WEEKDAY,R_WEEK_DAY,R_WEEK_DAY_ABBREV, R_WEEK_DAY_NAME,R_YEAR,R_YEAR_DAY,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,SYSUPTIME,S_AMPM,S_DATE,S_DAY,S_FULLDATE,S_HOUR,S_HOUR12,S_ISODATE,S_MIN,S_MONTH,S_MONTH_ABBREV,S_MONTH_NAME,S_MONTH_WEEK,S_M
<br>&gt; SEC,S_SE
<br>&gt; C,S_STAMP,S_TZ,S_TZOFFSET,S_UNIXTIME,S_USEC,S_WEEK,S_WEEKDAY,S_WEEK_DAY,S_WEEK_DAY_ABBREV,S_WEEK_DAY_NAME,S_YEAR,S_YEAR_DAY,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,USEC,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY",
<br>&gt; NULL);&nbsp; &nbsp; &nbsp; &#32;testcase("nv-pairs", ".SDATA.*",
<br>&gt; "HOST,MESSAGE,MSGID,PID,PROGRAM", NULL);&nbsp; &#32;@@ -139,7 +139,7 @@ main(int
<br>&gt; argc, char *argv[])&nbsp; &nbsp; &#32;g_ptr_array_add(transformers,
<br>&gt; value_pairs_new_transform_shift(2));&nbsp; &nbsp; &#32;g_ptr_array_add(transformers,
<br>&gt; value_pairs_new_transform_replace("C_", "CC_")); 
<br>&gt; -&nbsp; &#32;testcase("everything", NULL,
<br>&gt; "<a href="mailto:.SDATA.EventData@18372.4.Data">.SDATA.EventData@18372.4.Data</a>,<a href="mailto:.SDATA.Keywords@18372.4.Keyword">.SDATA.Keywords@18372.4.Keyword</a>,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,AMPM,BSDTAG,CC_DATE,CC_DAY,CC_FULLDATE,CC_HOUR,CC_ISODATE,CC_MIN,CC_MONTH,CC_MONTH_ABBREV,CC_MONTH_NAME,CC_MONTH_WEEK,CC_SEC,CC_ST AMP,CC_TZ,CC_TZOFFSET,CC_UNIXTIME,CC_WEEK,CC_WEEKDAY,CC_WEEK_DAY,CC_WEEK_DAY_ABBREV,CC_WEEK_DAY_NAME,CC_YEAR,CC_YEAR_DAY,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOUR,HOUR12,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONTH_NAME,MONT H_WEEK,MSEC,MSG,MSGHDR,MSGID,PID,PRI,PRIORITY,PROGRAM,R_AMPM,R_DATE,R_DAY,R_FULLDATE,R_HOUR,R_HOUR12,R_ISODATE,R_MIN,R_MONTH,R_MONTH_ABBREV,R_MONTH_NAME,R_MONTH_WEEK,R_MSEC,R_SEC,R_STAMP,R_TZ,R_TZOFFSET,R_UNIXTIME,R_USEC,R_WEEK,R_WEEKDAY,R_WEEK_DAY,R_WEEK_ DAY_ABBREV,R_WEEK_DAY_NAME,R_YEAR,R_YEAR_DAY,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,SYSUPTIME,S_AMPM,S_DATE,S_DAY,S_FULLDATE,S_HOUR,S_HOUR12,S_ISODATE,S_MIN,S_MONTH,S_MONTH_ABBREV,S_MONTH_NAME,S_MON
<br>&gt; TH_WEEK,
<br>&gt; S_MSEC,S_SEC,S_STAMP,S_TZ,S_TZOFFSET,S_UNIXTIME,S_USEC,S_WEEK,S_WEEKDAY,S_WEEK_DAY,S_WEEK_DAY_ABBREV,S_WEEK_DAY_NAME,S_YEAR,S_YEAR_DAY,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,USEC,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY",
<br>&gt; transformers); +&nbsp; &#32;testcase("everything", NULL,
<br>&gt; "<a href="mailto:.SDATA.EventData@18372.4.Data">.SDATA.EventData@18372.4.Data</a>,<a href="mailto:.SDATA.Keywords@18372.4.Keyword">.SDATA.Keywords@18372.4.Keyword</a>,.SDATA.meta.sequenceId,.SDATA.meta.sysUpTime,.SDATA.origin.ip,AMPM,BSDTAG,CC_DATE,CC_DAY,CC_FULLDATE,CC_HOUR,CC_ISODATE,CC_MIN,CC_MONTH,CC_MONTH_ABBREV,CC_MONTH_NAME,CC_MONTH_WEEK,CC_SEC,CC_ST AMP,CC_TZ,CC_TZOFFSET,CC_UNIXTIME,CC_WEEK,CC_WEEKDAY,CC_WEEK_DAY,CC_WEEK_DAY_ABBREV,CC_WEEK_DAY_NAME,CC_YEAR,CC_YEAR_DAY,CONTEXT_ID,DATE,DAY,FACILITY,FACILITY_NUM,FULLDATE,HOST,HOUR,HOUR12,ISODATE,LEVEL,LEVEL_NUM,LOGHOST,MESSAGE,MIN,MONTH,MONTH_ABBREV,MONT H_NAME,MONTH_WEEK,MSEC,MSG,MSGHDR,MSGID,PID,PRI,PRIORITY,PROGRAM,R_AMPM,R_DATE,R_DAY,R_FULLDATE,R_HOUR,R_HOUR12,R_ISODATE,R_MIN,R_MONTH,R_MONTH_ABBREV,R_MONTH_NAME,R_MONTH_WEEK,R_MSEC,R_SEC,R_STAMP,R_TZ,R_TZOFFSET,R_UNIXTIME,R_USEC,R_WEEK,R_WEEKDAY,R_WEEK_ DAY,R_WEEK_DAY_ABBREV,R_WEEK_DAY_NAME,R_YEAR,R_YEAR_DAY,SDATA,SEC,SEQNUM,SOURCEIP,STAMP,SYSUPTIME,S_AMPM,S_DATE,S_DAY,S_FULLDATE,S_HOUR,S_HOUR12,S_ISODATE,S_MIN,S_MONTH,S_MONTH_ABBREV,S_MONTH
<br>&gt; _NAME,S_
<br>&gt; MONTH_WEEK,S_MSEC,S_SEC,S_STAMP,S_TZ,S_TZOFFSET,S_UNIXTIME,S_USEC,S_WEEK,S_WEEKDAY,S_WEEK_DAY,S_WEEK_DAY_ABBREV,S_WEEK_DAY_NAME,S_YEAR,S_YEAR_DAY,TAG,TAGS,TZ,TZOFFSET,UNIXTIME,USEC,WEEK,WEEKDAY,WEEK_DAY,WEEK_DAY_ABBREV,WEEK_DAY_NAME,YEAR,YEAR_DAY",
<br>&gt; transformers);&nbsp; &nbsp; &#32;g_ptr_array_free(transformers, TRUE);&nbsp; &nbsp; &nbsp; &#32;app_shutdown();
<br>&gt; -- 
<br>&gt; 1.7.10.4
<br>&gt; 
<br>&gt; 
<br>&gt; ______________________________________________________________________________
<br>&gt; Member info: <a href="https://lists.balabit.hu/mailman/listinfo/syslog-ng">https://lists.balabit.hu/mailman/listinfo/syslog-ng</a>
<br>&gt; Documentation:
<br>&gt; <a href="http://www.balabit.com/support/documentation/?product=syslog-ng">http://www.balabit.com/support/documentation/?product=syslog-ng</a> FAQ:
<br>&gt; <a href="http://www.balabit.com/wiki/syslog-ng-faq">http://www.balabit.com/wiki/syslog-ng-faq</a>
<br>&gt; 
<br><br></p>
</body>
</html>