EA-Setka-2/Libs/MQL5Trace/Trace.mqh

193 lines
19 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:50:44 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Trace |
//| Copyright 2006-2011, www.FXmaster.de |
//| www.FXmaster.de |
//+------------------------------------------------------------------+
#property copyright "Copyright 2006-2011, www.FXmaster.de"
#property link "www.FXmaster.de"
#include "Tree.mqh"
class CTraceView; // ?@5420@8B5;L=>5 >1JO2;5=85
//------------------------------------------------------------------ class CTraceCtrl
class CTraceCtrl
{
public:
CTreeCtrl *m_stack; // >1J5:B 3@0D0
CTreeCtrl *m_prop; // >1J5:B A?8A:0 A2>9AB2
CTreeCtrl *m_file; // 3@C??8@>2:0 ?> D09;0<
CTreeCtrl *m_class; // 3@C??8@>2:0 ?> :;0AA0<
CTraceView* m_traceview; // C:070B5;L =0 >B>1@065=85 :;0AA0
CNode* m_cur; // C:070B5;L =0 B5:CI89 C75;
public:
CTraceCtrl() { Create(); Reset(); } // A>740;8 B@59A5@
~CTraceCtrl() { delete m_stack; delete m_prop; delete m_file; delete m_class; } // C40;8;8 B@59A5@
void Create(); // A>740;8 B@59A5@
void In(string apath, string afile, int aline, string atext, string adesc, int aid); // 2E>4 2 C:070==K9 C75;
void Out(int aid); // 2KE>4 4> C:070==>3> C7;0
bool StepBack(); // 2KE>4 87 C7;0 =0 >48= H03 225@E (?5@5E>4 =0 @>48B5;O)
void Reset() { m_cur=m_stack.m_root; m_stack.Reset(); m_file.Reset(); m_class.Reset(); } // A1@>A 2A5E C7;>2
void Clear() { m_cur=m_stack.m_root; m_stack.Clear(); m_file.Clear(); m_class.Clear(); } // A1@>A 2A5E C7;>2
public:
void AddWatch(string name, string val); // ?@>25@:0 45103 @568<0 4;O C7;0
void Break(); // ?0C70 4;O C7;0
};
//------------------------------------------------------------------ CTraceCtrl
void CTraceCtrl::Create()
{
m_stack=new CTreeCtrl; m_stack.m_root.m_text="TRACE"; m_stack.m_mode=1; // A>740;8 >1J5:B 3@0D0
m_prop=new CTreeCtrl; m_prop.m_root.m_text="INFO"; // A>740;8 >1J5:B 3@0D0
m_file=new CTreeCtrl; m_file.m_root.m_text="FILE"; // A>740;8 >1J5:B 3@0D0
m_class=new CTreeCtrl; m_class.m_root.m_text="CLASS"; // A>740;8 >1J5:B 3@0D0
m_cur=m_stack.m_root; // CAB0=>28;8 C:070B5;L =0 :>@5=L
m_stack.m_bBreak=true;
}
//------------------------------------------------------------------ In
void CTraceCtrl::In(string apath, string afile, int aline, string atext, string adesc, int aid)
{
if (NIL(m_stack) || NIL(m_cur)) return; // ?@028;L=>ABL C:070B5;O
if (aid>=0) Out(aid); // 5A;8 7040= B@51C5<K9 C75;, B> ?5@5E>48< =0 =53>
// ?@>25@O5< 8<5=0 C65 8<5NI8EAO C7;>2
int i, size=ArraySize(m_cur.m_next); // 27O;8 A?8A>: 25B>: =>40
bool b=false, ident;
for (i=0; i<size; i++) // 8I5< 2 25B:0E B5:CI53> =>40 B@51C5<>5 8<O
{
if (NIL(m_cur.m_next[i])) continue; // ?@028;L=>ABL C:070B5;O
if (m_cur.m_next[i].m_text==atext) { b=true; break; } // 5A;8 =0H;8, B> ?>8A: >AB0=02;8205<
}
ident=(m_cur.m_file==afile && m_cur.m_line==aline && m_cur.m_path==apath);
if (b)
{
m_cur=m_cur.m_next[i]; // ?5@5428=C;8AL : A;54CNI5<C C7;C
m_cur.m_desc=adesc; // 7040;8 0B@81CB
}
else if (!ident)// 5A;8 C75; =5 =0945= 8 MB> =5 B5:CI89, B> A>7405< =>2K9 C75;
{
ArrayResize(m_cur.m_next, size+1); // @0AH8@8;8 <0AA82
m_cur.m_next[size]=new CNode; // A>740;8 C75;
if (NIL(m_cur.m_next[size])) return; // ?@>25@8;8
m_stack.m_maxid++; // C25;8G8;8 3;>10;L=K9 AG5BG8:
m_cur.m_next[size].m_prev=m_cur; // ?>AB028;8 C:070B5;L =0 @>48B5;O
m_cur=m_cur.m_next[size]; // ?5@5<5AB8;8 B5:CI89 C:070B5;L =0 =>2K9 C75;
m_cur.m_id=m_stack.m_maxid; m_cur.m_text=atext;
// 7040;8 0B@81CBK
string afunc=atext, aclass="__base__"; int k=StringFind(atext, "::");
if (k>0) { aclass=StringSubstr(atext, 0, k); afunc=StringSubstr(atext, k+2); }
m_cur.m_path=apath; m_cur.m_file=afile; m_cur.m_line=aline;
m_cur.m_func=afunc; m_cur.m_class=aclass; m_cur.m_desc=adesc;
// 3@C??8@C5< 2 45@52LO
m_stack.SortBy(TG_TEXT, true);
m_file.Clear(); m_stack.GroupBy(TG_FILE, m_file); m_file.SortBy(TG_TEXT, true);
m_class.Clear(); m_stack.GroupBy(TG_CLASS, m_class); m_class.SortBy(TG_TEXT, true);
}
m_cur.m_uses++;
m_cur.m_tick0=GetTickCount(); m_cur.m_last=TimeLocal(); // 7040;8 G8A;> >1@0I5=89 8 2@5<O 2E>40
}
//------------------------------------------------------------------ Out
void CTraceCtrl::Out(int aid)
{
if (aid<0) { StepBack(); return; }
CNode *node=m_stack.FindNode(aid); if (NIL(node)) return; // =0H;8 C75; B@51C5<>3> id
while (m_cur!=node) if (!StepBack()) break; // 2KE>48< 87 C7;>2, ?>:0 =5 4>AB83=5< B@51C5<>3>
if (m_cur!=node) m_cur=node; // 5A;8 2 A>A54=59 25B:5, B> ?5@5?@K38205<
if (NIL(m_cur)) m_cur=node; // 5A;8 B5:CI89 =5 C:070=, B> 70405<
}
//------------------------------------------------------------------ StepBack
bool CTraceCtrl::StepBack()
{
if (NIL(m_stack.m_root)) { Print("-err Out root"); return(false); } // ?@028;L=>ABL C:070B5;O
if (NIL(m_cur)) { m_cur=m_stack.m_root; return(false); } // ?@028;L=>ABL C:070B5;O
if (m_cur.m_tick0>0) m_cur.m_tick+=GetTickCount()-m_cur.m_tick0; m_cur.m_tick0=0; // ?>4AG8B0;8 2@5<O
if (m_cur==m_stack.m_root) return(false); // 5A;8 C65 =0 25@ECH:5
if (NIL(m_cur.m_prev)) { Print("-err Out "+m_cur.m_text+"("+(string)m_cur.m_id+")"); return(false); } // ?@028;L=>ABL C:070B5;O
m_cur=m_cur.m_prev; // ?5@5H;8 : @>48B5;LA:><C C7;C
return(true);
}
//------------------------------------------------------------------ AddWatch
void CTraceCtrl::AddWatch(string name, string val) // 4>1028;5=85 Watch-?5@5<5==>9 2 B5:CI89 C75;
{
if (!NIL(m_trace) && !NIL(m_trace.m_cur)) m_trace.m_cur.AddWatch(name, val);
}
//------------------------------------------------------------------ Break
void CTraceCtrl::Break() // ?@>25@:0 45103 @568<0 4;O C7;0
{
if (NIL(m_traceview) || NIL(m_stack)) return; // ?@>25@:0 20;84=>AB8
if (!m_stack.m_bBreak) return; // ?@>25@:0 @07@5H5==>AB8 451030
m_stack.BreakBy(TG_ALL, NULL, false); // C1@0;8 D;038 m_break A> 2A5E CI;>2
m_cur.m_break=true; // 0:B828@>20;8 B>;L:> =0 B5:CI5<
m_traceview.m_viewstack.m_sid=m_cur.m_id; // ?5@5=5A;8 2K45;5=85 =0 =53>
m_stack.ExpandBy(TG_UP, m_cur, true, m_cur); // @0A:@K;8 @>48B5;LA:85 C7;K, 5A;8 70:@KBK
m_traceview.Draw(); // >B@8A>20;8 2A5
string namedbg=m_traceview.m_viewstack.m_name+string(m_cur.m_id)+".dbg"; // ?>;CG8;8 8<O :=>?:8 BREAK
string name=m_traceview.m_viewstack.m_name+".break"; // ?>;CG8;8 8<O :=>?:8 BREAK
bool state=ObjectGetInteger(m_traceview.m_chart, namedbg, OBJPROP_STATE);
while(!state) // ?>:0 :=>?:0 =5 =060B0, 2K?>;=O5< F8:;
{
Sleep(500); // A45;0;8 ?0C7C
state=ObjectGetInteger(m_traceview.m_chart, namedbg, OBJPROP_STATE); // ?@>25@O5< 5Q A>AB>O=85
if (!m_traceview.IsOpenView()) break; // 5A;8 >:=> 70:@KB>, B> 2KE>48<
m_stack.m_bBreak=ObjectGetInteger(m_traceview.m_chart, name, OBJPROP_STATE); // ?@>25@O5< 5Q A>AB>O=85
state=state || !m_stack.m_bBreak; // CG8BK205< A>AB>O=85 :=>?:8 0:B82=>AB8 451030 A8AB5<K
m_traceview.Draw(); // >B@8A>20;8 2>7<>6=K5 87<5=5=8O
}
m_cur.m_break=false; // C1@0;8 D;03
m_traceview.Draw(); // >B@8A>20;8 >1=>2;5=85
}
//------------------------------------------------------------------ CIn
class CIn
{
public:
void In(string apath, string afile, int aline, string afunc, string adesc)
{
if (NIL(m_trace)) return; // 5A;8 =5B 3@0D0, B> 2KE>48<
if (NIL(m_trace.m_stack)) return;
if (NIL(m_trace.m_stack.m_root)) return;
if (NIL(m_trace.m_cur)) m_trace.m_cur=m_trace.m_stack.m_root;
m_trace.In(apath, afile, aline, afunc, adesc, -1); // 2>H;8 2 A;54CNI89
if (m_trace.m_cur.m_brkuse>0 && m_trace.m_cur.m_uses>=m_trace.m_cur.m_brkuse) // 5A;8 4>AB83;8 G8A;0 2K7>2>2
m_trace.Break(); //B> 2E>48< 2 45103
}
void ~CIn() { if (!NIL(m_trace)) m_trace.Out(-1); } // 2KH;8 2KH5
};
// >?@545;5=85 <0:@>A>2
#ifdef TRACE
#define _IN(desc) CIn _in; _in.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN1(desc) CIn _in1; _in1.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN2(desc) CIn _in2; _in2.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN3(desc) CIn _in3; _in3.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN4(desc) CIn _in4; _in4.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN5(desc) CIn _in5; _in5.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _WATCH(w, v) if (!NIL(m_trace)) if (!NIL(m_trace.m_cur)) m_trace.m_cur.AddWatch(w, string(v));
#define _BRKUSES(u) if (!NIL(m_trace)) if (!NIL(m_trace.m_cur)) if (m_trace.m_cur.m_brkuse==-2) m_trace.m_cur.m_brkuse=long(u);
#include "View\TraceView.mqh" // ?>4:;NG05< >?8A0=85 :;0AA0
#ifndef __MQL4__
extern CTraceCtrl* m_trace; // 548=AB25==K9 M:75<?;O@ B@0AA8@>2I8:0
#else
CTraceCtrl* m_trace; // 548=AB25==K9 M:75<?;O@ B@0AA8@>2I8:0
#endif
#else //TRACE
#define _IN(desc) ;// CIn _in; _in.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN1(desc) ;// CIn _in1; _in1.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN2(desc) ;// CIn _in2; _in2.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN3(desc) ;// CIn _in3; _in3.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN4(desc) ;// CIn _in4; _in4.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _IN5(desc) ;// CIn _in5; _in5.In(__PATH__, __FILE__, __LINE__, __FUNCTION__, string(desc))
#define _WATCH(w, v) ;// if (!NIL(m_trace)) if (!NIL(m_trace.m_cur)) m_trace.m_cur.AddWatch(w, string(v));
#define _BRKUSES(u) ;//if (!NIL(m_trace)) if (!NIL(m_trace.m_cur)) if (m_trace.m_cur.m_brkuse==-2) m_trace.m_cur.m_brkuse=long(u);
#endif //TRACE