#ifndef LIB_ERROR_MAIN_CODE_MQH_INCLUDED #define LIB_ERROR_MAIN_CODE_MQH_INCLUDED #property version "4.0"; /********************************************************************************** * Copyright (C) 2010-2020 Dominik Egert * * This file is part of lib_bali * * lib_error.mqh may be copied and/or distributed at free will * Dominik Egert / Freie Netze UG. ********************************************************************************** * * Version 4.0 * State: public * * * File information * ================ * * Use: resolve error codes to text * * * */ ///////////////////////////////////////// // // Define library mode // // Header mode #ifndef LIB_ERR_LIB_EXPORT #define LIB_ERR_LIB_EXPORT #endif // Binary mode #ifdef LIB_ERR_BINARY_LIBRARY #ifndef LIB_ERR_NO_INCLUDE #define LIB_ERR_NO_INCLUDE #endif #ifdef LIB_ERR_LIB_EXPORT #undef LIB_ERR_LIB_EXPORT #endif #ifdef LIB_DEBUG #undef LIB_DEBUG #endif #define LIB_ERR_LIB_EXPORT export #property library #endif /////////////////////////////////////// // // Debugging support // //#define LIB_DEBUG #ifdef LIB_DEBUG #include <../Shared Projects/MQLplus/lib_debug.mqh> #endif /////////////////////////////////////// // Error resolver trace options // Trace err_reg_resolver() //#define DBG_TRACE_ERROR_ERR_REG_RESOLVER // Trace err_desc() //#define DBG_TRACE_ERROR_ERR_DESC // Trace err_desc_user //#define DBG_TRACE_ERROR_ERR_DESC_USER // Trace err_desc_comment //#define DBG_TRACE_ERROR_ERR_DESC_COMMENT // Trace err_SetMqlError //#define DBG_TRACE_ERROR_ERR_SETMQLERROR // Trace err_SetUserError //#define DBG_TRACE_ERROR_ERR_SETUSERERROR // Trace err_ResetUserError //#define DBG_TRACE_ERROR_ERR_RESETUSERERROR // Trace err_ResolveLastError //#define DBG_TRACE_ERROR_ERR_RESOLVELASTERROR // Trace err_LastErrorCode //#define DBG_TRACE_ERROR_ERR_LASTERRORCODE // Trace default OnError() handler //#define DBG_TRACE_ERROR_DEFAULT_ONERROR // /////////////////////////////////////// // // END Global error handler configuration //*********************************************************************************************************************************************************/ //*********************************************************************************************************************************************************/ // Macro definitions (no edit) // ///////////////////////////////////////////////////////////////////////////////////////////////////// // // Debug trace function call support // // Will only work when including lib_debug.mqh // #ifdef LIB_DEBUG /////////////////////////////////////////////////////////////// // Full trace #ifdef DBG_TRACE_LIB_ERROR #ifndef DBG_TRACE_ERROR_ERR_REG_RESOLVER #define DBG_TRACE_ERROR_ERR_REG_RESOLVER #endif #ifndef DBG_TRACE_ERROR_ERR_DESC #define DBG_TRACE_ERROR_ERR_DESC #endif #ifndef DBG_TRACE_ERROR_ERR_DESC_USER #define DBG_TRACE_ERROR_ERR_DESC_USER #endif #ifndef DBG_TRACE_ERROR_ERR_DESC_COMMENT #define DBG_TRACE_ERROR_ERR_DESC_COMMENT #endif #ifndef DBG_TRACE_ERROR_ERR_SETMQLERROR #define DBG_TRACE_ERROR_ERR_SETMQLERROR #endif #ifndef DBG_TRACE_ERROR_ERR_SETUSERERROR #define DBG_TRACE_ERROR_ERR_SETUSERERROR #endif #ifndef DBG_TRACE_ERROR_ERR_RESETUSERERROR #define DBG_TRACE_ERROR_ERR_RESETUSERERROR #endif #ifndef DBG_TRACE_ERROR_ERR_RESOLVELASTERROR #define DBG_TRACE_ERROR_ERR_RESOLVELASTERROR #endif #ifndef DBG_TRACE_ERROR_ERR_LASTERRORCODE #define DBG_TRACE_ERROR_ERR_LASTERRORCODE #endif #ifndef DBG_TRACE_ERROR_DEFAULT_ONERROR #define DBG_TRACE_ERROR_DEFAULT_ONERROR #endif #endif // /////////////////////////////////////////////////////////////// // Disable debugging support #else // Error code location string #define DGB_CODE_LOCATION(x) /////////////////////////////////////////////////////////////// // Clear debug tracing at runtime #ifdef DBG_TRACE_ERROR_ERR_REG_RESOLVER #undef DBG_TRACE_ERROR_ERR_REG_RESOLVER #endif #ifdef DBG_TRACE_ERROR_ERR_DESC #undef DBG_TRACE_ERROR_ERR_DESC #endif #ifdef DBG_TRACE_ERROR_ERR_DESC_USER #undef DBG_TRACE_ERROR_ERR_DESC_USER #endif #ifdef DBG_TRACE_ERROR_ERR_DESC_COMMENT #undef DBG_TRACE_ERROR_ERR_DESC_COMMENT #endif #ifdef DBG_TRACE_ERROR_ERR_SETMQLERROR #undef DBG_TRACE_ERROR_ERR_SETMQLERROR #endif #ifdef DBG_TRACE_ERROR_ERR_SETUSERERROR #undef DBG_TRACE_ERROR_ERR_SETUSERERROR #endif #ifdef DBG_TRACE_ERROR_ERR_RESETUSERERROR #undef DBG_TRACE_ERROR_ERR_RESETUSERERROR #endif #ifdef DBG_TRACE_ERROR_ERR_RESOLVELASTERROR #undef DBG_TRACE_ERROR_ERR_RESOLVELASTERROR #endif #ifdef DBG_TRACE_ERROR_ERR_LASTERRORCODE #undef DBG_TRACE_ERROR_ERR_LASTERRORCODE #endif #ifdef DBG_TRACE_ERROR_DEFAULT_ONERROR #undef DBG_TRACE_ERROR_DEFAULT_ONERROR #endif // /////////////////////////////////////////////////////////////// #endif // ///////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////// // // Minimum required debugging support // in case lib_debug.mqh is not included. // // Include primitive debugging helpers #ifndef DBG_ASSERT_RETURN_VAR #define DBG_ASSERT_RETURN_VAR(cond, msg, retval) { if(!(cond)) { string _msg_ = StringFormat("%s>%s< %s(){ @%i: %s }", ((#cond == "") ? "" : #cond + " "), __FILE__, __FUNCTION__, __LINE__, msg); return(retval); } } #endif #ifndef DBG_MSG_TRACE_RETURN #define DBG_MSG_TRACE_RETURN return #endif #ifndef DBG_MSG_TRACE_RETURN_VAR #define DBG_MSG_TRACE_RETURN_VAR(x) return(x) #endif #ifndef DBG_MSG #define DBG_MSG(x) #endif #ifndef DBG_MSG_PERSIST #define DBG_MSG_PERSIST(x) printf("%s", x) #endif #ifndef DBG_MSG_VAR #define DBG_MSG_VAR(x) #endif #ifndef PERF_COUNTER_BEGIN #define PERF_COUNTER_BEGIN #endif #ifndef DBG_MSG_NOTRACE_RETURN #define DBG_MSG_NOTRACE_RETURN return #endif #ifndef DBG_MSG_NOTRACE_RETURN_VAR #define DBG_MSG_NOTRACE_RETURN_VAR(x) return(x) #endif // //////////////////////////////////////////////////// // // END Macro definitions (no edit) //*********************************************************************************************************************************************************/ //*********************************************************************************************************************************************************/ // Error handler (No editing needed beyond this line...) // #ifndef __MQL4_COMPATIBILITY_CODE__ namespace lib_err {// Namespace lib_err:: BEGIN #endif ////////////////////////////////////////// // // Database language router // // Language id generator union str_char { uchar arr[sizeof(uint)]; uint id; } static lib_err_language; #ifdef LIB_ERROR_DESCRIPTION_FROM_FILE static int lib_err_language_id_bytes = StringToCharArray("FILE", lib_err_language.arr, NULL, sizeof(lib_err_language.id)); #else static int lib_err_language_id_bytes = StringToCharArray(TerminalInfoString(TERMINAL_LANGUAGE), lib_err_language.arr, NULL, sizeof(lib_err_language.id)); #endif // Primary error code resolver const string LIB_ERR_NAMESPACE_DEF(lib_err, error_description)(const int error_code) { switch(lib_err_language.id) { // Read from file #ifdef LIB_ERROR_DESCRIPTION_FROM_FILE case LIB_ERROR_LANG_FROM_FILE: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_FROM_FILE); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_FROM_FILE)(error_code)); #endif // Worldwide #ifdef LIB_ERROR_LANG_TERM_ID_RU case LIB_ERROR_LANG_TERM_ID_RU: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_RU); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_RU)(error_code)); #endif #ifdef LIB_ERROR_LANG_TERM_ID_TR case LIB_ERROR_LANG_TERM_ID_TR: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_TR); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_TR)(error_code)); #endif #ifdef LIB_ERROR_LANG_TERM_ID_ZH case LIB_ERROR_LANG_TERM_ID_ZH: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_ZH); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_ZH)(error_code)); #endif #ifdef LIB_ERROR_LANG_TERM_ID_JP case LIB_ERROR_LANG_TERM_ID_JP: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_JP); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_JP)(error_code)); #endif #ifdef LIB_ERROR_LANG_TERM_ID_KO case LIB_ERROR_LANG_TERM_ID_KO: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_KO); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_KO)(error_code)); #endif // Europe #ifdef LIB_ERROR_LANG_TERM_ID_ES case LIB_ERROR_LANG_TERM_ID_ES: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_ES); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_ES)(error_code)); #endif #ifdef LIB_ERROR_LANG_TERM_ID_PT case LIB_ERROR_LANG_TERM_ID_PT: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_PT); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_PT)(error_code)); #endif #ifdef LIB_ERROR_LANG_TERM_ID_FR case LIB_ERROR_LANG_TERM_ID_FR: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_FR); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_FR)(error_code)); #endif #ifdef LIB_ERROR_LANG_TERM_ID_IT case LIB_ERROR_LANG_TERM_ID_IT: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_IT); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_IT)(error_code)); #endif #ifdef LIB_ERROR_LANG_TERM_ID_DE case LIB_ERROR_LANG_TERM_ID_DE: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_DE); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_DE)(error_code)); #endif // English as default default: LIB_ERR_NAMESPACE(lib_err, func_ptr_mql_err_codes) = LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_EN); return(LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_EN)(error_code)); } // Return error return(NULL); } // Language id to ALPHA-2 code const string LIB_ERR_NAMESPACE_DEF(lib_err, error_language_alpha_code)() { switch(lib_err_language.id) { case LIB_ERROR_LANG_TERM_ID_RU: return("ru"); case LIB_ERROR_LANG_TERM_ID_TR: return("tr"); case LIB_ERROR_LANG_TERM_ID_ZH: return("cn"); case LIB_ERROR_LANG_TERM_ID_JP: return("jp"); case LIB_ERROR_LANG_TERM_ID_KO: return("kp"); case LIB_ERROR_LANG_TERM_ID_ES: return("es"); case LIB_ERROR_LANG_TERM_ID_PT: return("pl"); case LIB_ERROR_LANG_TERM_ID_FR: return("fr"); case LIB_ERROR_LANG_TERM_ID_IT: return("it"); case LIB_ERROR_LANG_TERM_ID_DE: return("de"); } // Return default return("en"); } // Language specific error code resolver (english) #ifdef LIB_ERROR_DESCRIPTION_FROM_FILE const string LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_FROM_FILE)(const int error_code) { // Error structure struct err_desc_struct { int err_code; string err_name; string err_desc; err_desc_struct() : err_code (-1), err_name (NULL), err_desc (NULL) { }; }; // Local init static int arr_size = NULL; int cnt = NULL; static string filename = StringFormat("lib_error_descriptions_%s_%s.csv", LIB_ERR_MT_VERSION_ID_STRING, LIB_ERR_NAMESPACE(lib_err, error_language_alpha_code)()); static err_desc_struct local_err_desc_arr[]; // Read file, if exists if( (arr_size == NULL) && (FileIsExist("lib_error_descriptions.csv")) ) { ResetLastError(); const int h_file = FileOpen("lib_error_descriptions.csv", FILE_READ | FILE_COMMON | FILE_TXT, CP_UTF8); bool abort = (_LastError != NULL); ushort separator[1]; string f_line = NULL; string split_value[]; StringToShortArray(";", separator, 0, 1); while( (!FileIsEnding(h_file)) && (!_StopFlag) && (!abort) ) { // Get next line ResetLastError(); f_line = FileReadString(h_file); abort |= (_LastError != NULL); // Split CSV values if( (!abort) && (StringSplit(f_line, separator[0], split_value) == 3) ) { arr_size = ArrayResize(local_err_desc_arr, arr_size + 1, 300); local_err_desc_arr[arr_size - 1].err_code = StringToInteger(split_value[0]); local_err_desc_arr[arr_size - 1].err_name = split_value[1]; local_err_desc_arr[arr_size - 1].err_desc = split_value[2]; } } is_init = (h_file != INVALID_HANDLE) && (!abort) && (arr_size > NULL); FileClose(h_file); arr_size = (abort) ? -1 : ArraySize(local_err_desc_arr); } // Find error description while( (cnt < arr_size) && (local_err_desc_arr[cnt].err_code != error_code) && (!_StopFlag) ) { cnt++; } // Clear error codes ResetLastError(); // Return return((cnt < arr_size) ? LIB_ERR_OUTPUT_FORMAT(local_err_desc_arr.err_code, local_err_desc_arr.err_name, local_err_desc_arr.err_desc) : LIB_ERROR_LANGUAGE_FUNCTION(LIB_ERROR_LANG_TERM_ID_EN)(error_code)); } #endif // ////////////////////////////////////////// ////////////////////////////////////////// // // Global resolver array // // Mql error resolver functions static TUsrErrFunc LIB_ERR_NAMESPACE_DEF(lib_err, func_ptr_mql_err_codes) = LIB_ERR_NAMESPACE(lib_err, error_description); // Array error group resolver functions static TUsrErrFunc LIB_ERR_NAMESPACE_DEF(lib_err, error_groups)[(0x10000 / LIB_ERR_GROUP_SIZE)]; // ////////////////////////////////////////// ////////////////////////////////////////// // // Global state storage // // Internal error code variable static int LIB_ERR_NAMESPACE_DEF(lib_err, _err_last_error_code) = -1; // Last resolved error code static int LIB_ERR_NAMESPACE_DEF(lib_err, _last_resolved_code) = NULL; // Additional error comment handling static string LIB_ERR_NAMESPACE_DEF(lib_err, _intern_err_comment) = ""; // ////////////////////////////////////////// /* ********************************************************************************************************* * Error code resolver * ********************************************************************************************************* */ //+------------------------------------------------------------------+ //| err_desc() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_DESC #undef DBG_TRACE_ERROR_ERR_DESC #define DBG_TRACE_ERROR_ERR_DESC(x) x #define DBG_TRACE_ERROR_ERR_DESC_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #endif #endif #ifndef DBG_TRACE_ERROR_ERR_DESC #define DBG_TRACE_ERROR_ERR_DESC(x) #define DBG_TRACE_ERROR_ERR_DESC_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// const string LIB_ERR_NAMESPACE_DEF(lib_err, err_desc)(const int err_code = -1, const string txt_prefix = NULL) { DBG_TRACE_ERROR_ERR_DESC( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(err_code); DBG_MSG_VAR(txt_prefix); ); PERF_COUNTER_BEGIN; // Local init int error_code = err_code; int cur_api_err_code = _LastError; string error_string = NULL; DBG_TRACE_ERROR_ERR_DESC( DBG_MSG_VAR(error_code); DBG_MSG_VAR(cur_api_err_code); ); // Check error code input if(error_code < 0) { if(LIB_ERR_NAMESPACE(lib_err, _err_last_error_code) > -1) { error_code = (int)LIB_ERR_NAMESPACE(lib_err, _err_last_error_code); LIB_ERR_NAMESPACE(lib_err, _err_last_error_code) = -1; } if(cur_api_err_code > 0) { error_code = cur_api_err_code; ResetLastError(); } if( (cur_api_err_code == NULL) && (error_code < 1)) { error_code = NULL; } } // Resolve user defined error codes if((error_code >= ERR_USER_ERROR_FIRST) && (error_code <= ERR_USER_ERROR_LAST)) { error_string = StringFormat("%s %s", LIB_ERR_NAMESPACE(lib_err, err_desc_user)(error_code), LIB_ERR_NAMESPACE(lib_err, err_desc_comment)()); } // Resolve MQL API error codes else { error_string = func_ptr_mql_err_codes(error_code); } // Add comment if given if( (txt_prefix != "") && (txt_prefix != NULL)) { error_string = (StringLen(txt_prefix) == NULL) ? error_string : StringFormat("%s: %s", txt_prefix, error_string); } // Save last resolved error code LIB_ERR_NAMESPACE(lib_err, _last_resolved_code) = error_code; // Return resolved error text DBG_TRACE_ERROR_ERR_DESC_RETURN(error_string); } //+------------------------------------------------------------------+ //| err_desc_user() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_DESC_USER #undef DBG_TRACE_ERROR_ERR_DESC_USER #define DBG_TRACE_ERROR_ERR_DESC_USER(x) x #define DBG_TRACE_ERROR_ERR_DESC_USER_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #endif #endif #ifndef DBG_TRACE_ERROR_ERR_DESC_USER #define DBG_TRACE_ERROR_ERR_DESC_USER(x) #define DBG_TRACE_ERROR_ERR_DESC_USER_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// const string LIB_ERR_NAMESPACE_DEF(lib_err, err_desc_user)(const int error_code) { DBG_TRACE_ERROR_ERR_DESC_USER( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(error_code); ); PERF_COUNTER_BEGIN; // Check group id state if(error_groups[(uchar)(error_code >> 0x08)] == NULL) { DBG_TRACE_ERROR_ERR_DESC_USER_RETURN(StringFormat("(%i - %s) %s: %i", error_code, "ERR_USER_ERROR", "Unknown error code. No router for group id", (error_code >> 0x08))); } // Resolve error code to message TUsrErrFunc func_ptr = error_groups[(uchar)(error_code >> 0x08)]; string retval = func_ptr(error_code); // Return result if(StringLen(retval) > 2) { DBG_TRACE_ERROR_ERR_DESC_USER_RETURN(retval); } // Return unknown error code DBG_TRACE_ERROR_ERR_DESC_USER_RETURN(StringFormat("(%i - %s) %s", error_code, "ERR_USER_ERROR", "A description is not available.")); } //+------------------------------------------------------------------+ //| err_desc_comment() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_DESC_COMMENT #undef DBG_TRACE_ERROR_ERR_DESC_COMMENT #define DBG_TRACE_ERROR_ERR_DESC_COMMENT(x) x #define DBG_TRACE_ERROR_ERR_DESC_COMMENT_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #endif #endif #ifndef DBG_TRACE_ERROR_ERR_DESC_COMMENT #define DBG_TRACE_ERROR_ERR_DESC_COMMENT(x) #define DBG_TRACE_ERROR_ERR_DESC_COMMENT_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// const string LIB_ERR_NAMESPACE_DEF(lib_err, err_desc_comment)(const string comment = NULL) { DBG_TRACE_ERROR_ERR_DESC_USER( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(comment); ); PERF_COUNTER_BEGIN; // Store new or additional comment if(comment != NULL) { LIB_ERR_NAMESPACE(lib_err, _intern_err_comment) = StringFormat("%s %s", (LIB_ERR_NAMESPACE(lib_err, _intern_err_comment) == NULL) ? "" : LIB_ERR_NAMESPACE(lib_err, _intern_err_comment), (comment == NULL) ? "" : comment); if(StringSubstr(comment, NULL, 2) != "\r\n") { StringTrimLeft(LIB_ERR_NAMESPACE(lib_err, _intern_err_comment)); } StringTrimRight(LIB_ERR_NAMESPACE(lib_err, _intern_err_comment)); } // Retrieve and clear stored comment else if(StringLen(LIB_ERR_NAMESPACE(lib_err, _intern_err_comment)) > 1) { string tmp = " " + LIB_ERR_NAMESPACE(lib_err, _intern_err_comment); LIB_ERR_NAMESPACE(lib_err, _intern_err_comment) = NULL; DBG_TRACE_ERROR_ERR_DESC_COMMENT_RETURN(tmp); } // Return DBG_TRACE_ERROR_ERR_DESC_COMMENT_RETURN(""); } #ifndef __MQL4_COMPATIBILITY_CODE__ }; // Namespace lib_err:: END #endif // // END Error handler //*********************************************************************************************************************************************************/ //*********************************************************************************************************************************************************/ // Extended version of original MQL API error functions // #ifndef __MQL4_COMPATIBILITY_CODE__ namespace LibError { // Namespace LibError:: BEGIN #endif //+------------------------------------------------------------------+ //| RegisterErrorCodeResolver() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_REG_RESOLVER #undef DBG_TRACE_ERROR_ERR_REG_RESOLVER #define DBG_TRACE_ERROR_ERR_REG_RESOLVER(x) x #define DBG_TRACE_ERROR_ERR_REG_RESOLVER_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #else #endif #endif #ifndef DBG_TRACE_ERROR_ERR_REG_RESOLVER #define DBG_TRACE_ERROR_ERR_REG_RESOLVER(x) #define DBG_TRACE_ERROR_ERR_REG_RESOLVER_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// bool LIB_ERR_NAMESPACE_DEF(LibError, RegisterErrorCodeResolver)(const ushort group_id, const TUsrErrFunc resolver_func_ptr) LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_REG_RESOLVER( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(group_id); DBG_MSG_VAR((resolver_func_ptr != NULL)); ); PERF_COUNTER_BEGIN; // Static init static bool init = false; // Local init uchar _grp_id = (uchar)((group_id > 0xFF) ? (group_id >> 0x08) : group_id); DBG_TRACE_ERROR_ERR_REG_RESOLVER( DBG_MSG_VAR(init); DBG_MSG_VAR(_grp_id); ); // Check init state if(!init) { ZeroMemory(LIB_ERR_NAMESPACE(lib_err, error_groups)); init = true; } // Debug: Compile error (group_ids must be unique) DBG_ASSERT_RETURN_VAR((LIB_ERR_NAMESPACE(lib_err, error_groups)[_grp_id] == NULL), StringFormat("Error: Group ID %i assigned! Check parameter 1 from macro 'LIB_ERR_REGISTER_RESOLVER_BEGIN / _END'", _grp_id), false); // Create new message router LIB_ERR_NAMESPACE(lib_err, error_groups)[_grp_id] = resolver_func_ptr; // Return DBG_TRACE_ERROR_ERR_REG_RESOLVER_RETURN(true); } //+------------------------------------------------------------------+ //| SetMqlErrorCode() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_SETMQLERROR #undef DBG_TRACE_ERROR_ERR_SETMQLERROR #define DBG_TRACE_ERROR_ERR_SETMQLERROR(x) x #define DBG_TRACE_ERROR_ERR_SETMQLERROR_RETURN DBG_MSG_TRACE_RETURN #endif #endif #ifndef DBG_TRACE_ERROR_ERR_SETMQLERROR #define DBG_TRACE_ERROR_ERR_SETMQLERROR(x) #define DBG_TRACE_ERROR_ERR_SETMQLERROR_RETURN DBG_MSG_NOTRACE_RETURN #endif ///////////////////////////////////// void LIB_ERR_NAMESPACE_DEF(LibError, SetMqlErrorCode)( const uint err_code, const string comment = "", const string comment1 = "", const string comment2 = "", const string comment3 = "", const string comment4 = "", const string comment5 = "", const string comment6 = "", const string comment7 = "", const string comment8 = "", const string comment9 = "", const string commentA = "", const string commentB = "", const string commentC = "", const string commentD = "", const string commentE = "", const string commentF = "") LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_SETMQLERROR( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(err_code); DBG_MSG_VAR(comment); DBG_MSG_VAR(comment1); DBG_MSG_VAR(comment2); DBG_MSG_VAR(comment3); DBG_MSG_VAR(comment4); DBG_MSG_VAR(comment5); DBG_MSG_VAR(comment6); DBG_MSG_VAR(comment7); DBG_MSG_VAR(comment8); DBG_MSG_VAR(comment9); DBG_MSG_VAR(commentA); DBG_MSG_VAR(commentB); DBG_MSG_VAR(commentC); DBG_MSG_VAR(commentD); DBG_MSG_VAR(commentE); DBG_MSG_VAR(commentF); ); PERF_COUNTER_BEGIN; // Local init string concat = StringFormat("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", ((comment1 != "") && (comment1 != NULL) ? "\r\n |=> " : "") + comment, ((comment1 != "") && (comment1 != NULL) ? "\r\n |=> " + comment1 : ""), ((comment2 != "") && (comment2 != NULL) ? "\r\n |=> " + comment2 : ""), ((comment3 != "") && (comment3 != NULL) ? "\r\n |=> " + comment3 : ""), ((comment4 != "") && (comment4 != NULL) ? "\r\n |=> " + comment4 : ""), ((comment5 != "") && (comment5 != NULL) ? "\r\n |=> " + comment5 : ""), ((comment6 != "") && (comment6 != NULL) ? "\r\n |=> " + comment6 : ""), ((comment7 != "") && (comment7 != NULL) ? "\r\n |=> " + comment7 : ""), ((comment8 != "") && (comment8 != NULL) ? "\r\n |=> " + comment8 : ""), ((comment9 != "") && (comment9 != NULL) ? "\r\n |=> " + comment9 : ""), ((commentA != "") && (commentA != NULL) ? "\r\n |=> " + commentA : ""), ((commentB != "") && (commentB != NULL) ? "\r\n |=> " + commentB : ""), ((commentC != "") && (commentC != NULL) ? "\r\n |=> " + commentC : ""), ((commentD != "") && (commentD != NULL) ? "\r\n |=> " + commentD : ""), ((commentE != "") && (commentE != NULL) ? "\r\n |=> " + commentE : ""), ((commentF != "") && (commentF != NULL) ? "\r\n |=> " + commentF : "")); DBG_TRACE_ERROR_ERR_SETMQLERROR( DBG_MSG_VAR(short_code); DBG_MSG_VAR(concat); ); // Set comment, if supplied LIB_ERR_NAMESPACE(lib_err, err_desc_comment)(concat); // Set error code LIB_ERR_NAMESPACE(lib_err, _err_last_error_code) = (int)err_code; DBG_TRACE_ERROR_ERR_SETMQLERROR( DBG_MSG_VAR(LIB_ERR_NAMESPACE(lib_err, _err_last_error_code)); DBG_MSG_VAR(LIB_ERR_NAMESPACE(lib_err, err_desc)(LIB_ERR_NAMESPACE(lib_err, _err_last_error_code))); ); // Return DBG_TRACE_ERROR_ERR_SETMQLERROR_RETURN; } //+------------------------------------------------------------------+ //| SetUserErrorCode() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_SETUSERERROR #undef DBG_TRACE_ERROR_ERR_SETUSERERROR #define DBG_TRACE_ERROR_ERR_SETUSERERROR(x) x #define DBG_TRACE_ERROR_ERR_SETUSERERROR_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #endif #endif #ifndef DBG_TRACE_ERROR_ERR_SETUSERERROR #define DBG_TRACE_ERROR_ERR_SETUSERERROR(x) #define DBG_TRACE_ERROR_ERR_SETUSERERROR_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// bool LIB_ERR_NAMESPACE_DEF(LibError, SetUserErrorCode)(const uint err_code, const string comment = "", const string comment1 = "", const string comment2 = "", const string comment3 = "", const string comment4 = "", const string comment5 = "", const string comment6 = "", const string comment7 = "", const string comment8 = "", const string comment9 = "", const string commentA = "", const string commentB = "", const string commentC = "", const string commentD = "", const string commentE = "", const string commentF = "") LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_SETUSERERROR( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(err_code); DBG_MSG_VAR(comment); DBG_MSG_VAR(comment1); DBG_MSG_VAR(comment2); DBG_MSG_VAR(comment3); DBG_MSG_VAR(comment4); DBG_MSG_VAR(comment5); DBG_MSG_VAR(comment6); DBG_MSG_VAR(comment7); DBG_MSG_VAR(comment8); DBG_MSG_VAR(comment9); DBG_MSG_VAR(commentA); DBG_MSG_VAR(commentB); DBG_MSG_VAR(commentC); DBG_MSG_VAR(commentD); DBG_MSG_VAR(commentE); DBG_MSG_VAR(commentF); ); PERF_COUNTER_BEGIN; // Local init const ushort short_code = (ushort)err_code; string concat = StringFormat("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", ((comment1 != "") && (comment1 != NULL) ? "\r\n |=> " : "") + comment, ((comment1 != "") && (comment1 != NULL) ? "\r\n |=> " + comment1 : ""), ((comment2 != "") && (comment2 != NULL) ? "\r\n |=> " + comment2 : ""), ((comment3 != "") && (comment3 != NULL) ? "\r\n |=> " + comment3 : ""), ((comment4 != "") && (comment4 != NULL) ? "\r\n |=> " + comment4 : ""), ((comment5 != "") && (comment5 != NULL) ? "\r\n |=> " + comment5 : ""), ((comment6 != "") && (comment6 != NULL) ? "\r\n |=> " + comment6 : ""), ((comment7 != "") && (comment7 != NULL) ? "\r\n |=> " + comment7 : ""), ((comment8 != "") && (comment8 != NULL) ? "\r\n |=> " + comment8 : ""), ((comment9 != "") && (comment9 != NULL) ? "\r\n |=> " + comment9 : ""), ((commentA != "") && (commentA != NULL) ? "\r\n |=> " + commentA : ""), ((commentB != "") && (commentB != NULL) ? "\r\n |=> " + commentB : ""), ((commentC != "") && (commentC != NULL) ? "\r\n |=> " + commentC : ""), ((commentD != "") && (commentD != NULL) ? "\r\n |=> " + commentD : ""), ((commentE != "") && (commentE != NULL) ? "\r\n |=> " + commentE : ""), ((commentF != "") && (commentF != NULL) ? "\r\n |=> " + commentF : "")); //StringTrimRight(concat); DBG_TRACE_ERROR_ERR_SETUSERERROR( DBG_MSG_VAR(short_code); DBG_MSG_VAR(concat); ); // Set comment, if supplied LIB_ERR_NAMESPACE(lib_err, err_desc_comment)(concat); // Set error code LIB_ERR_NAMESPACE(lib_err, _err_last_error_code) = short_code + ERR_USER_ERROR_FIRST; ResetLastError(); SetUserError(short_code); DBG_TRACE_ERROR_ERR_SETUSERERROR( DBG_MSG_VAR(LIB_ERR_NAMESPACE(lib_err, _err_last_error_code)); DBG_MSG_VAR(LIB_ERR_NAMESPACE(lib_err, err_desc)(LIB_ERR_NAMESPACE(lib_err, _err_last_error_code))); ); // Return DBG_TRACE_ERROR_ERR_SETUSERERROR_RETURN((err_code & 0x0000FFFF) != NULL); } //+------------------------------------------------------------------+ //| ResetUserErrorCode() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_RESETUSERERROR #undef DBG_TRACE_ERROR_ERR_RESETUSERERROR #define DBG_TRACE_ERROR_ERR_RESETUSERERROR(x) x #define DBG_TRACE_ERROR_ERR_RESETUSERERROR_RETURN DBG_MSG_TRACE_RETURN #endif #endif #ifndef DBG_TRACE_ERROR_ERR_RESETUSERERROR #define DBG_TRACE_ERROR_ERR_RESETUSERERROR(x) #define DBG_TRACE_ERROR_ERR_RESETUSERERROR_RETURN DBG_MSG_NOTRACE_RETURN #endif ///////////////////////////////////// void LIB_ERR_NAMESPACE_DEF(LibError, ResetUserErrorCode)() LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_RESETUSERERROR( DBG_MSG_TRACE_BEGIN; DBG_MSG_VAR(LIB_ERR_NAMESPACE(lib_err, _err_last_error_code)); ); PERF_COUNTER_BEGIN; // Reset error code LIB_ERR_NAMESPACE(lib_err, _err_last_error_code) = -1; LIB_ERR_NAMESPACE(lib_err, err_desc_comment)(); ResetLastError(); // Return DBG_TRACE_ERROR_ERR_RESETUSERERROR_RETURN; } //+------------------------------------------------------------------+ //| ResolveLastErrorCode() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_RESOLVELASTERROR #undef DBG_TRACE_ERROR_ERR_RESOLVELASTERROR #define DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(x) x #define DBG_TRACE_ERROR_ERR_RESOLVELASTERROR_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #else #endif #endif #ifndef DBG_TRACE_ERROR_ERR_RESOLVELASTERROR #define DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(x) #define DBG_TRACE_ERROR_ERR_RESOLVELASTERROR_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// int LIB_ERR_NAMESPACE_DEF(LibError, ResolveLastErrorCode)(string& error_msg) LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(DBG_MSG_TRACE_BEGIN); PERF_COUNTER_BEGIN; // Resolve code to text error_msg = LIB_ERR_NAMESPACE(lib_err, err_desc)(); DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(DBG_MSG_VAR(error_msg)); // Return DBG_TRACE_ERROR_ERR_RESOLVELASTERROR_RETURN(LIB_ERR_NAMESPACE(lib_err, _last_resolved_code)); } string LIB_ERR_NAMESPACE_DEF(LibError, ResolveLastErrorCode)() LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(DBG_MSG_TRACE_BEGIN); PERF_COUNTER_BEGIN; // Resolve and return DBG_TRACE_ERROR_ERR_RESOLVELASTERROR_RETURN(LIB_ERR_NAMESPACE(lib_err, err_desc)()); } string LIB_ERR_NAMESPACE_DEF(LibError, ResolveLastErrorCode)(int& error_code) LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(DBG_MSG_TRACE_BEGIN); PERF_COUNTER_BEGIN; // Local init const string error_msg = LIB_ERR_NAMESPACE(lib_err, err_desc)(); // Resolve error error_code = LIB_ERR_NAMESPACE(lib_err, _last_resolved_code); DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(DBG_MSG_VAR(error_msg)); DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(DBG_MSG_VAR(error_code)); // Return DBG_TRACE_ERROR_ERR_RESOLVELASTERROR_RETURN(error_msg); } string LIB_ERR_NAMESPACE_DEF(LibError, ResolveLastErrorCode)(const int err_no, const string prefix) LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_RESOLVELASTERROR(DBG_MSG_TRACE_BEGIN); PERF_COUNTER_BEGIN; // Resolve and return DBG_TRACE_ERROR_ERR_RESOLVELASTERROR_RETURN(LIB_ERR_NAMESPACE(lib_err, err_desc)(err_no, prefix)); } //+------------------------------------------------------------------+ //| GetLastResolvedErrorCode() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR #undef DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR #define DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR(x) x #define DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #endif #endif #ifndef DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR #define DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR(x) #define DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// int LIB_ERR_NAMESPACE_DEF(LibError, GetLastResolvedErrorCode)() LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR(DBG_MSG_TRACE_BEGIN); PERF_COUNTER_BEGIN; // Return DBG_TRACE_ERROR_ERR_LASTRESOLVEDERROR_RETURN((LIB_ERR_NAMESPACE(lib_err, _last_resolved_code) == -1) ? ERR_SUCCESS : LIB_ERR_NAMESPACE(lib_err, _last_resolved_code)); } //+------------------------------------------------------------------+ //| GetLastErrorCode() | //+------------------------------------------------------------------+ ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_ERR_LASTERRORCODE #undef DBG_TRACE_ERROR_ERR_LASTERRORCODE #define DBG_TRACE_ERROR_ERR_LASTERRORCODE(x) x #define DBG_TRACE_ERROR_ERR_LASTERRORCODE_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #endif #endif #ifndef DBG_TRACE_ERROR_ERR_LASTERRORCODE #define DBG_TRACE_ERROR_ERR_LASTERRORCODE(x) #define DBG_TRACE_ERROR_ERR_LASTERRORCODE_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// int LIB_ERR_NAMESPACE_DEF(LibError, GetLastErrorCode)() LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_ERR_LASTERRORCODE(DBG_MSG_TRACE_BEGIN); PERF_COUNTER_BEGIN; // Check current state if(LIB_ERR_NAMESPACE(lib_err, _err_last_error_code) <= ERR_SUCCESS) { // Resolve error code LIB_ERR_NAMESPACE(lib_err, err_desc)(-1); // Return DBG_TRACE_ERROR_ERR_LASTERRORCODE_RETURN(LIB_ERR_NAMESPACE(lib_err, _last_resolved_code)); } // Return DBG_TRACE_ERROR_ERR_LASTERRORCODE_RETURN(LIB_ERR_NAMESPACE(lib_err, _err_last_error_code)); } //+------------------------------------------------------------------+ //| DefaultOnError() | //+------------------------------------------------------------------+ ///////////////////////////////////////////////////////// // // DefaultOnError() Function // // Generic error handling function. // Some return codes are not of interest, so // they get sorted out here and are // surpressed of being journaled. // #ifndef LIB_ERR_USER_ERROR_HANDLER #define LIB_ERR_DEFAULT_HANDLER ///////////////////////////////////// // Function debug trace code #ifdef LIB_DEBUG #ifdef DBG_TRACE_ERROR_DEFAULT_ONERROR #undef DBG_TRACE_ERROR_DEFAULT_ONERROR #define DBG_TRACE_ERROR_DEFAULT_ONERROR(x) x #define DBG_TRACE_ERROR_DEFAULT_ONERROR_RETURN(x) DBG_MSG_TRACE_RETURN_VAR(x) #endif #endif #ifndef DBG_TRACE_ERROR_DEFAULT_ONERROR #define DBG_TRACE_ERROR_DEFAULT_ONERROR(x) #define DBG_TRACE_ERROR_DEFAULT_ONERROR_RETURN(x) DBG_MSG_NOTRACE_RETURN_VAR(x) #endif ///////////////////////////////////// const bool LIB_ERR_NAMESPACE_DEF(LibError, DefaultOnError)(uint& err_no, const string prefix = NULL) LIB_ERR_LIB_EXPORT { DBG_TRACE_ERROR_DEFAULT_ONERROR(DBG_MSG_TRACE_BEGIN); PERF_COUNTER_BEGIN; // Local init #ifdef LIB_DEBUG const static bool exec_env = false; #else const static bool exec_env = (MQLInfoInteger(MQL_PROFILER) || MQLInfoInteger(MQL_FORWARD) || MQLInfoInteger(MQL_OPTIMIZATION) || MQLInfoInteger(MQL_FRAME_MODE)) && (!MQLInfoInteger(MQL_VISUAL_MODE) || !MQLInfoInteger(MQL_DEBUG)); #endif err_no = (uint)_LastError; const uint err = (err_no > NULL) ? err_no : ((LIB_ERR_NAMESPACE(lib_err, _err_last_error_code) < NULL) ? NULL : LIB_ERR_NAMESPACE(lib_err, _err_last_error_code)); const uint err_mask = 0x000000FF | (0x0000FF00 * (((err & 0xFFFF0000) == NULL) & 0x00000001)); const bool err_warn = ((err & LIB_ERR_LEVEL_WARNING) == LIB_ERR_LEVEL_WARNING); DBG_TRACE_ERROR_DEFAULT_ONERROR( DBG_MSG_VAR(err) ); // Success code if((err & err_mask) == ERR_SUCCESS) { // Reset error code LIB_ERR_NAMESPACE(lib_err, _err_last_error_code) = -1; ResetUserErrorCode(); DBG_TRACE_ERROR_DEFAULT_ONERROR_RETURN(false); } // Warnings else if((err_mask == 0x000000FF) && ((err & LIB_ERR_LEVEL_WARNING) == LIB_ERR_LEVEL_WARNING)) #ifdef LIB_ERR_LEVEL_WARNING_AS_ERROR { printf("%s", LIB_ERR_NAMESPACE(lib_err, err_desc)(-1, prefix)); DBG_TRACE_ERROR_DEFAULT_ONERROR_RETURN(true); } #else { printf("%s", LIB_ERR_NAMESPACE(lib_err, err_desc)(-1, prefix)); DBG_TRACE_ERROR_DEFAULT_ONERROR_RETURN(false); } #endif // Handled error codes show as error or are given as non error, depending on execution environment else if( (exec_env) || ((err_mask == 0x000000FF) && ((err & LIB_ERR_LEVEL_HANDLED_ERROR) == LIB_ERR_LEVEL_HANDLED_ERROR))) { DBG_TRACE_ERROR_DEFAULT_ONERROR_RETURN(!exec_env); } // Resolve and print error message printf("%s", LIB_ERR_NAMESPACE(lib_err, err_desc)(-1, prefix)); // Return error state DBG_TRACE_ERROR_DEFAULT_ONERROR_RETURN(true); } #endif #ifndef __MQL4_COMPATIBILITY_CODE__ }; // Namespace LibError:: END #endif // // END Extended version of original MQL API SetUserError() //*********************************************************************************************************************************************************/ /**************************************/ #endif // LIB_ERROR_MAIN_CODE_MQH_INCLUDED