webu
Full Member
Posts: 145
|
Post by webu on Sept 25, 2018 14:37:34 GMT 1
Greetings to everybody in all countries from a sunny Germany! :-)
I try it once in the german-help-area, but nobody answered me, so i try it here now.
I clicked in "Properties" -> "Compiler" -> "Trace & Assert Level" the item "In IDE and in Exe" and I hoped, that Tron, Troff, Trace$ etc. than will work also in Exe. In the help under "Trace$" i have read this very well
"In a stand-alone program (EXE) the Tron command is ignored. ...",
but I hoped, that the compiler-setting would change this?
|
|
|
Post by scalion on Oct 4, 2018 21:04:30 GMT 1
Hello Webu, Sorry but that's not work, no setting exist to have an effective tron/trace in compiler. Now you can use an alternate way... Waiting for my next post I'm going to program a little utility for you. See you soon.
|
|
|
Post by scalion on Oct 5, 2018 14:47:25 GMT 1
Try this code, he insert a call to MyTracingProc() for each lines of your desired g32 project and save it. After you must load MyCompilableTracing.g32 then you can modify the content of this proc before compiling to do what you want (it upgradable but i think you dont have much time):
FullW 1 : Void SetForegroundWindow(Me.hWnd) : AutoRedraw = 1 Global Long i, NL = 0, EOP = 0 Global String FileName Global Dim L(10000) As String FileSelect "*.g32", "", FileName If Exist(FileName) Open FileName for Input As # 1 While Not EOF(# 1) Inc NL : Line Input # 1, L(NL) If UCase(Trim(L(NL))) = "$DATFILE" And EOP = 0 EOP = NL - 1 If Len(Trim(L(NL))) = 0 And EOP = 0 Dec NL Wend Close # 1 If EOP = 0 EOP = NL EndIf If NL = 0 Message "No lines to process." : End Ocx TextBox tb tb.Enabled = 0 tb.Left = 10 : tb.Top = 10 : tb.Width = _X - 20 : tb.Height = _Y - 20 tb.MultiLine = True tb.SelText = "' You can use Proc MyTracingProc(MyTrace) to perform operations"#13#10 tb.SelText = "' that will work after compiling"#13#10 For i = 1 To EOP tb.SelText = "MyTracingProc " & G32ToString(L(i)) & #13#10 tb.SelText = L(i) & #13#10 Next i tb.SelText = "Proc MyTracingProc(MyTrace As String)"#13#10"'Here your tracing code."#13#10"EndProc"#13#10 For i = EOP + 1 To NL tb.SelText = L(i) & #13#10 Next i Message "Now saving g32 with compilable tracing. Its MyCompilableTracing.g32" Open "MyCompilableTracing.g32" for Output As # 1 Print # 1, tb.Text Close # 1 Me.Close Message "End" Function G32ToString(L As String) As String Local Long i, lc = 0 Local String Result = "" For i = 1 To Len(L) If Mid(L, i, 1) = #34 If lc = 0 Result = Result & #34 Result = Result & "#34" : lc = 1 Else If Mid(L, i, 1) = #39 If lc = 0 Result = Result & #34 Result = Result & "#39" : lc = 1 Else If lc = 1 Result = Result & #34 Result = Result & Mid(L, i, 1) : lc = 0 EndIf Next i Return #34 & Result & #34 EndFunc
|
|
webu
Full Member
Posts: 145
|
Post by webu on Oct 5, 2018 18:04:25 GMT 1
Ok, but does somebody know, what is ment with this compiler-option "In IDE and in Exe" in "Trace & Assert Level"?
Many thanks for your code as a help, i will try it.
I had already been founded something similar because I noticed I that the compiler option did not work in that way i suppose. But my simple version only inserts one call to a debug-Proc in the first line of every Proc/Sub. Example-result-code:
---------------- Proc Work(bla$) dbg("Work") Do something Until MouseK
Proc work_more(blubb$) dbg("work_more") Do something Until MouseK
Proc dbg(a$) Debug (a$) Return ----------------
|
|
|
Post by scalion on Oct 5, 2018 21:27:38 GMT 1
Hello, In fact, the "Assert & Trace Level" compiler option in the "Opt.Code" pane concerns only the "debug" command. However maybe it's a mistake not to have planned a compilation of the TRON and TROFF commands. I think we could create an extra menu "compile with TRON / TROFF" since the commands gfa_compile and gfa_docompile exist. If you are interested I can schedule it but it will take a little time so it will be patient. Have a nice day.
|
|
|
Post by scalion on Oct 14, 2018 21:50:14 GMT 1
Ok, hello all ! I wrote an extension to compile a program with the following instructions: TRON (including "TRON Procedure") TROFF TraceLnr Trace $ SrcCode $ () TraceReg TraceReg (Register)
A new menu in "extra" menu will appear for this.
Download the GfaCompileTracing.Gll (14.5 KB)_ and place it in GFA-Basic 32 Path (like C:\Program Files (x86)\GB32), next you must go to the "Extra / Load+Config Gll" to adding this extension.
Take a look to the source code :
(***********************************************************) (* GFA-BASIC 32 EDITOR EXTENSIONS *) (***********************************************************) Sub Gfa_init // wird automatisch beim Laden des Basic aufgerufen
Global CurrentLanguage As Int = Gfa_IntSetting("Language") ' 0 = English, 1 = Deutsch
DefineLanguageStrings
Gfa_AddMenu Gfa_Menu_CompileWithTrace, Do_Menu_CompileWithTrace
EndSub Sub DefineLanguageStrings
If CurrentLanguage = 0 Global String Gfa_Menu_CompileWithTrace = "Compile with tracing" Else Global String Gfa_Menu_CompileWithTrace = "Kompiliere eine Exe mit Tracing" EndIf
End Sub Sub Do_Menu_CompileWithTrace(i%)
Local String L, Lc Local String e, e2, ePred, eBPred Local Long Lidx, VnameIdx = 0, Fidx = 0, Eidx, NL, k, NSrcCode Local Boolean CDirty, Ok, Lchg, InTypeDef = False
Local String VnameFlagTraceOnOff = UniqueName("CFLAGTRACEONOFF") Local String VnameTraceLnr = UniqueName("CTRACELNR") Local String VnameTrace = UniqueName("CTRACESTRING") Local String VnameTraceReg = UniqueName("CTRACEREG") Local String VnameProcTrace = UniqueName("CTRACEPROC") Local String VnameDefProcTrace = UniqueName("CDEFTRACEPROC") Local String VnameTRON = UniqueName("CTRON") Local String VnameTROFF = UniqueName("CTROFF") Local String VNameProcAddr = UniqueName("CTRACEPROCADDR") Local String VnameTraceRegSet = UniqueName("CTRACEREGSET") Local String VnameTraceRegAdr = UniqueName("CTRACEREGADR") Local String VnameSrcCode = UniqueName("CSRCCODEARRAY") Local String VnameSrcCodeFunc = UniqueName("CSRCCODEFUNC") Local String VNameFtrace = UniqueName("F_TRACE") Local String VNameLB = UniqueName("LB_TRACE") Local Dim VNameReg(28) As String Local Dim Register(28) As String Local Dim ReadCmd(28) As String Local Dim RegOffset(28) As String
Register(1) = "EDI" : ReadCmd(1) = "LPEEK" : RegOffset(1) = "" Register(2) = "ESI" : ReadCmd(2) = "LPEEK" : RegOffset(2) = "+4" Register(3) = "ESP" : ReadCmd(3) = "LPEEK" : RegOffset(3) = "+8" Register(4) = "EBP" : ReadCmd(4) = "LPEEK" : RegOffset(4) = "+12" Register(5) = "EBX" : ReadCmd(5) = "LPEEK" : RegOffset(5) = "+16" Register(6) = "EDX" : ReadCmd(6) = "LPEEK" : RegOffset(6) = "+20" Register(7) = "ECX" : ReadCmd(7) = "LPEEK" : RegOffset(7) = "+24" Register(8) = "EAX" : ReadCmd(8) = "LPEEK" : RegOffset(8) = "+28" Register(9) = "EFL" : ReadCmd(9) = "LPEEK" : RegOffset(9) = "+32" Register(10) = "EIP" : ReadCmd(10) = "LPEEK" : RegOffset(10) = "+36" Register(11) = "DI" : ReadCmd(11) = "DPEEK" : RegOffset(11) = "+2" Register(12) = "SI" : ReadCmd(12) = "DPEEK" : RegOffset(12) = "+6" Register(13) = "SP" : ReadCmd(13) = "DPEEK" : RegOffset(13) = "+10" Register(14) = "BP" : ReadCmd(14) = "DPEEK" : RegOffset(14) = "+14" Register(15) = "BX" : ReadCmd(15) = "DPEEK" : RegOffset(15) = "+18" Register(16) = "DX" : ReadCmd(16) = "DPEEK" : RegOffset(16) = "+22" Register(17) = "CX" : ReadCmd(17) = "DPEEK" : RegOffset(17) = "+26" Register(18) = "AX" : ReadCmd(18) = "DPEEK" : RegOffset(18) = "+30" Register(19) = "IP" : ReadCmd(19) = "DPEEK" : RegOffset(19) = "+38" Register(20) = "BL" : ReadCmd(20) = "PEEK" : RegOffset(20) = "+19" Register(21) = "DL" : ReadCmd(21) = "PEEK" : RegOffset(21) = "+23" Register(22) = "CL" : ReadCmd(22) = "PEEK" : RegOffset(22) = "+27" Register(23) = "AL" : ReadCmd(23) = "PEEK" : RegOffset(23) = "+31" Register(24) = "FL" : ReadCmd(24) = "PEEK" : RegOffset(24) = "+35" Register(25) = "BH" : ReadCmd(25) = "PEEK" : RegOffset(25) = "+18" Register(26) = "DH" : ReadCmd(26) = "PEEK" : RegOffset(26) = "+22" Register(27) = "CH" : ReadCmd(27) = "PEEK" : RegOffset(27) = "+26" Register(28) = "AH" : ReadCmd(28) = "PEEK" : RegOffset(28) = "+30" ' Local CO As Control ' Set CO = OCX(Gfa_hWndED) ' CO.Enabled = False For k = 1 To 28 VNameReg(k) = UniqueName("CREG" & Chr(64 + k) & "_" & Register(28)) Next k CDirty = Gfa_Dirty NL = Gfa_LineCnt NSrcCode = NL Local Dim LB(NL * 6 + 1000) As String Local Dim ListingRestore(NL + 1) Local Dim LBITD(NL * 6 + 1000) As Long Local Dim CSRCCODE(NL + 1) As String
For Lidx = 1 To NL LB(Lidx) = Gfa_Text(Lidx - 1) ListingRestore(Lidx) = LB(Lidx) CSRCCODE(Lidx) = VnameSrcCode & "(" & Trim(Lidx) & ")=" & G32ToString(LB(Lidx)) Next Lidx
For Lidx = 1 To NL
L = LB(Lidx) Lc = "" If Len(L) > 0 Eidx = 0 e = "" ePred = "" Lc = "" Lchg = False Do
Inc Eidx eBPred = ePred ePred = e e = G32Element(L, Eidx)
If Len(e) = 0 If UCase(ePred) = "TRON" e = VnameDefProcTrace Else Exit Do EndIf EndIf
If UCase(e) = "TRACELNR" e = VnameTraceLnr : Lchg = True If UCase(e) = "TRACE$" e = VnameTrace : Lchg = True If UCase(e) = "SRCCODE$" e = VnameSrcCodeFunc : Lchg = True
If UCase(e) = "TRACEREG" Lchg = True If G32Element(L, Eidx + 1) = "(" And G32Element(L, Eidx + 3) = ")" e2 = UCase(G32Element(L, Eidx + 2)) For k = 1 To 28 If e2 = Register(k) e = ReadCmd(k) & "(" & VnameTraceRegAdr & RegOffset(k) & ")" Add Eidx, 3 Exit For EndIf Next k Else e = VnameTraceRegAdr EndIf EndIf
If UCase(ePred) = "TRON" Lchg = True If InStr("_ABCDEFGHIJKLMNOPQRSTUVWXYZ", UCase(Mid(e, 1, 1))) > 0 e = "ProcAddr(" & e & ")" Else e = "ProcAddr(" & VnameDefProcTrace & ")" EndIf EndIf
'Type toto : - Long a : b As Double : EndType If UCase(e) = "TYPE" And (Eidx = 1 Or ePred = ":") InTypeDef = True Else If (UCase(e) = "TYPE" And UCase(ePred) = "END") Or UCase(e) = "ENDTYPE" InTypeDef = False EndIf If UCase(e) = "TRON" And (Eidx = 1 Or ePred = ":") Lchg = True Lc = Lc & " " & VnameTRON Else If UCase(e) = "TROFF" Lchg = True Lc = Lc & " " & VnameTROFF Else Lc = Lc & " " & e EndIf Loop If Lchg = True LB(Lidx) = Lc EndIf EndIf LBITD(Lidx) = InTypeDef Next Lidx
For Lidx = NL DownTo 1
If Len(LB(Lidx)) > 0 e = G32Element(LB(Lidx), 1) If InStr(" PROC PROCEDURE FUNC FUNCTION SUB ", " " & UCase(e) & " ") = 0 And LBITD(Lidx) = False And LBITD(Lidx - 1) = False Insert LB(Lidx) = "If " & VnameFlagTraceOnOff & "=True " Insert LB(Lidx + 1) = VnameTraceLnr & "=" & Trim(Lidx) & " : " & VnameTrace & "=" & VnameSrcCode & "(" & VnameTraceLnr & ") : " & VnameProcTrace Insert LB(Lidx + 2) = "Endif" Insert LBITD(Lidx) = False Insert LBITD(Lidx + 1) = False Insert LBITD(Lidx + 2) = False Add NL, 3 EndIf
EndIf Next Lidx
For Lidx = NSrcCode DownTo 1 Insert LB(1) = CSRCCODE(Lidx) Next Lidx Add NL, NSrcCode
Insert LB(1) = VnameTraceRegAdr & "=Malloc(40)" Insert LB(1) = "Global long " & VnameTraceLnr & "," & VNameProcAddr & "," & VnameTraceRegAdr Insert LB(1) = "Global Boolean " & VnameFlagTraceOnOff & "=False" Insert LB(1) = "Global String " & VnameTrace Insert LB(1) = "Global Dim " & VnameSrcCode & "(" & Trim(NSrcCode) & ") as String" Add NL, 5
'VnameSrcCodeFunc Inc NL : LB(NL) = "Function " & VnameSrcCodeFunc & "( P as long ) as String" Inc NL : LB(NL) = " If P<1 or P>" & Trim(NSrcCode) & " Return "#34#34 Inc NL : LB(NL) = " Return " & VnameSrcCode & "(P)" Inc NL : LB(NL) = "EndFunc"
Inc NL : LB(NL) = "Proc " & VnameTRON & "( P as long )" Inc NL : LB(NL) = VNameProcAddr & " = P" Inc NL : LB(NL) = VnameFlagTraceOnOff & "=True" Inc NL : LB(NL) = "EndProc"
Inc NL : LB(NL) = "Proc " & VnameProcTrace Inc NL : LB(NL) = "CFLAGTRACEONOFF = False" Inc NL : LB(NL) = VnameTraceRegSet Inc NL : LB(NL) = "~StdCall(" & VNameProcAddr & ")()" Inc NL : LB(NL) = "CFLAGTRACEONOFF = True" Inc NL : LB(NL) = "EndProc"
Inc NL : LB(NL) = "Proc " & VnameTraceRegSet Inc NL : LB(NL) = "GetRegs" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & ", _EDI" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+4, _ESI" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+8, _ESP" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+12, _EBP" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+16, _EBX" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+20, _EDX" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+24, _ECX" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+28, _EAX" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+32, _EFL" Inc NL : LB(NL) = "LPoke " & VnameTraceRegAdr & "+36, _EIP" Inc NL : LB(NL) = "EndProc"
Inc NL : LB(NL) = "Proc " & VnameTROFF Inc NL : LB(NL) = VnameFlagTraceOnOff & "=False" Inc NL : LB(NL) = "EndProc" ' Inc NL : LB(NL) = "Proc " & VnameDefProcTrace Inc NL : LB(NL) = "Print " & VnameTraceLnr & ";"#34":"#34";" & VnameTrace Inc NL : LB(NL) = "EndProc"
Gfa_Line = 0 Gfa_CtrlP Gfa_DeleteLines Gfa_LineCnt + 1
For Lidx = 1 To NL Gfa_Insert LB(Lidx) & #13#10 Next Lidx
'Message "Code modifié"
Gfa_Compile
Gfa_Line = 0 Gfa_CtrlP Gfa_DeleteLines Gfa_LineCnt + 1
For Lidx = 1 To NSrcCode Gfa_Insert ListingRestore(Lidx) & #13#10 Next Lidx
Gfa_Dirty = CDirty
Erase LB() Erase LBITD() Erase VNameReg() Erase Register() Erase ReadCmd() Erase RegOffset() Erase CSRCCODE() Erase ListingRestore() 'CO.Enabled = True
EndSub Function UniqueName(BaseName As String) As String
Local String Vname, V Local Long k, VnameIdx = 0, Lidx Local Boolean Ok
For k = 1 To Len(BaseName) V = Mid(BaseName, k, 1) If k = 1 If InStr("ABCDEFGHIJKLMNOPQRSTUVWXYZ_", UCase(V)) = 0 Mid(BaseName, k, 1) = "_" EndIf Else If InStr("ABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789", UCase(V)) = 0 Mid(BaseName, k, 1) = "_" EndIf EndIf Next k
Vname = BaseName Do Ok = True For Lidx = 1 To Gfa_LineCnt If InStr(UCase(Gfa_Text(Lidx - 1)), UCase(Vname)) > 0 Ok = False : Exit For EndIf Next Lidx If Ok = False Inc VnameIdx Vname = BaseName & Trim(VnameIdx) EndIf Loop Until Ok = True
Return Vname
EndFunc Proc StandardCode
Local Long Lidx, i Local Boolean InString Local String L, v ' Separate multiple command to multiline Lidx = 1 Do
L = Gfa_Text(Lidx) InString = False For i = 1 To Len(L) v = Mid(L, i, 1) If v = #34 If InString = False InString = True Else If i < Len(L) If Mid(L, i + 1, 1) <> #34 InString = False EndIf EndIf EndIf EndIf Next i
Loop
EndProc Function G32Element(L As String, Index%) As String
Local Long Scan, Vindex, ElementBegin Local String V, VV, VVV Local Boolean AcceptOperator = False Local Boolean AcceptComment = True Local Boolean AcceptNumber = False Local Boolean AcceptString = False Local Boolean NumberPoint = False Local Boolean NumberExp = False Local Boolean ElementWithPoint = False
Scan = 1 Vindex = 0 Do
Do V = Mid(L, Scan, 1) If V = " " If Scan < Len(L) Inc Scan Else Return "" EndIf Else Exit Do EndIf Loop
Inc Vindex
VV = Mid(L & " ", Scan, 2) VVV = Mid(L & " ", Scan, 3)
If VV = "/*" // a comment maybe in middle ElementBegin = Scan Add Scan, 2 Do VV = Mid(L & " ", Scan, 2) If VV = "*/" If Vindex = Index Return Mid(L, ElementBegin, 2 + Scan - ElementBegin) EndIf Add Scan, 2 Exit Do Else Inc Scan EndIf Loop Else If VV = "//" Or V = #39 // a comment at end If Vindex = Index Return Mid(L, Scan) Return "" Else If V = "°" // a comment line
If Index = 1 Return L Return ""
Else If V = #34 // a string constant
ElementBegin = Scan Inc Scan Do V = Mid(L, Scan, 1) VV = Mid(L & " ", Scan, 2) Inc Scan Exit If (V = #34 And VV <> #34#34) If VV = #34#34 Inc Scan Loop Until Scan > Len(L) If Vindex = Index Return Mid(L, ElementBegin, Scan - ElementBegin)
Else If InStr(" >>= <<= ", " " & VVV & " ") > 0
If Vindex = Index Return VVV Add Scan, 3
Else If InStr(" ++ -- += -= /* *= %= &= |= ^= %| %& && == := ^^ << <> => >= <= =< <> >< != ", " " & VV & " ") > 0
'a = a => 7 %& 1 =< 3 >= 1 <= 2 <> 3 >< 4 != 2 If Vindex = Index Return VV Add Scan, 2
Else If Mid(VV, 2, 1) = " " ' A single caracter
If Vindex = Index Return V Add Scan, 2
Else If InStr("+-(),!~#@", V) > 0
If Vindex = Index Return V Inc Scan
Else If (V = "." And InStr("0123456789", Mid(VV, 2, 1)) > 0) Or InStr("0123456789", V) > 0
' A number ElementBegin = Scan NumberPoint = False NumberExp = False Do V = Mid(L, Scan, 1) If V = "." And NumberPoint = False NumberPoint = True Inc Scan Else If NumberExp = False And InStr("+-", V) > 0 And UCase(Mid(L, Scan - 1, 1)) = "E" NumberExp = True Inc Scan Else If InStr("0123456789", V) > 0 Inc Scan Else Exit Do EndIf Loop Until Scan > Len(L) If Vindex = Index Return Mid(L, ElementBegin, Scan - ElementBegin)
Else If InStr("_ABCDEFGHIJKLMNOPQRSTUVWXYZ", UCase(V)) > 0 ' A keyword (command,object,function,proc,var,operator,etc...) ElementBegin = Scan ElementWithPoint = False Do V = UCase(Mid(L, Scan, 1)) If V = "." ElementWithPoint = True If InStr("_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.", UCase(V)) > 0 Inc Scan Else Exit Do EndIf Loop Until Scan > Len(L) If ElementWithPoint = False If Scan <= Len(L) If InStr("|&$%#!", Mid(L, Scan, 1)) > 0 Inc Scan EndIf If Vindex = Index Return Mid(L, ElementBegin, Scan - ElementBegin) Else If Vindex = Index Return Mid(L, ElementBegin) Return "" EndIf Else If Vindex = Index Return Mid(L, ElementBegin, Scan - ElementBegin) EndIf
Else // Something... If Vindex = Index Return Mid(L, Scan) Return "" EndIf
Loop Until Scan > Len(L)
Return ""
EndFunc Function G32ToString(L As String) As String Local Long i, lc = 0 Local String Result = "" For i = 1 To Len(L) If Mid(L, i, 1) = #34 If lc = 0 Result = Result & #34 Result = Result & "#34" : lc = 1 Else If Mid(L, i, 1) = #39 If lc = 0 Result = Result & #34 Result = Result & "#39" : lc = 1 Else If lc = 1 Result = Result & #34 Result = Result & Mid(L, i, 1) : lc = 0 EndIf Next i Return #34 & Result & #34 EndFunc
This is a small "mill" or "gas plant" if you prefer, which inserts an extra code for each line of code. This additional code verifies if the tracing is active and accordingly calls the procedure passed in Tron parameter. If no procedure is passed as a parameter a default procedure is called which displays the line number and the corresponding source code. Of course your original code is restored after compilation.
Have a nice day
|
|
|
Post by scalion on Oct 15, 2018 8:53:46 GMT 1
Hello, Just a little update for this gll extension : in addition of TRON,TROFF,TraceLnr,Trace$,SrcCode$(),TraceReg,TraceReg(Register) we have now ProcLnr(Procname) and ProcLineCnt(Procname) i forgeted in first version. You have only to replace actual GfaCompileTracing.gll and restart Gfa-Basic 32.
Note sometime, due to an asynchronous events there an error message, this due to an insertion error on first line, but i can't correcting this bug at this time. In case of error, just edit your first line to correct (simple double insertion in general) and retry. Sometime there's no error in your code but in modified code that not appear.
|
|
webu
Full Member
Posts: 145
|
Post by webu on Oct 15, 2018 12:55:40 GMT 1
Thank you for your doing!
First of all, I have to deal with inserting and using GLL, because I have never done that! :-)
|
|
|
Post by scalion on Oct 15, 2018 20:07:03 GMT 1
Thank you for your attendance. Have you been able to install the extension and do you have any comments regarding the operation or need help installing it? Good night.
|
|