#ifndef LIB_DBG_DEBUG_FUNCTIONS_MQH_INCLUDED #define LIB_DBG_DEBUG_FUNCTIONS_MQH_INCLUDED #property version "5.10" /********************************************************************************** * Copyright (C) 2020 Dominik Egert * * This file is the debugger functions library include file. * * Lisence applied: GPLv2 * https://www.gnu.org/licenses/old-licenses/gpl-2.0.html * * Author Dominik Egert / Freie Netze UG. ********************************************************************************** * * Version: 5.10 * State: public * * File information * ================ * */ //*********************************************************************************************************************************************************/ // Begin Debugging support functions // // Overloaded functions #ifndef LIB_DEBUG_NAMESPACE #ifdef __MQL5__ namespace dbg_lib { #endif // Internal debuging code variables static ulong LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_session_id) = LIB_DBG_GETTICKCOUNT(); static int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_uninit_reason) = -1; static int LIB_DBG_NAMESPACE_DEF(dbg_lib, trace_call_depth) = NULL; // Auto en/disable api call tracing static bool LIB_DBG_NAMESPACE_DEF(dbg_lib, trace_api_calls) = false; // Debug file loader trace function const bool LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_print_file_trace)(const string _file) { static int cnt = NULL; LIB_DBG_NAMESPACE(dbg_lib, dbg_printf)("Loaded file: %s, count: %i", _file, cnt + 1); cnt++; return(true); } // Debug strip mql-api function stubs const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_extract_mqlfunction_name)(const string p_in) //{ string out = p_in; int pos = StringFind(out, "trace_call_details"); if(pos == -1) { return(p_in); } out = StringSubstr(out, pos + 18); pos = StringFind(out, ")"); string out_arr[]; if(StringSplit(StringSubstr(out, 0, pos), 0x2C, out_arr) != 5) { return(p_in); } out = StringSubstr(out, pos); out = StringSubstr(out, StringFind(out, out_arr[4])); out = StringSubstr(out, StringFind(out, "(")); return(StringFormat("(%s%s", out_arr[4], out)); } { string out = p_in; int pos = StringFind(out, "trace_call_details"); if(pos == -1) { return(p_in); } out = StringSubstr(out, pos + 18); pos = StringFind(out, ")"); string out_arr[]; if(StringSplit(StringSubstr(out, 0, pos), 0x2C, out_arr) != 5) { return(p_in); } out = StringSubstr(out, pos); out = StringSubstr(out, StringFind(out, out_arr[4])); out = StringSubstr(out, StringFind(out, "(")); pos = StringSplit(out_arr[4], 0x005F, out_arr); return(StringFormat("(%s%s", out_arr[pos - 1], out)); } // MQL macro function replacement protection void LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_Alert)(const string p_in) { Alert(p_in); } template const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArraySize)(T& p_in[]) { return(ArraySize(p_in)); } template const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArraySize)(T& p_in[][]) { return(ArraySize(p_in)); } template const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArraySize)(T& p_in[][][]) { return(ArraySize(p_in)); } template const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArraySize)(T& p_in[][][][]) { return(ArraySize(p_in)); } template const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArraySize)(T*& p_in[]) { return(ArraySize(p_in)); } template const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArraySize)(T*& p_in[][]) { return(ArraySize(p_in)); } template const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArraySize)(T*& p_in[][][]) { return(ArraySize(p_in)); } template const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArraySize)(T*& p_in[][][][]) { return(ArraySize(p_in)); } template void LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ArrayPrint)(const T& p_in[], const int digits, const int start) { ArrayPrint(p_in, digits, "", start); } const long LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ChartID)() { return(ChartID()); } const ulong LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_GetMicrosecondCount)() { return(GetMicrosecondCount()); } const ulong LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_GetTickCount)() { return(LIB_DBG_GETTICKCOUNT()); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ColorToString)(const color p_in, const bool color_name = false) { return(ColorToString(p_in, color_name)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_IntegerToString)(const long p_in) { return(IntegerToString(p_in)); } const long LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_MQLInfoInteger)(const ENUM_MQL_INFO_INTEGER p_in) { return(MQLInfoInteger(p_in)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_MQLInfoString)(const ENUM_MQL_INFO_STRING p_in) { return(MQLInfoString(p_in)); } const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringLen)(const string p_in) { return(StringLen(p_in)); } const datetime LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringToTime)(const string p_in) { return(StringToTime(p_in)); } const long LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_TerminalInfoInteger)(const ENUM_TERMINAL_INFO_INTEGER p_in) { return(TerminalInfoInteger(p_in)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_TerminalInfoString)(const ENUM_TERMINAL_INFO_STRING p_in) { return(TerminalInfoString(p_in)); } const datetime LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_TimeCurrent)() { return(TimeCurrent()); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_TimeToString)(const datetime val) { const bool ms = ((val / TimeLocal()) > 100); datetime _val = val / ((ms) ? 1000 : 1); return(StringFormat("%s%s", TimeToString(_val, TIME_DATE | TIME_SECONDS), (ms) ? StringFormat(".%03i", val%1000) : "")); } const bool LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_TimeToStruct)(const datetime dtm, MqlDateTime& tm) { return(TimeToStruct(dtm, tm)); } template const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringFormat)(const string p1, const T p2) { return(StringFormat(p1, p2)); } template const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringFormat)(const string p1, const T p2, const U p3) { return(StringFormat(p1, p2, p3)); } template const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringFormat)(const string p1, const T p2, const U p3, const V p4) { return(StringFormat(p1, p2, p3, p4)); } template const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringFormat)(const string p1, const T p2, const U p3, const V p4, const W p5) { return(StringFormat(p1, p2, p3, p4, p5)); } template const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringFormat)(const string p1, const T p2, const U p3, const V p4, const W p5, const X p6) { return(StringFormat(p1, p2, p3, p4, p5, p6)); } template const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringFormat)(const string p1, const T p2, const U p3, const V p4, const W p5, const X p6, const Y p7) { return(StringFormat(p1, p2, p3, p4, p5, p6, p7)); } template const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_StringFormat)(const string p1, const T p2, const U p3, const V p4, const W p5, const X p6, const Y p7, const Z p8) { return(StringFormat(p1, p2, p3, p4, p5, p6, p7, p8)); } // Unified string trim (MQL5/MQL4+) #ifndef __MQL5__ void LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_string_trim)(string& p_in) { string out = StringTrimLeft(p_in); p_in = StringTrimRight(out); } #else void LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_string_trim)(string& p_in) { StringTrimLeft(p_in); StringTrimRight(p_in); } #endif // Consistent typename to string conversion const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_typename_to_string)(const string p_in, const bool enum_no_resolve = false) { static string last_call = NULL; static string tmp = NULL; if(last_call == p_in) { return(tmp); } else if((enum_no_resolve) && ((StringFind(p_in, " enum ") != -1) || (StringFind(p_in, " ENUM ") != -1))) { return("enum"); } last_call = p_in; tmp = " " + p_in + " "; StringReplace(tmp, " const ", " "); StringReplace(tmp, " class ", " "); StringReplace(tmp, " struct ", " "); StringReplace(tmp, " interface ", " "); StringReplace(tmp, " static ", " "); StringReplace(tmp, " ENUM ", " "); StringReplace(tmp, " enum ", " "); tmp = StringSubstr(tmp, NULL, StringFind(tmp, "[")); StringReplace(tmp, " *", "*"); LIB_DBG_NAMESPACE(dbg_lib, dbg_string_trim)(tmp); return(tmp); } // Boolean return value print statement const bool LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_eval_return)(const string file, const string func, const int line, const string msg, const bool retval, const bool _printf = true, const string cmnt = NULL) { if(_printf) { LIB_DBG_NAMESPACE(dbg_lib, dbg_printf)(LIB_DBG_NAMESPACE(dbg_lib, dbg_context_msg)(DBG_OUTPUT_PREFIX, file, func, line, (cmnt == NULL) ? StringFormat("(%s) => %s", msg, LIB_DBG_NAMESPACE(dbg_lib, dbg_to_string)(retval)) : StringFormat("(%s) => %s // %s", msg, LIB_DBG_NAMESPACE(dbg_lib, dbg_to_string)(retval), cmnt))); } return(retval); } // Array index checking template const T LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_eval_array_index)(const T& arr[], const int idx) { if(idx != -1) { return(arr[idx]); } return(NULL); } const int LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_eval_array_index)(const int arr_size, const int idx, const string msg) { if((idx >= arr_size) || (idx < NULL)) { LIB_DBG_NAMESPACE(dbg_lib, dbg_printf)(msg); return(-1); } return(idx); } // To HEX-String helpers const string LIB_DBG_NAMESPACE_DEF(dbg_lib, flt_raw)(const float in, const bool hex = DBG_HEX_OUTPUT) { union conv { float f; uint u; } c; c.f = in; return((hex) ? StringFormat("0x%08X", c.u) : LIB_DBG_NAMESPACE(dbg_lib, bits_out)((ulong)c.u)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbl_raw)(const double in, const bool hex = DBG_HEX_OUTPUT) { union conv { double d; ulong u; } c; c.d = in; return((hex) ? StringFormat("0x%016llX", c.u) : LIB_DBG_NAMESPACE(dbg_lib, bits_out)((ulong)c.u)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_remove_leading_namespace)(const string in) { const int shift = (StringFind(in, "::", 0) == 0) ? 2 : 0; return((StringLen(in) > DBG_PRINT_VARNAME_MAX_LENGTH + shift) ? StringSubstr(in, shift, DBG_PRINT_VARNAME_MAX_LENGTH - 10 + shift) + "..." : StringSubstr(in, shift)); } // Known basic types const int typename_known(const string type) { return( (type == "bool") || (type == "float") || (type == "double") || (type == "datetime") || (type == "enum") || (type == "char") || (type == "short") || (type == "int") || (type == "long") || (type == "uchar") || (type == "ushort") ||(type == "uint") || (type == "ulong") || (type == "complex") || (type == "matrix") || (type == "matrixf") || (type == "matrixc") || (type == "vector") || (type == "vectorf") || (type == "vectorc") || (type == "string") ); }; // IEEE 754 compliant float to string conversion const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ieee754_to_string)(const float value) { string str = NULL; for(int sig = 6; sig <= 9; sig++) { if(value == float(str = StringFormat("%." + string(sig) + "g", value))) break; } return(str); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ieee754_to_string)(const double value) { string str = NULL; for(int sig = 14; sig <= 17; sig++) { if(value == double(str = StringFormat("%." + string(sig) + "g", value))) break; } return(str); } // Value to string helpers const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const char val) { return(StringFormat("%hd", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const short val) { return(StringFormat("%hi", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const int val) { return(StringFormat("%i", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const long val) { return(StringFormat("%lli", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const uchar val) { return(StringFormat("%hu", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const ushort val) { return(StringFormat("%hu", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const uint val) { return(StringFormat("%u", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const ulong val) { return(StringFormat("%llu", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const string val) { return(StringFormat("%s", val)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const float val) { return(LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ieee754_to_string)(val)); } #ifdef __MQL5__ const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const double val) { return(string(val)); } #else const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const double val) { return(LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_ieee754_to_string)(val)); } #endif const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const datetime val) { return(TimeToString(val)); } //{ return(StringFormat("%s", TimeToString(val))); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const color val) { return(ColorToString(val, true)); } //{ return(StringFormat("%s", ColorToString(val, true))); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const bool val) { return(StringFormat("%s", val ? "true" : "false")); } #ifdef LIB_DBG_INCLUDE_COMPLEX_TYPE const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const complex val) { return(StringFormat("r:%g;i:%g", val.real, val.imag)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const matrix& val) { return(StringFormat("%s, line: %i", "Not implemented: " + __FILE__, __LINE__)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const vector& val) { return(StringFormat("%s, line: %i", "Not implemented: " + __FILE__, __LINE__)); } #endif template const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_to_string)(const T val) { return(EnumToString(val)); } // { return(StringFormat("%s", EnumToString(val))); } // Get day of week const string LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_day_of_week)(const datetime val) { MqlDateTime tm; LIB_DBG_NAMESPACE(dbg_lib, dbg_TimeToStruct)(val / (((val / TimeLocal()) > 100) ? 1000 : 1), tm); switch(tm.day_of_week) { case 0: return("Sunday"); case 1: return("Monday"); case 2: return("Tuesday"); case 3: return("Wednesday"); case 4: return("Thursday"); case 5: return("Friday"); case 6: return("Saturday"); } return(NULL); } // Literal to bit string const string LIB_DBG_NAMESPACE_DEF(dbg_lib, bits_out)(const ulong val) { return(StringFormat("%s %s", LIB_DBG_NAMESPACE(dbg_lib, bits_out)((uint)(val>>32)), LIB_DBG_NAMESPACE(dbg_lib, bits_out)((uint)val))); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, bits_out)(const uint val) { return(StringFormat("%s %s", LIB_DBG_NAMESPACE(dbg_lib, bits_out)((ushort)(val>>16)), LIB_DBG_NAMESPACE(dbg_lib, bits_out)((ushort)val))); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, bits_out)(const ushort val) { return(StringFormat("%s %s", LIB_DBG_NAMESPACE(dbg_lib, bits_out)((uchar)(val>>8)), LIB_DBG_NAMESPACE(dbg_lib, bits_out)((uchar)val))); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, bits_out)(const uchar val) { return(StringFormat("%s%s%s%s%s%s%s%s", ((((uchar)val)&0x80) > NULL) ? "1" : "0", ((((uchar)val)&0x40) > NULL) ? "1" : "0", ((((uchar)val)&0x20) > NULL) ? "1" : "0", ((((uchar)val)&0x10) > NULL) ? "1" : "0", ((((uchar)val)&0x08) > NULL) ? "1" : "0", ((((uchar)val)&0x04) > NULL) ? "1" : "0", ((((uchar)val)&0x02) > NULL)? "1" : "0", ((((uchar)val)&0x01) > NULL) ? "1" : "0")); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, bits_out)(const float val) { union __flt_uint { float f; uint u; } tmp; tmp.f = val; return(LIB_DBG_NAMESPACE(dbg_lib, bits_out)(tmp.u)); } const string LIB_DBG_NAMESPACE_DEF(dbg_lib, bits_out)(const double val) { union __flt_uint { double f; ulong u; } tmp; tmp.f = val; return(LIB_DBG_NAMESPACE(dbg_lib, bits_out)(tmp.u)); } // Uninit code to string const string LIB_DBG_NAMESPACE_DEF(dbg_lib, uninit_text)(const string func_name, const int custom_uninit_reason = -1) { LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason) = (LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason) == -1) && ((_UninitReason != NULL) || (_StopFlag && (func_name == "OnDeinit"))) ? _UninitReason : LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason); if(LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason) == -1) { return(NULL); } switch((custom_uninit_reason == -1) ? LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason) : custom_uninit_reason) { // Terminal built-in reasons case REASON_PROGRAM: return(StringFormat("(_UninitReason) %i = REASON_PROGRAM: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Expert Advisor terminated its operation by calling the ExpertRemove() function.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_REMOVE: return(StringFormat("(_UninitReason) %i = REASON_REMOVE: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Program has been deleted from the chart.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_RECOMPILE: return(StringFormat("(_UninitReason) %i = REASON_RECOMPILE: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Program has been recompiled.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_CHARTCHANGE: return(StringFormat("(_UninitReason) %i = REASON_CHARTCHANGE: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Symbol or chart period has been changed.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_CHARTCLOSE: return(StringFormat("(_UninitReason) %i = REASON_CHARTCLOSE: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Chart has been closed.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_PARAMETERS: return(StringFormat("(_UninitReason) %i = REASON_PARAMETERS: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Input parameters have been changed by a user.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_ACCOUNT: return(StringFormat("(_UninitReason) %i = REASON_ACCOUNT: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_TEMPLATE: return(StringFormat("(_UninitReason) %i = REASON_TEMPLATE: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "A new template has been applied.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_INITFAILED: return(StringFormat("(_UninitReason) %i = REASON_INITFAILED: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "This value means that OnInit() handler has returned a nonzero value.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); case REASON_CLOSE: return(StringFormat("(_UninitReason) %i = REASON_CLOSE: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Terminal has been closed.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); // MQLplus extended reasons case REASON_MQLPLUS_EXPERT_KILL: return(StringFormat("(_UninitReason) %i = REASON_MQLPLUS_EXPERT_KILL: %s (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), "Program terminated its operation by calling the ExpertKill() function.", LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); // Unknown reasons default: return(StringFormat("Unknown reason: %i (session id: %llu)", (int)LIB_DBG_NAMESPACE(dbg_lib, dbg_uninit_reason), LIB_DBG_NAMESPACE(dbg_lib, dbg_session_id))); } return(NULL); } // Return function results template T LIB_DBG_NAMESPACE_DEF(dbg_lib, return_function_result_wrapper)(const string file, const string function, const int line, const string val_name, const T value) { LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_trace_end)(file, function, line, LIB_DBG_NAMESPACE(dbg_lib, var_out)(val_name, value)); return(value); }; // Return function object template void LIB_DBG_NAMESPACE_DEF(dbg_lib, return_function_object_wrapper)(const string file, const string function, const int line, const string val_name, const T& value) { LIB_DBG_NAMESPACE_DEF(dbg_lib, dbg_trace_end)(file, function, line, LIB_DBG_NAMESPACE(dbg_lib, var_out)(val_name, value)); return; }; // Software inherited brakepoints const bool LIB_DBG_NAMESPACE_DEF(dbg_lib, BreakPoint)(const int _line_, const string _file_, const long _timestamp_ = NULL) { #ifndef DBG_DEBUGGER_OVERWRITE if(IS_DEBUG_MODE) { printf("##### Breakpoint set at line: %i in file: %s.", _line_, _file_); return(true); } else #endif if(_timestamp_ <= ((TimeCurrent() - (TimeCurrent() % PeriodSeconds())) * (_timestamp_ > NULL))) { printf("##### Breakpoint set at line: %i in file: %s, waiting %i seconds.", _line_, _file_, DBG_SOFT_BKP_TIMEOUT); return(true); } return(false); } const bool LIB_DBG_NAMESPACE_DEF(dbg_lib, ExecTime)(const uint _seconds_) { static ulong exec_time_start = GetMicrosecondCount(); exec_time_start = (exec_time_start * (ulong)((_seconds_ > 0x00) & 0x01)) + (GetMicrosecondCount() * (ulong)((_seconds_ == NULL) & 0x01)); return(((long)exec_time_start) < ((long)(GetMicrosecondCount() - (_seconds_ * 1000000)))); } #ifdef __MQL5__ }; #endif #endif // // END Debugging support //*********************************************************************************************************************************************************/ #endif // LIB_DBG_DEBUG_FUNCTIONS_MQH_INCLUDED