/* 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); }