diff options
Diffstat (limited to 'pigeonhole/src/lib-sieve/sieve-runtime-trace.c')
-rw-r--r-- | pigeonhole/src/lib-sieve/sieve-runtime-trace.c | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/pigeonhole/src/lib-sieve/sieve-runtime-trace.c b/pigeonhole/src/lib-sieve/sieve-runtime-trace.c new file mode 100644 index 0000000..a9351a3 --- /dev/null +++ b/pigeonhole/src/lib-sieve/sieve-runtime-trace.c @@ -0,0 +1,151 @@ +/* Copyright (c) 2002-2018 Pigeonhole authors, see the included COPYING file + */ + +#include "lib.h" +#include "str.h" +#include "ostream.h" + +#include "sieve-common.h" +#include "sieve-script.h" +#include "sieve-binary.h" +#include "sieve-code.h" +#include "sieve-interpreter.h" +#include "sieve-runtime.h" +#include "sieve-runtime-trace.h" + +static inline string_t *_trace_line_new +(const struct sieve_runtime_env *renv, sieve_size_t address, unsigned int cmd_line) +{ + string_t *trline; + unsigned int i; + + trline = t_str_new(128); + if ( (renv->trace->config.flags & SIEVE_TRFLG_ADDRESSES) > 0 ) + str_printfa(trline, "%08llx: ", (unsigned long long) address); + if ( cmd_line > 0 ) + str_printfa(trline, "%4d: ", cmd_line); + else + str_append(trline, " "); + + for ( i = 0; i < renv->trace->indent; i++ ) + str_append(trline, " "); + + return trline; +} + +static inline void _trace_line_print +(string_t *trline, const struct sieve_runtime_env *renv) +{ + sieve_trace_log_write_line(renv->trace->log, trline); +} + +static inline void _trace_line_print_empty +(const struct sieve_runtime_env *renv) +{ + sieve_trace_log_write_line(renv->trace->log, NULL); +} + +/* + * Trace errors + */ + +void _sieve_runtime_trace_error +(const struct sieve_runtime_env *renv, const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new(renv, renv->pc, 0); + + str_printfa(trline, "%s: #ERROR#: ", sieve_operation_mnemonic(renv->oprtn)); + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +void _sieve_runtime_trace_operand_error +(const struct sieve_runtime_env *renv, const struct sieve_operand *oprnd, + const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new(renv, oprnd->address, + sieve_runtime_get_source_location(renv, oprnd->address)); + + str_printfa(trline, "%s: #ERROR#: ", sieve_operation_mnemonic(renv->oprtn)); + + if ( oprnd->field_name != NULL ) + str_printfa(trline, "%s: ", oprnd->field_name); + + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +/* + * Trace info + */ + +static inline void ATTR_FORMAT(4, 0) _sieve_runtime_trace_vprintf +(const struct sieve_runtime_env *renv, sieve_size_t address, + unsigned int cmd_line, const char *fmt, va_list args) +{ + string_t *trline = _trace_line_new(renv, address, cmd_line); + + str_vprintfa(trline, fmt, args); + + _trace_line_print(trline, renv); +} + +static inline void ATTR_FORMAT(4, 5) _sieve_runtime_trace_printf +(const struct sieve_runtime_env *renv, sieve_size_t address, + unsigned int cmd_line, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + _sieve_runtime_trace_vprintf(renv, address, cmd_line, fmt, args); + va_end(args); +} + +void ATTR_FORMAT(2, 0) _sieve_runtime_trace +(const struct sieve_runtime_env *renv, const char *fmt, va_list args) +{ + _sieve_runtime_trace_vprintf + (renv, renv->oprtn->address, sieve_runtime_get_command_location(renv), + fmt, args); +} + +void _sieve_runtime_trace_address +(const struct sieve_runtime_env *renv, sieve_size_t address, + const char *fmt, va_list args) +{ + _sieve_runtime_trace_vprintf + (renv, address, sieve_runtime_get_source_location(renv, address), fmt, + args); +} + +/* + * Trace boundaries + */ + +void _sieve_runtime_trace_begin(const struct sieve_runtime_env *renv) +{ + const char *script_name = ( renv->script != NULL ? + sieve_script_name(renv->script) : sieve_binary_path(renv->sbin) ); + + _trace_line_print_empty(renv); + _sieve_runtime_trace_printf(renv, renv->pc, 0, + "## Started executing script '%s'", script_name); +} + +void _sieve_runtime_trace_end(const struct sieve_runtime_env *renv) +{ + const char *script_name = ( renv->script != NULL ? + sieve_script_name(renv->script) : sieve_binary_path(renv->sbin) ); + + _sieve_runtime_trace_printf(renv, renv->pc, 0, + "## Finished executing script '%s'", script_name); + _trace_line_print_empty(renv); +} + +void _sieve_runtime_trace_sep(const struct sieve_runtime_env *renv) +{ + _trace_line_print_empty(renv); +} + |