summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2021-01-01 17:08:59 +0100
committerSébastien Helleu <flashcode@flashtux.org>2021-01-01 17:08:59 +0100
commitd413ccdf4fbab249084afa0b73393b947415d02c (patch)
tree69c771c9914e184ab917f891d7f371fe08ce33bf
parentdoc: update German auto-generated file (diff)
downloadweechat-d413ccdf4fbab249084afa0b73393b947415d02c.tar.xz
weechat-d413ccdf4fbab249084afa0b73393b947415d02c.zip
core: add indentation and colors in /eval debug output
-rw-r--r--ChangeLog.adoc2
-rw-r--r--src/core/wee-command.c39
-rw-r--r--src/core/wee-eval.c365
-rw-r--r--src/core/wee-eval.h4
-rw-r--r--tests/unit/core/test-core-eval.cpp230
5 files changed, 475 insertions, 165 deletions
diff --git a/ChangeLog.adoc b/ChangeLog.adoc
index f51509316..91363a566 100644
--- a/ChangeLog.adoc
+++ b/ChangeLog.adoc
@@ -20,7 +20,7 @@ https://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes]
New features::
- * core: display more verbose debug with two "-d" in command /eval
+ * core: improve debug in command /eval: display more verbose debug with two "-d", add indentation and colors
* core: add options "setvar" and "delvar" in command /buffer, rename option "localvar" to "listvar"
* core: add buffer local variable "completion_default_template" (evaluated) to override the value of option "weechat.completion.default_template" (issue #1600)
* core: add option "recreate" in command /filter
diff --git a/src/core/wee-command.c b/src/core/wee-command.c
index 860476f8a..7feef67b5 100644
--- a/src/core/wee-command.c
+++ b/src/core/wee-command.c
@@ -34,6 +34,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
+#include <regex.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -2016,6 +2017,36 @@ COMMAND_CALLBACK(debug)
}
/*
+ * Prints eval debug output.
+ */
+
+void
+command_eval_print_debug (const char *debug)
+{
+ regex_t regex;
+ char str_replace[1024], *string;
+
+ string = NULL;
+
+ if (string_regcomp (&regex, "(^|\n)( *)([0-9]+:)", REG_EXTENDED) == 0)
+ {
+ /* colorize debug ids and the following colon with delimiter color */
+ snprintf (str_replace, sizeof (str_replace),
+ "$1$2%s$3%s",
+ GUI_COLOR(GUI_COLOR_CHAT_DELIMITERS),
+ GUI_COLOR(GUI_COLOR_CHAT));
+ string = string_replace_regex (debug, &regex, str_replace, '$',
+ NULL, NULL);
+ regfree (&regex);
+ }
+
+ gui_chat_printf (NULL, "%s", (string) ? string : debug);
+
+ if (string)
+ free (string);
+}
+
+/*
* Callback for command "/eval": evaluates an expression and sends result to
* buffer.
*/
@@ -2024,7 +2055,7 @@ COMMAND_CALLBACK(eval)
{
int i, print_only, split_command, condition, debug, error;
char *result, *ptr_args, **commands, str_debug[32];
- const char **debug_output;
+ const char *debug_output;
struct t_hashtable *pointers, *options;
/* make C compiler happy */
@@ -2130,7 +2161,7 @@ COMMAND_CALLBACK(eval)
debug_output = hashtable_get (options,
"debug_output");
if (debug_output)
- gui_chat_printf (NULL, "%s", debug_output);
+ command_eval_print_debug (debug_output);
}
}
else
@@ -2158,7 +2189,7 @@ COMMAND_CALLBACK(eval)
debug_output = hashtable_get (options,
"debug_output");
if (debug_output)
- gui_chat_printf (NULL, "%s", debug_output);
+ command_eval_print_debug (debug_output);
}
}
string_free_split_command (commands);
@@ -2181,7 +2212,7 @@ COMMAND_CALLBACK(eval)
debug_output = hashtable_get (options,
"debug_output");
if (debug_output)
- gui_chat_printf (NULL, "%s", debug_output);
+ command_eval_print_debug (debug_output);
}
}
}
diff --git a/src/core/wee-eval.c b/src/core/wee-eval.c
index 8c6cb09ad..3ecf37c25 100644
--- a/src/core/wee-eval.c
+++ b/src/core/wee-eval.c
@@ -46,9 +46,21 @@
#include "../plugins/plugin.h"
-#define EVAL_DEBUG(level, msg, argz...) \
- if (eval_context->debug_level >= level) \
- eval_debug_message (eval_context, msg, ##argz);
+#define EVAL_DEBUG_MSG(level, msg, argz...) \
+ if (eval_context->debug_level >= level) \
+ { \
+ debug_id = ++(eval_context->debug_id); \
+ (eval_context->debug_depth)++; \
+ eval_debug_message_vargs (eval_context, debug_id, msg, ##argz); \
+ }
+
+#define EVAL_DEBUG_RESULT(level, result) \
+ if (eval_context->debug_level >= level) \
+ { \
+ eval_debug_message (eval_context, debug_id, 1, result); \
+ (eval_context->debug_depth)--; \
+ }
+
char *logical_ops[EVAL_NUM_LOGICAL_OPS] =
{ "||", "&&" };
@@ -73,17 +85,62 @@ char *eval_expression_condition (const char *expr,
*/
void
-eval_debug_message (struct t_eval_context *eval_context, char *message, ...)
+eval_debug_message (struct t_eval_context *eval_context, int debug_id,
+ int result, const char *message)
{
- weechat_va_format (message);
- if (!vbuffer)
- return;
+ int i;
+ char str_id[64];
+
+ if (*(eval_context->debug_output)[0])
+ string_dyn_concat (eval_context->debug_output, "\n", -1);
+
+ /* indentation */
+ for (i = 1; i < eval_context->debug_depth; i++)
+ {
+ string_dyn_concat (eval_context->debug_output, " ", -1);
+ }
+
+ /* debug id */
+ if (debug_id >= 0)
+ {
+ snprintf (str_id, sizeof (str_id), "%d:", debug_id);
+ string_dyn_concat (eval_context->debug_output, str_id, -1);
+ }
+
+ /* debug message */
+ if (result)
+ {
+ string_dyn_concat (eval_context->debug_output, "== ", -1);
+ if (message)
+ string_dyn_concat (eval_context->debug_output, "\"", -1);
+ string_dyn_concat (eval_context->debug_output,
+ (message) ? message : "null",
+ -1);
+ if (message)
+ string_dyn_concat (eval_context->debug_output, "\"", -1);
+ }
+ else
+ {
+ string_dyn_concat (eval_context->debug_output, message, -1);
+ }
+}
- if (*(eval_context->debug)[0])
- string_dyn_concat (eval_context->debug, "\n", -1);
- string_dyn_concat (eval_context->debug, vbuffer, -1);
- free (vbuffer);
+/*
+ * Adds a debug message in the debug output, with variable arguments.
+ */
+
+void
+eval_debug_message_vargs (struct t_eval_context *eval_context, int debug_id,
+ const char *message, ...)
+{
+ weechat_va_format (message);
+ if (vbuffer)
+ {
+ eval_debug_message (eval_context, debug_id, 0,
+ vbuffer);
+ free (vbuffer);
+ }
}
/*
@@ -122,14 +179,20 @@ eval_strstr_level (const char *string, const char *search,
int escape)
{
const char *ptr_string;
- int level, length_search;
+ int level, length_search, debug_id;
int length_prefix, length_prefix2, length_suffix, length_suffix2;
- EVAL_DEBUG(2, "eval_strstr_level(\"%s\", \"%s\", \"%s\", \"%s\", %d)",
- string, search, extra_prefix, extra_suffix, escape);
+ ptr_string = NULL;
+
+ debug_id = -1;
+ EVAL_DEBUG_MSG(2, "eval_strstr_level(\"%s\", \"%s\", \"%s\", \"%s\", %d)",
+ string, search, extra_prefix, extra_suffix, escape);
if (!string || !search)
- return NULL;
+ {
+ ptr_string = NULL;
+ goto end;
+ }
length_search = strlen (search);
@@ -177,15 +240,19 @@ eval_strstr_level (const char *string, const char *search,
else if ((level == 0)
&& (strncmp (ptr_string, search, length_search) == 0))
{
- return ptr_string;
+ goto end;
}
else
{
ptr_string++;
}
}
+ ptr_string = NULL;
+
+end:
+ EVAL_DEBUG_RESULT(2, ptr_string);
- return NULL;
+ return ptr_string;
}
/*
@@ -673,25 +740,30 @@ eval_hdata_get_value (struct t_hdata *hdata, void *pointer, const char *path,
{
char *value, *old_value, *var_name, str_value[128], *pos;
const char *ptr_value, *hdata_name, *ptr_var_name;
- int type;
+ int type, debug_id;
struct t_hashtable *hashtable;
- EVAL_DEBUG(1, "eval_hdata_get_value(\"%s\", 0x%lx, \"%s\")",
- hdata->name, pointer, path);
+ debug_id = -1;
+ EVAL_DEBUG_MSG(1, "eval_hdata_get_value(\"%s\", 0x%lx, \"%s\")",
+ hdata->name, pointer, path);
value = NULL;
var_name = NULL;
/* NULL pointer? return empty string */
if (!pointer)
- return strdup ("");
+ {
+ value = strdup ("");
+ goto end;
+ }
/* no path? just return current pointer as string */
if (!path || !path[0])
{
snprintf (str_value, sizeof (str_value),
"0x%lx", (unsigned long)pointer);
- return strdup (str_value);
+ value = strdup (str_value);
+ goto end;
}
/*
@@ -818,6 +890,8 @@ end:
if (var_name)
free (var_name);
+ EVAL_DEBUG_RESULT(1, value);
+
return value;
}
@@ -951,14 +1025,16 @@ eval_replace_vars_cb (void *data, const char *text)
struct t_eval_context *eval_context;
struct t_config_option *ptr_option;
struct t_gui_buffer *ptr_buffer;
- char str_value[512], *value;
- char *tmp;
+ char str_value[512], *value, *tmp;
const char *ptr_value;
- int length;
+ int length, debug_id;
+
+ value = NULL;
eval_context = (struct t_eval_context *)data;
- EVAL_DEBUG(1, "eval_replace_vars_cb(\"%s\")", text);
+ debug_id = -1;
+ EVAL_DEBUG_MSG(1, "eval_replace_vars_cb(\"%s\")", text);
/* 1. variable in hashtable "extra_vars" */
if (eval_context->extra_vars)
@@ -970,16 +1046,17 @@ eval_replace_vars_cb (void *data, const char *text)
{
tmp = strdup (ptr_value);
if (!tmp)
- return NULL;
+ goto end;
hashtable_remove (eval_context->extra_vars, text);
value = eval_replace_vars (tmp, eval_context);
hashtable_set (eval_context->extra_vars, text, tmp);
free (tmp);
- return value;
+ goto end;
}
else
{
- return strdup (ptr_value);
+ value = strdup (ptr_value);
+ goto end;
}
}
}
@@ -989,24 +1066,39 @@ eval_replace_vars_cb (void *data, const char *text)
* --> use with caution: the text must be safe!
*/
if (strncmp (text, "eval:", 5) == 0)
- return eval_replace_vars (text + 5, eval_context);
+ {
+ value = eval_replace_vars (text + 5, eval_context);
+ goto end;
+ }
/*
* 3. force evaluation of condition (recursive call)
* --> use with caution: the text must be safe!
*/
if (strncmp (text, "eval_cond:", 10) == 0)
- return eval_string_eval_cond (text + 10, eval_context);
+ {
+ value = eval_string_eval_cond (text + 10, eval_context);
+ goto end;
+ }
/* 4. convert escaped chars */
if (strncmp (text, "esc:", 4) == 0)
- return string_convert_escaped_chars (text + 4);
+ {
+ value = string_convert_escaped_chars (text + 4);
+ goto end;
+ }
if ((text[0] == '\\') && text[1] && (text[1] != '\\'))
- return string_convert_escaped_chars (text);
+ {
+ value = string_convert_escaped_chars (text);
+ goto end;
+ }
/* 5. hide chars: replace all chars by a given char/string */
if (strncmp (text, "hide:", 5) == 0)
- return eval_string_hide (text + 5);
+ {
+ value = eval_string_hide (text + 5);
+ goto end;
+ }
/*
* 6. cut chars:
@@ -1016,19 +1108,34 @@ eval_replace_vars_cb (void *data, const char *text)
* suffix when the string is cut
*/
if (strncmp (text, "cut:", 4) == 0)
- return eval_string_cut (text + 4, 0);
+ {
+ value = eval_string_cut (text + 4, 0);
+ goto end;
+ }
if (strncmp (text, "cutscr:", 7) == 0)
- return eval_string_cut (text + 7, 1);
+ {
+ value = eval_string_cut (text + 7, 1);
+ goto end;
+ }
/* 7. reverse string */
if (strncmp (text, "rev:", 4) == 0)
- return string_reverse (text + 4);
+ {
+ value = string_reverse (text + 4);
+ goto end;
+ }
if (strncmp (text, "revscr:", 7) == 0)
- return string_reverse_screen (text + 7);
+ {
+ value = string_reverse_screen (text + 7);
+ goto end;
+ }
/* 8. repeated string */
if (strncmp (text, "repeat:", 7) == 0)
- return eval_string_repeat (text + 7);
+ {
+ value = eval_string_repeat (text + 7);
+ goto end;
+ }
/*
* 9. length of string:
@@ -1039,87 +1146,129 @@ eval_replace_vars_cb (void *data, const char *text)
{
length = gui_chat_strlen (text + 7);
snprintf (str_value, sizeof (str_value), "%d", length);
- return strdup (str_value);
+ value = strdup (str_value);
+ goto end;
}
if (strncmp (text, "lengthscr:", 10) == 0)
{
length = gui_chat_strlen_screen (text + 10);
snprintf (str_value, sizeof (str_value), "%d", length);
- return strdup (str_value);
+ value = strdup (str_value);
+ goto end;
}
/* 10. regex group captured */
if (strncmp (text, "re:", 3) == 0)
- return eval_string_regex_group (text + 3, eval_context);
+ {
+ value = eval_string_regex_group (text + 3, eval_context);
+ goto end;
+ }
/* 11. color code */
if (strncmp (text, "color:", 6) == 0)
- return eval_string_color (text + 6);
+ {
+ value = eval_string_color (text + 6);
+ goto end;
+ }
/* 12. modifier */
if (strncmp (text, "modifier:", 9) == 0)
- return eval_string_modifier (text + 9);
+ {
+ value = eval_string_modifier (text + 9);
+ goto end;
+ }
/* 13. info */
if (strncmp (text, "info:", 5) == 0)
- return eval_string_info (text + 5);
+ {
+ value = eval_string_info (text + 5);
+ goto end;
+ }
/* 14. base_encode/base_decode */
if (strncmp (text, "base_encode:", 12) == 0)
- return eval_string_base_encode (text + 12);
+ {
+ value = eval_string_base_encode (text + 12);
+ goto end;
+ }
if (strncmp (text, "base_decode:", 12) == 0)
- return eval_string_base_decode (text + 12);
+ {
+ value = eval_string_base_decode (text + 12);
+ goto end;
+ }
/* 15. current date/time */
if ((strncmp (text, "date", 4) == 0) && (!text[4] || (text[4] == ':')))
- return eval_string_date (text + 4);
+ {
+ value = eval_string_date (text + 4);
+ goto end;
+ }
/* 16. environment variable */
if (strncmp (text, "env:", 4) == 0)
{
ptr_value = getenv (text + 4);
- if (ptr_value)
- return strdup (ptr_value);
+ value = strdup ((ptr_value) ? ptr_value : "");
+ goto end;
}
/* 17: ternary operator: if:condition?value_if_true:value_if_false */
if (strncmp (text, "if:", 3) == 0)
- return eval_string_if (text + 3, eval_context);
+ {
+ value = eval_string_if (text + 3, eval_context);
+ goto end;
+ }
/*
* 18. calculate the result of an expression
* (with number, operators and parentheses)
*/
if (strncmp (text, "calc:", 5) == 0)
- return calc_expression (text + 5);
+ {
+ value = calc_expression (text + 5);
+ goto end;
+ }
/* 19. option: if found, return this value */
if (strncmp (text, "sec.data.", 9) == 0)
{
ptr_value = hashtable_get (secure_hashtable_data, text + 9);
- return strdup ((ptr_value) ? ptr_value : "");
+ value = strdup ((ptr_value) ? ptr_value : "");
+ goto end;
}
config_file_search_with_string (text, NULL, NULL, &ptr_option, NULL);
if (ptr_option)
{
if (!ptr_option->value)
- return strdup ("");
+ {
+ value = strdup ("");
+ goto end;
+ }
switch (ptr_option->type)
{
case CONFIG_OPTION_TYPE_BOOLEAN:
- return strdup (CONFIG_BOOLEAN(ptr_option) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
+ value = strdup (CONFIG_BOOLEAN(ptr_option) ?
+ EVAL_STR_TRUE : EVAL_STR_FALSE);
+ goto end;
case CONFIG_OPTION_TYPE_INTEGER:
if (ptr_option->string_values)
- return strdup (ptr_option->string_values[CONFIG_INTEGER(ptr_option)]);
+ {
+ value = strdup (ptr_option->string_values[CONFIG_INTEGER(ptr_option)]);
+ goto end;
+ }
snprintf (str_value, sizeof (str_value),
"%d", CONFIG_INTEGER(ptr_option));
- return strdup (str_value);
+ value = strdup (str_value);
+ goto end;
case CONFIG_OPTION_TYPE_STRING:
- return strdup (CONFIG_STRING(ptr_option));
+ value = strdup (CONFIG_STRING(ptr_option));
+ goto end;
case CONFIG_OPTION_TYPE_COLOR:
- return strdup (gui_color_get_name (CONFIG_COLOR(ptr_option)));
+ value = strdup (gui_color_get_name (CONFIG_COLOR(ptr_option)));
+ goto end;
case CONFIG_NUM_OPTION_TYPES:
- return strdup ("");
+ value = strdup ("");
+ goto end;
}
}
@@ -1129,11 +1278,19 @@ eval_replace_vars_cb (void *data, const char *text)
{
ptr_value = hashtable_get (ptr_buffer->local_variables, text);
if (ptr_value)
- return strdup (ptr_value);
+ {
+ value = strdup (ptr_value);
+ goto end;
+ }
}
/* 21. hdata */
- return eval_string_hdata (text, eval_context);
+ value = eval_string_hdata (text, eval_context);
+
+end:
+ EVAL_DEBUG_RESULT(1, value);
+
+ return value;
}
/*
@@ -1147,8 +1304,10 @@ eval_replace_vars (const char *expr, struct t_eval_context *eval_context)
{
const char *no_replace_prefix_list[] = { "if:", NULL };
char *result;
+ int debug_id;
- EVAL_DEBUG(1, "eval_replace_vars(\"%s\")", expr);
+ debug_id = -1;
+ EVAL_DEBUG_MSG(1, "eval_replace_vars(\"%s\")", expr);
eval_context->recursion_count++;
@@ -1169,6 +1328,8 @@ eval_replace_vars (const char *expr, struct t_eval_context *eval_context)
eval_context->recursion_count--;
+ EVAL_DEBUG_RESULT(1, result);
+
return result;
}
@@ -1190,13 +1351,14 @@ char *
eval_compare (const char *expr1, int comparison, const char *expr2,
struct t_eval_context *eval_context)
{
- int rc, string_compare, length1, length2;
+ int rc, string_compare, length1, length2, debug_id;
regex_t regex;
double value1, value2;
- char *error;
+ char *error, *value;
- EVAL_DEBUG(1, "eval_compare(\"%s\", \"%s\", \"%s\")",
- expr1, comparisons[comparison], expr2);
+ debug_id = -1;
+ EVAL_DEBUG_MSG(1, "eval_compare(\"%s\", \"%s\", \"%s\")",
+ expr1, comparisons[comparison], expr2);
rc = 0;
string_compare = 0;
@@ -1309,7 +1471,11 @@ eval_compare (const char *expr1, int comparison, const char *expr2,
}
end:
- return strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
+ value = strdup ((rc) ? EVAL_STR_TRUE : EVAL_STR_FALSE);
+
+ EVAL_DEBUG_RESULT(1, value);
+
+ return value;
}
/*
@@ -1324,19 +1490,24 @@ char *
eval_expression_condition (const char *expr,
struct t_eval_context *eval_context)
{
- int logic, comp, length, level, rc;
+ int logic, comp, length, level, rc, debug_id;
const char *pos, *pos_end;
char *expr2, *sub_expr, *value, *tmp_value, *tmp_value2;
- EVAL_DEBUG(1, "eval_expression_condition(\"%s\")", expr);
+ debug_id = -1;
+ EVAL_DEBUG_MSG(1, "eval_expression_condition(\"%s\")", expr);
value = NULL;
+ expr2 = NULL;
if (!expr)
- return NULL;
+ goto end;
if (!expr[0])
- return strdup (expr);
+ {
+ value = strdup (expr);
+ goto end;
+ }
/* skip spaces at beginning of string */
while (expr[0] == ' ')
@@ -1344,7 +1515,10 @@ eval_expression_condition (const char *expr,
expr++;
}
if (!expr[0])
- return strdup (expr);
+ {
+ value = strdup (expr);
+ goto end;
+ }
/* skip spaces at end of string */
pos_end = expr + strlen (expr) - 1;
@@ -1355,7 +1529,7 @@ eval_expression_condition (const char *expr,
expr2 = string_strndup (expr, pos_end + 1 - expr);
if (!expr2)
- return NULL;
+ goto end;
/*
* search for a logical operator, and if one is found:
@@ -1530,6 +1704,8 @@ end:
if (expr2)
free (expr2);
+ EVAL_DEBUG_RESULT(1, value);
+
return value;
}
@@ -1562,20 +1738,23 @@ eval_replace_regex (const char *string, regex_t *regex, const char *replace,
struct t_eval_context *eval_context)
{
char *result, *result2, *str_replace;
- int length, length_replace, start_offset, i, rc, end;
+ int length, length_replace, start_offset, i, rc, end, debug_id;
int empty_replace_allowed;
struct t_eval_regex eval_regex;
- EVAL_DEBUG(1, "eval_replace_regex(\"%s\", 0x%lx, \"%s\")",
- string, regex, replace);
+ result = NULL;
+
+ debug_id = -1;
+ EVAL_DEBUG_MSG(1, "eval_replace_regex(\"%s\", 0x%lx, \"%s\")",
+ string, regex, replace);
if (!string || !regex || !replace)
- return NULL;
+ goto end;
length = strlen (string) + 1;
result = malloc (length);
if (!result)
- return NULL;
+ goto end;
snprintf (result, length, "%s", string);
eval_context->regex = &eval_regex;
@@ -1636,7 +1815,8 @@ eval_replace_regex (const char *string, regex_t *regex, const char *replace,
if (!result2)
{
free (result);
- return NULL;
+ result = NULL;
+ goto end;
}
result2[0] = '\0';
if (eval_regex.match[0].rm_so > 0)
@@ -1663,6 +1843,9 @@ eval_replace_regex (const char *string, regex_t *regex, const char *replace,
break;
}
+end:
+ EVAL_DEBUG_RESULT(1, result);
+
return result;
}
@@ -1712,7 +1895,7 @@ eval_expression (const char *expr, struct t_hashtable *pointers,
struct t_hashtable *extra_vars, struct t_hashtable *options)
{
struct t_eval_context context, *eval_context;
- int condition, rc, pointers_allocated, regex_allocated;
+ int condition, rc, pointers_allocated, regex_allocated, debug_id;
int ptr_window_added, ptr_buffer_added;
long number;
char *value, *error;
@@ -1760,7 +1943,9 @@ eval_expression (const char *expr, struct t_hashtable *pointers,
eval_context->regex = NULL;
eval_context->recursion_count = 0;
eval_context->debug_level = 0;
- eval_context->debug = NULL;
+ eval_context->debug_depth = 0;
+ eval_context->debug_id = 0;
+ eval_context->debug_output = NULL;
/*
* set window/buffer with pointer to current window/buffer
@@ -1839,12 +2024,13 @@ eval_expression (const char *expr, struct t_hashtable *pointers,
if (error && !error[0] && (number >= 1))
{
eval_context->debug_level = (int)number;
- eval_context->debug = string_dyn_alloc (256);
+ eval_context->debug_output = string_dyn_alloc (256);
}
}
}
- EVAL_DEBUG(1, "eval_expression(\"%s\")", expr);
+ debug_id = -1;
+ EVAL_DEBUG_MSG(1, "eval_expression(\"%s\")", expr);
/* evaluate expression */
if (condition)
@@ -1888,10 +2074,13 @@ eval_expression (const char *expr, struct t_hashtable *pointers,
free (regex);
}
- if (options && eval_context->debug)
- hashtable_set (options, "debug_output", *(eval_context->debug));
- if (eval_context->debug)
- string_dyn_free (eval_context->debug, 1);
+ EVAL_DEBUG_RESULT(1, value);
+
+ /* set debug in options hashtable */
+ if (options && eval_context->debug_output)
+ hashtable_set (options, "debug_output", *(eval_context->debug_output));
+ if (eval_context->debug_output)
+ string_dyn_free (eval_context->debug_output, 1);
return value;
}
diff --git a/src/core/wee-eval.h b/src/core/wee-eval.h
index 5b696f9b8..c76f8f2da 100644
--- a/src/core/wee-eval.h
+++ b/src/core/wee-eval.h
@@ -79,7 +79,9 @@ struct t_eval_context
struct t_eval_regex *regex; /* in case of replace with regex */
int recursion_count; /* to prevent infinite recursion */
int debug_level; /* 0: no debug, 1: debug, 2: extra */
- char **debug; /* not NULL if debug_level >= 1 */
+ int debug_depth; /* used for debug indentation */
+ int debug_id; /* operation id in debug output */
+ char **debug_output; /* string with debug output */
};
extern int eval_is_true (const char *value);
diff --git a/tests/unit/core/test-core-eval.cpp b/tests/unit/core/test-core-eval.cpp
index da4a6af83..08ede271c 100644
--- a/tests/unit/core/test-core-eval.cpp
+++ b/tests/unit/core/test-core-eval.cpp
@@ -282,13 +282,20 @@ TEST(CoreEval, EvalCondition)
hashtable_set (options, "debug", "1");
WEE_CHECK_EVAL("1", "abc < def");
ptr_debug_output = (const char *)hashtable_get (options, "debug_output");
- STRCMP_EQUAL("eval_expression(\"abc < def\")\n"
- "eval_expression_condition(\"abc < def\")\n"
- "eval_expression_condition(\"abc\")\n"
- "eval_replace_vars(\"abc\")\n"
- "eval_expression_condition(\"def\")\n"
- "eval_replace_vars(\"def\")\n"
- "eval_compare(\"abc\", \"<\", \"def\")",
+ STRCMP_EQUAL("1:eval_expression(\"abc < def\")\n"
+ " 2:eval_expression_condition(\"abc < def\")\n"
+ " 3:eval_expression_condition(\"abc\")\n"
+ " 4:eval_replace_vars(\"abc\")\n"
+ " 4:== \"abc\"\n"
+ " 3:== \"abc\"\n"
+ " 5:eval_expression_condition(\"def\")\n"
+ " 6:eval_replace_vars(\"def\")\n"
+ " 6:== \"def\"\n"
+ " 5:== \"def\"\n"
+ " 7:eval_compare(\"abc\", \"<\", \"def\")\n"
+ " 7:== \"1\"\n"
+ " 2:== \"1\"\n"
+ "1:== \"1\"",
ptr_debug_output);
hashtable_remove (options, "debug");
hashtable_remove (options, "debug_output");
@@ -297,66 +304,126 @@ TEST(CoreEval, EvalCondition)
hashtable_set (options, "debug", "2");
WEE_CHECK_EVAL("1", "abc < def");
ptr_debug_output = (const char *)hashtable_get (options, "debug_output");
- STRCMP_EQUAL("eval_expression(\"abc < def\")\n"
- "eval_expression_condition(\"abc < def\")\n"
- "eval_strstr_level(\"abc < def\", \"||\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"&&\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"=~\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"!~\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"==*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"!!*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"=*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"!*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"==-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"!!-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"=-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"!-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"==\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"!=\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"<=\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc < def\", \"<\", \"(\", \")\", 0)\n"
- "eval_expression_condition(\"abc\")\n"
- "eval_strstr_level(\"abc\", \"||\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"&&\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"=~\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"!~\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"==*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"!!*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"=*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"!*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"==-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"!!-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"=-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"!-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"==\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"!=\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"<=\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \"<\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \">=\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"abc\", \">\", \"(\", \")\", 0)\n"
- "eval_replace_vars(\"abc\")\n"
- "eval_expression_condition(\"def\")\n"
- "eval_strstr_level(\"def\", \"||\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"&&\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"=~\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"!~\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"==*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"!!*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"=*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"!*\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"==-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"!!-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"=-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"!-\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"==\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"!=\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"<=\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \"<\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \">=\", \"(\", \")\", 0)\n"
- "eval_strstr_level(\"def\", \">\", \"(\", \")\", 0)\n"
- "eval_replace_vars(\"def\")\n"
- "eval_compare(\"abc\", \"<\", \"def\")",
- ptr_debug_output);
+ STRCMP_EQUAL(
+ "1:eval_expression(\"abc < def\")\n"
+ " 2:eval_expression_condition(\"abc < def\")\n"
+ " 3:eval_strstr_level(\"abc < def\", \"||\", \"(\", \")\", 0)\n"
+ " 3:== null\n"
+ " 4:eval_strstr_level(\"abc < def\", \"&&\", \"(\", \")\", 0)\n"
+ " 4:== null\n"
+ " 5:eval_strstr_level(\"abc < def\", \"=~\", \"(\", \")\", 0)\n"
+ " 5:== null\n"
+ " 6:eval_strstr_level(\"abc < def\", \"!~\", \"(\", \")\", 0)\n"
+ " 6:== null\n"
+ " 7:eval_strstr_level(\"abc < def\", \"==*\", \"(\", \")\", 0)\n"
+ " 7:== null\n"
+ " 8:eval_strstr_level(\"abc < def\", \"!!*\", \"(\", \")\", 0)\n"
+ " 8:== null\n"
+ " 9:eval_strstr_level(\"abc < def\", \"=*\", \"(\", \")\", 0)\n"
+ " 9:== null\n"
+ " 10:eval_strstr_level(\"abc < def\", \"!*\", \"(\", \")\", 0)\n"
+ " 10:== null\n"
+ " 11:eval_strstr_level(\"abc < def\", \"==-\", \"(\", \")\", 0)\n"
+ " 11:== null\n"
+ " 12:eval_strstr_level(\"abc < def\", \"!!-\", \"(\", \")\", 0)\n"
+ " 12:== null\n"
+ " 13:eval_strstr_level(\"abc < def\", \"=-\", \"(\", \")\", 0)\n"
+ " 13:== null\n"
+ " 14:eval_strstr_level(\"abc < def\", \"!-\", \"(\", \")\", 0)\n"
+ " 14:== null\n"
+ " 15:eval_strstr_level(\"abc < def\", \"==\", \"(\", \")\", 0)\n"
+ " 15:== null\n"
+ " 16:eval_strstr_level(\"abc < def\", \"!=\", \"(\", \")\", 0)\n"
+ " 16:== null\n"
+ " 17:eval_strstr_level(\"abc < def\", \"<=\", \"(\", \")\", 0)\n"
+ " 17:== null\n"
+ " 18:eval_strstr_level(\"abc < def\", \"<\", \"(\", \")\", 0)\n"
+ " 18:== \"< def\"\n"
+ " 19:eval_expression_condition(\"abc\")\n"
+ " 20:eval_strstr_level(\"abc\", \"||\", \"(\", \")\", 0)\n"
+ " 20:== null\n"
+ " 21:eval_strstr_level(\"abc\", \"&&\", \"(\", \")\", 0)\n"
+ " 21:== null\n"
+ " 22:eval_strstr_level(\"abc\", \"=~\", \"(\", \")\", 0)\n"
+ " 22:== null\n"
+ " 23:eval_strstr_level(\"abc\", \"!~\", \"(\", \")\", 0)\n"
+ " 23:== null\n"
+ " 24:eval_strstr_level(\"abc\", \"==*\", \"(\", \")\", 0)\n"
+ " 24:== null\n"
+ " 25:eval_strstr_level(\"abc\", \"!!*\", \"(\", \")\", 0)\n"
+ " 25:== null\n"
+ " 26:eval_strstr_level(\"abc\", \"=*\", \"(\", \")\", 0)\n"
+ " 26:== null\n"
+ " 27:eval_strstr_level(\"abc\", \"!*\", \"(\", \")\", 0)\n"
+ " 27:== null\n"
+ " 28:eval_strstr_level(\"abc\", \"==-\", \"(\", \")\", 0)\n"
+ " 28:== null\n"
+ " 29:eval_strstr_level(\"abc\", \"!!-\", \"(\", \")\", 0)\n"
+ " 29:== null\n"
+ " 30:eval_strstr_level(\"abc\", \"=-\", \"(\", \")\", 0)\n"
+ " 30:== null\n"
+ " 31:eval_strstr_level(\"abc\", \"!-\", \"(\", \")\", 0)\n"
+ " 31:== null\n"
+ " 32:eval_strstr_level(\"abc\", \"==\", \"(\", \")\", 0)\n"
+ " 32:== null\n"
+ " 33:eval_strstr_level(\"abc\", \"!=\", \"(\", \")\", 0)\n"
+ " 33:== null\n"
+ " 34:eval_strstr_level(\"abc\", \"<=\", \"(\", \")\", 0)\n"
+ " 34:== null\n"
+ " 35:eval_strstr_level(\"abc\", \"<\", \"(\", \")\", 0)\n"
+ " 35:== null\n"
+ " 36:eval_strstr_level(\"abc\", \">=\", \"(\", \")\", 0)\n"
+ " 36:== null\n"
+ " 37:eval_strstr_level(\"abc\", \">\", \"(\", \")\", 0)\n"
+ " 37:== null\n"
+ " 38:eval_replace_vars(\"abc\")\n"
+ " 38:== \"abc\"\n"
+ " 19:== \"abc\"\n"
+ " 39:eval_expression_condition(\"def\")\n"
+ " 40:eval_strstr_level(\"def\", \"||\", \"(\", \")\", 0)\n"
+ " 40:== null\n"
+ " 41:eval_strstr_level(\"def\", \"&&\", \"(\", \")\", 0)\n"
+ " 41:== null\n"
+ " 42:eval_strstr_level(\"def\", \"=~\", \"(\", \")\", 0)\n"
+ " 42:== null\n"
+ " 43:eval_strstr_level(\"def\", \"!~\", \"(\", \")\", 0)\n"
+ " 43:== null\n"
+ " 44:eval_strstr_level(\"def\", \"==*\", \"(\", \")\", 0)\n"
+ " 44:== null\n"
+ " 45:eval_strstr_level(\"def\", \"!!*\", \"(\", \")\", 0)\n"
+ " 45:== null\n"
+ " 46:eval_strstr_level(\"def\", \"=*\", \"(\", \")\", 0)\n"
+ " 46:== null\n"
+ " 47:eval_strstr_level(\"def\", \"!*\", \"(\", \")\", 0)\n"
+ " 47:== null\n"
+ " 48:eval_strstr_level(\"def\", \"==-\", \"(\", \")\", 0)\n"
+ " 48:== null\n"
+ " 49:eval_strstr_level(\"def\", \"!!-\", \"(\", \")\", 0)\n"
+ " 49:== null\n"
+ " 50:eval_strstr_level(\"def\", \"=-\", \"(\", \")\", 0)\n"
+ " 50:== null\n"
+ " 51:eval_strstr_level(\"def\", \"!-\", \"(\", \")\", 0)\n"
+ " 51:== null\n"
+ " 52:eval_strstr_level(\"def\", \"==\", \"(\", \")\", 0)\n"
+ " 52:== null\n"
+ " 53:eval_strstr_level(\"def\", \"!=\", \"(\", \")\", 0)\n"
+ " 53:== null\n"
+ " 54:eval_strstr_level(\"def\", \"<=\", \"(\", \")\", 0)\n"
+ " 54:== null\n"
+ " 55:eval_strstr_level(\"def\", \"<\", \"(\", \")\", 0)\n"
+ " 55:== null\n"
+ " 56:eval_strstr_level(\"def\", \">=\", \"(\", \")\", 0)\n"
+ " 56:== null\n"
+ " 57:eval_strstr_level(\"def\", \">\", \"(\", \")\", 0)\n"
+ " 57:== null\n"
+ " 58:eval_replace_vars(\"def\")\n"
+ " 58:== \"def\"\n"
+ " 39:== \"def\"\n"
+ " 59:eval_compare(\"abc\", \"<\", \"def\")\n"
+ " 59:== \"1\"\n"
+ " 2:== \"1\"\n"
+ "1:== \"1\"",
+ ptr_debug_output);
hashtable_remove (options, "debug");
hashtable_remove (options, "debug_output");
@@ -702,7 +769,7 @@ TEST(CoreEval, EvalExpression)
WEE_CHECK_EVAL("1", "<<<buffer.number>>>");
hashtable_free (options);
- /* test with debug */
+ /* test with debug level 1 */
options = hashtable_new (32,
WEECHAT_HASHTABLE_STRING,
WEECHAT_HASHTABLE_STRING,
@@ -711,9 +778,30 @@ TEST(CoreEval, EvalExpression)
hashtable_set (options, "debug", "1");
WEE_CHECK_EVAL("fedcba", "${rev:abcdef}");
ptr_debug_output = (const char *)hashtable_get (options, "debug_output");
- STRCMP_EQUAL("eval_expression(\"${rev:abcdef}\")\n"
- "eval_replace_vars(\"${rev:abcdef}\")\n"
- "eval_replace_vars_cb(\"rev:abcdef\")",
+ STRCMP_EQUAL("1:eval_expression(\"${rev:abcdef}\")\n"
+ " 2:eval_replace_vars(\"${rev:abcdef}\")\n"
+ " 3:eval_replace_vars_cb(\"rev:abcdef\")\n"
+ " 3:== \"fedcba\"\n"
+ " 2:== \"fedcba\"\n"
+ "1:== \"fedcba\"",
+ ptr_debug_output);
+ hashtable_free (options);
+
+ /* test with debug level 2 */
+ options = hashtable_new (32,
+ WEECHAT_HASHTABLE_STRING,
+ WEECHAT_HASHTABLE_STRING,
+ NULL, NULL);
+ CHECK(options);
+ hashtable_set (options, "debug", "2");
+ WEE_CHECK_EVAL("fedcba", "${rev:abcdef}");
+ ptr_debug_output = (const char *)hashtable_get (options, "debug_output");
+ STRCMP_EQUAL("1:eval_expression(\"${rev:abcdef}\")\n"
+ " 2:eval_replace_vars(\"${rev:abcdef}\")\n"
+ " 3:eval_replace_vars_cb(\"rev:abcdef\")\n"
+ " 3:== \"fedcba\"\n"
+ " 2:== \"fedcba\"\n"
+ "1:== \"fedcba\"",
ptr_debug_output);
hashtable_free (options);