From c5e75352f27a02501b3a1a9189f10a581c12e7fb Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Mon, 24 Dec 2012 20:10:27 +0100 Subject: block-parser: Add support for custom block functions Similar to replace-table custom functions, this brings an ability to register custom block functions that can be called from templates with variable arguments. The syntax is as follows: ... An optional exclamation mark before the function name reverts the result (negates) the predicate. This allows template flexibility with respect to the currently processed image. --- src/replace-table.c | 83 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 27 deletions(-) (limited to 'src/replace-table.c') diff --git a/src/replace-table.c b/src/replace-table.c index 3398bae..9c1b254 100644 --- a/src/replace-table.c +++ b/src/replace-table.c @@ -209,38 +209,64 @@ parse_function_args (const char *str, GPtrArray *a) add_arg (a, str_start, str + i - str_start); } -static gboolean -parse_registered_function (const char *token, gchar **out_fname, gchar ***args) +/* + * parse_function: returns name of the function or NULL if token is invalid. Parsed arguments are stored in *args. + * - in case an exclamation mark is present before the function name, the *negation argument is set to TRUE + * + */ +gchar * +parse_function (const char *token, gchar ***args, gboolean *negation) { char *opening_p, *closing_p; GPtrArray *a; + gchar *tok; gchar *s; + gchar *fname; - g_return_val_if_fail (token != NULL, FALSE); - g_return_val_if_fail (out_fname != NULL, FALSE); + if (args) + *args = NULL; + if (negation) + *negation = FALSE; - opening_p = strchr (token, '('); - closing_p = strchr (token, ')'); + g_return_val_if_fail (token != NULL, NULL); + + tok = g_strdup (token); + g_strstrip (tok); + opening_p = strchr (tok, '('); + closing_p = strrchr (tok, ')'); /* every function call should contain an opening and closing parenthesis */ - if (opening_p == NULL || closing_p == NULL || closing_p <= opening_p) - return FALSE; + if (opening_p == NULL || closing_p == NULL || closing_p <= opening_p) { + g_free (tok); + return NULL; + } + + /* find a possible exclamation mark */ + if (*tok == '!') { + if (negation) + *negation = TRUE; + *tok = ' '; + } /* find function name */ - s = g_strndup (token, opening_p - token); - *out_fname = g_strdup (g_strstrip (s)); + s = g_strndup (tok, opening_p - tok); + fname = g_strdup (g_strstrip (s)); g_free (s); /* parse arguments */ - a = g_ptr_array_new (); - s = g_strndup (opening_p + 1, closing_p - opening_p - 1); - parse_function_args (s, a); - g_free (s); + if (args) { + a = g_ptr_array_new (); + s = g_strndup (opening_p + 1, closing_p - opening_p - 1); + parse_function_args (s, a); + g_free (s); - g_ptr_array_add (a, NULL); - *args = (gchar **) g_ptr_array_free (a, FALSE); + g_ptr_array_add (a, NULL); + *args = (gchar **) g_ptr_array_free (a, FALSE); + } + + g_free (tok); - return TRUE; + return fname; } /* @@ -289,15 +315,18 @@ replace_table_process (gchar **buffer, ReplaceTable *table) } /* check registered functions */ - if (! replace_value && parse_registered_function (token, &s, &args)) { - func_data = g_hash_table_lookup (table->functions, s); - g_free (s); - if (func_data) { - replace_value = func_data->callback (args, func_data->user_data); - if (replace_value == NULL) - replace_value = g_strdup (""); + if (! replace_value) { + s = parse_function (token, &args, NULL); + if (s) { + func_data = g_hash_table_lookup (table->functions, s); + if (func_data) { + replace_value = func_data->callback (args, func_data->user_data); + if (replace_value == NULL) + replace_value = g_strdup (""); + } + g_strfreev (args); + g_free (s); } - g_strfreev (args); } /* lookup in the replace table */ @@ -437,12 +466,12 @@ extract_token_arg (const gchar *str) const gchar *start; const gchar *end; - start = strstr (str, "("); + start = strchr (str, '('); if (start == NULL) return NULL; start++; - end = strstr (str, ")"); + end = strrchr (str, ')'); if (end == NULL) return NULL; end++; -- cgit v1.2.3