debugger.tcp.bmx 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292
  1. SuperStrict
  2. Import "debugger.glue.c"
  3. NoDebug
  4. Import BRL.Socket
  5. Import pub.stdc
  6. ?win32
  7. Include "deref_win32.bmx"
  8. ?linux
  9. Include "deref_linux.bmx"
  10. ?macos
  11. Include "deref_macos.bmx"
  12. ?
  13. Private
  14. Const derefFailure:String = "{?}"
  15. Const derefSymbol:String = "->"
  16. ?Win32
  17. Extern "Win32"
  18. Const SW_SHOW:Int=5
  19. Const SW_RESTORE:Int=9
  20. Function IsIconic:Int( hwnd:Byte Ptr )="WINBOOL IsIconic( HWND )!"
  21. Function GetForegroundWindow:Byte Ptr()="HWND GetForegroundWindow()!"
  22. Function SetForegroundWindow:Int( hwnd:Byte Ptr )="WINBOOL SetForegroundWindow( HWND )!"
  23. Function ShowWindow:Int( hwnd:Byte Ptr,cmdShow:Int )="WINBOOL ShowWindow( HWND ,int )!"
  24. Function GetCurrentThreadId:Int()="DWORD GetCurrentThreadId()!"
  25. End Extern
  26. ?
  27. ?MacOS
  28. Extern
  29. Function CGDisplayIsCaptured:Int( displayId:Int )
  30. End Extern
  31. ?
  32. Extern
  33. Function bbIsMainThread:Int()="bbIsMainThread"
  34. Function bbGCValidate:Int( mem:Byte Ptr ) = "int bbGCValidate( void * )!"
  35. Function DebugScopeName:String( scope:Int Ptr )="bmx_debugger_DebugScopeName"
  36. Function bmx_debugger_DebugScopeKind:UInt( scope:Int Ptr )
  37. Function bmx_debugger_DebugScopeDecl:Byte Ptr( scope:Int Ptr )
  38. Function DebugDeclName:String( decl:Int Ptr )="bmx_debugger_DebugDeclName"
  39. Function bmx_debugger_DebugDeclType:String( decl:Int Ptr )
  40. Function bmx_debugger_DebugDeclKind:UInt( decl:Int Ptr )
  41. Function bmx_debugger_DebugDeclNext:Byte Ptr( decl:Int Ptr )
  42. Function bmx_debugger_DebugDecl_VarAddress:Byte Ptr( decl:Int Ptr )
  43. Function bmx_debugger_DebugDecl_ConstValue:String( decl:Int Ptr )
  44. Function bmx_debugger_DebugDecl_FieldOffset:Byte Ptr(decl:Int Ptr, inst:Byte Ptr)
  45. Function bmx_debugger_DebugDecl_StringFromAddress:String( addr:Byte Ptr )
  46. Function bmx_debugger_DebugDeclTypeChar:Int( decl:Int Ptr, index:Int )
  47. Function bmx_debugger_DebugDecl_ArraySize:Int( decl:Byte Ptr )
  48. Function bmx_debugger_DebugDecl_ArrayDecl:Byte Ptr(inst:Byte Ptr)
  49. Function bmx_debugger_DebugDecl_ArrayDeclIndexedPart(decl:Byte Ptr, inst:Byte Ptr, index:Int)
  50. Function bmx_debugger_DebugDecl_ArrayDeclFree(decl:Byte Ptr)
  51. Function bmx_debugger_DebugDecl_clas:Byte Ptr( inst:Byte Ptr )
  52. Function bmx_debugger_DebugDecl_isStringClass:Int( clas:Byte Ptr )
  53. Function bmx_debugger_DebugDecl_isArrayClass:Int( clas:Byte Ptr )
  54. Function bmx_debugger_DebugDecl_isBaseObject:Int( clas:Byte Ptr )
  55. Function bmx_debugger_DebugClassSuper:Byte Ptr(clas:Byte Ptr)
  56. Function bmx_debugger_DebugClassScope:Byte Ptr(clas:Byte Ptr)
  57. Function DebugStmFile:String( stm:Int Ptr )="bmx_debugger_DebugStmFile"
  58. Function DebugStmLine:Int( stm:Int Ptr )="bmx_debugger_DebugStmLine"
  59. Function DebugStmChar:Int( stm:Int Ptr )="bmx_debugger_DebugStmChar"
  60. Function DebugBreakOnLine:Int( stm:Int Ptr )="bmx_debugger_DebugBreakOnLine"
  61. Function bmx_debugger_ref_bbNullObject:Byte Ptr()
  62. Function bmx_debugger_ref_bbEmptyArray:Byte Ptr()
  63. Function bmx_debugger_ref_bbEmptyString:Byte Ptr()
  64. Function bmx_debugger_ref_brl_blitz_NullFunctionError:Byte Ptr()
  65. Function bbObjectStructInfo:Byte Ptr(name:Byte Ptr)="BBDebugScope * bbObjectStructInfo( char * )!"
  66. Function bmx_debugger_DebugEnumDeclValue:String(decl:Byte Ptr, val:Byte Ptr)
  67. Function bmx_debugger_AddBreakpoint:Int(filename:String, line:Int)
  68. Function bmx_debugger_RemoveBreakpoint:Int(filename:String, line:Int)
  69. Function bmx_snprintf:Int(buf:Byte Ptr, size:Size_T, num:Size_T)
  70. End Extern
  71. ?Not ptr64
  72. Function ToHex$( val:Int )
  73. Local buf:Short[8]
  74. For Local k:Int=7 To 0 Step -1
  75. Local n:Int=(val&15)+Asc("0")
  76. If n>Asc("9") n=n+(Asc("A")-Asc("9")-1)
  77. buf[k]=n
  78. val:Shr 4
  79. Next
  80. Return String.FromShorts( buf,8 ).ToLower()
  81. End Function
  82. ?ptr64
  83. Function ToHex$( val:Long )
  84. Local buf:Short[16]
  85. For Local k:Int=15 To 0 Step -1
  86. Local n:Int=(val&15)+Asc("0")
  87. If n>Asc("9") n=n+(Asc("A")-Asc("9")-1)
  88. buf[k]=n
  89. val:Shr 4
  90. Next
  91. Return String.FromShorts( buf,16 ).ToLower()
  92. End Function
  93. ?
  94. Function IsAlpha:Int( ch:Int )
  95. Return (ch>=Asc("a") And ch<=Asc("z")) Or (ch>=Asc("A") And ch<=Asc("Z"))
  96. End Function
  97. Function IsNumeric:Int( ch:Int )
  98. Return ch>=Asc("0") And ch<=Asc("9")
  99. End Function
  100. Function IsAlphaNumeric:Int( ch:Int )
  101. Return IsAlpha(ch) Or IsNumeric(ch)
  102. End Function
  103. Function IsUnderscore:Int( ch:Int )
  104. Return ch=Asc("_")
  105. End Function
  106. Function Ident$( tag$ Var )
  107. If Not tag Return ""
  108. If Not IsAlpha( tag[0] ) And Not IsUnderscore( tag[0] ) Return ""
  109. Local i:Int=1
  110. While i<tag.length And (IsAlphaNumeric(tag[i]) Or IsUnderscore(tag[i]))
  111. i:+1
  112. Wend
  113. Local id$=tag[..i]
  114. tag=tag[i..]
  115. Return id
  116. End Function
  117. Function TypeName$( tag$ Var )
  118. Local t$=tag[..1]
  119. tag=tag[1..]
  120. Select t
  121. Case "b"
  122. Return "Byte"
  123. Case "s"
  124. Return "Short"
  125. Case "i"
  126. Return "Int"
  127. Case "u"
  128. Return "UInt"
  129. Case "l"
  130. Return "Long"
  131. Case "y"
  132. Return "ULong"
  133. Case "j"
  134. Return "Int128"
  135. Case "f"
  136. Return "Float"
  137. Case "d"
  138. Return "Double"
  139. Case "h"
  140. Return "Float64"
  141. Case "k"
  142. Return "Float128"
  143. Case "m"
  144. Return "Double128"
  145. Case "$"
  146. Return "String"
  147. Case "z"
  148. Return "CString"
  149. Case "w"
  150. Return "WString"
  151. Case "t"
  152. Return "Size_T"
  153. Case "W"
  154. Return "WParam"
  155. Case "X"
  156. Return "LParam"
  157. Case ":","?","#","@","/"
  158. Local id$=Ident( tag )
  159. While tag And tag[0]=Asc(".")
  160. tag=tag[1..]
  161. id=Ident( tag )
  162. Wend
  163. If Not id DebugError "Invalid object typetag"
  164. Return id
  165. Case "*"
  166. Return TypeName( tag )+" Ptr"
  167. Case "["
  168. Local length:Int
  169. While tag[..1]=","
  170. tag=tag[1..]
  171. t:+","
  172. Wend
  173. While IsNumeric(tag[0])
  174. length = length * 10 + Int(tag[..1])
  175. tag=tag[1..]
  176. Wend
  177. If tag[..1]<>"]" DebugError "Invalid array typetag"
  178. tag=tag[1..]
  179. If length Then
  180. Return TypeName( tag )+t+length+"]"
  181. Else
  182. Return TypeName( tag )+t+"]"
  183. End If
  184. Case "("
  185. If tag[..1]<>")"
  186. t:+TypeName( tag )
  187. While tag[..1]=","
  188. tag=tag[1..]
  189. t:+","+TypeName( tag )
  190. Wend
  191. If tag[..1]<>")" DebugError "Invalid function typetag"
  192. EndIf
  193. tag=tag[1..]
  194. Return TypeName( tag )+t+")"
  195. End Select
  196. If Not tag.length Return ""
  197. DebugError "Invalid debug typetag:"+t
  198. End Function
  199. 'int offsets into 12 byte DebugStm struct
  200. 'Const DEBUGSTM_FILE=0
  201. 'Const DEBUGSTM_LINE=1
  202. 'Const DEBUGSTM_CHAR=2
  203. 'int offsets into 16 byte DebugDecl struct
  204. 'Const DEBUGDECL_KIND=0
  205. 'Const DEBUGDECL_NAME=1
  206. 'Const DEBUGDECL_TYPE=2
  207. 'Const DEBUGDECL_ADDR:Int=3
  208. 'DEBUGDECL_KIND values
  209. Const DEBUGDECLKIND_END:Int=0
  210. Const DEBUGDECLKIND_CONST:Int=1
  211. Const DEBUGDECLKIND_LOCAL:Int=2
  212. Const DEBUGDECLKIND_FIELD:Int=3
  213. Const DEBUGDECLKIND_GLOBAL:Int=4
  214. Const DEBUGDECLKIND_VARPARAM:Int=5
  215. Const DEBUGDECLKIND_TYPEMETHOD:Int=6
  216. Const DEBUGDECLKIND_TYPEFUNCTION:Int=7
  217. 'int offsets into 12+n_decls*4 byte DebugScope struct
  218. 'Const DEBUGSCOPE_KIND=0
  219. 'Const DEBUGSCOPE_NAME=1
  220. 'Const DEBUGSCOPE_DECLS=2
  221. 'DEBUGSCOPE_KIND values
  222. Const DEBUGSCOPEKIND_FUNCTION:Int=1
  223. Const DEBUGSCOPEKIND_TYPE:Int=2
  224. Const DEBUGSCOPEKIND_LOCAL:Int=3
  225. Const DEBUGSCOPEKIND_INTERFACE:Int=4
  226. Const DEBUGSCOPEKIND_STRUCT:Int=5
  227. Function DebugError( t$ )
  228. WriteStderr "Debugger Error:"+t+"~n"
  229. End
  230. End Function
  231. Function DebugDeclKind$( decl:Int Ptr )
  232. Select bmx_debugger_DebugDeclKind(decl)
  233. Case DEBUGDECLKIND_CONST Return "Const"
  234. Case DEBUGDECLKIND_LOCAL Return "Local"
  235. Case DEBUGDECLKIND_FIELD Return "Field"
  236. Case DEBUGDECLKIND_GLOBAL Return "Global"
  237. Case DEBUGDECLKIND_VARPARAM Return "Local"
  238. End Select
  239. DebugError "Invalid decl kind"
  240. End Function
  241. Function DebugDeclType$( decl:Int Ptr )
  242. Local t$=bmx_debugger_DebugDeclType(decl)
  243. Local ty$=TypeName( t )
  244. Return ty
  245. End Function
  246. Function DebugDeclSize:Int( decl:Int Ptr )
  247. Local tag:Int=bmx_debugger_DebugDeclTypeChar(decl, 0)
  248. Select tag
  249. Case Asc("b") Return 1
  250. Case Asc("s") Return 2
  251. Case Asc("i") Return 4
  252. Case Asc("u") Return 4
  253. Case Asc("f") Return 4
  254. Case Asc("l") Return 8
  255. Case Asc("y") Return 8
  256. Case Asc("d") Return 8
  257. Case Asc("h") Return 8
  258. Case Asc("j") Return 16
  259. Case Asc("k") Return 16
  260. Case Asc("m") Return 16
  261. ' size_t (t) fall-through to ptr64 size below
  262. End Select
  263. ?Not ptr64
  264. Return 4
  265. ?ptr64
  266. Return 8
  267. ?
  268. End Function
  269. Function DebugEscapeString$( s$ )
  270. If s.length>4096 s=s[..4096]
  271. s=s.Replace( "~~","~~~~")
  272. s=s.Replace( "~0","~~0" )
  273. s=s.Replace( "~t","~~t" )
  274. s=s.Replace( "~n","~~n" )
  275. s=s.Replace( "~r","~~r" )
  276. s=s.Replace( "~q","~~q" )
  277. Return "~q"+s+"~q"
  278. End Function
  279. Function DebugDeclValue$( decl:Int Ptr,inst:Byte Ptr )
  280. If bmx_debugger_DebugDeclKind(decl)=DEBUGDECLKIND_CONST
  281. Return DebugEscapeString(bmx_debugger_DebugDecl_ConstValue(decl))
  282. End If
  283. Local p:Byte Ptr
  284. Select bmx_debugger_DebugDeclKind(decl)
  285. Case DEBUGDECLKIND_GLOBAL
  286. p=bmx_debugger_DebugDecl_VarAddress(decl)
  287. Case DEBUGDECLKIND_LOCAL
  288. p=bmx_debugger_DebugDecl_VarAddress(decl)
  289. Case DEBUGDECLKIND_FIELD
  290. p=bmx_debugger_DebugDecl_FieldOffset(decl, inst)
  291. Case DEBUGDECLKIND_VARPARAM
  292. p=bmx_debugger_DebugDecl_VarAddress(decl)
  293. ?Not ptr64
  294. p=Byte Ptr ( (Int Ptr p)[0] )
  295. ?ptr64
  296. p=Byte Ptr ( (Long Ptr p)[0] )
  297. ?
  298. Default
  299. DebugError "Invalid decl kind"
  300. End Select
  301. Local tag:Int=bmx_debugger_DebugDeclTypeChar(decl, 0)
  302. Select tag
  303. Case Asc("b")
  304. Return String.FromInt( (Byte Ptr p)[0] )
  305. Case Asc("s")
  306. Return String.FromInt( (Short Ptr p)[0] )
  307. Case Asc("i")
  308. Return String.FromInt( (Int Ptr p)[0] )
  309. Case Asc("u")
  310. Return String.FromUInt( (UInt Ptr p)[0] )
  311. Case Asc("l")
  312. Return String.FromLong( (Long Ptr p)[0] )
  313. Case Asc("y")
  314. Return String.FromULong( (ULong Ptr p)[0] )
  315. Case Asc("f")
  316. Return String.FromFloat( (Float Ptr p)[0] )
  317. Case Asc("d")
  318. Return String.FromDouble( (Double Ptr p)[0] )
  319. Case Asc("t")
  320. Return String.FromSizet( (Size_T Ptr p)[0] )
  321. ?win32
  322. Case Asc("W")
  323. Return String.FromWParam( (WParam Ptr p)[0] )
  324. Case Asc("X")
  325. Return String.FromLParam( (LParam Ptr p)[0] )
  326. ?
  327. Case Asc("$")
  328. p=(Byte Ptr Ptr p)[0]
  329. Return DebugEscapeString( bmx_debugger_DebugDecl_StringFromAddress(p) )
  330. Case Asc("z")
  331. p=(Byte Ptr Ptr p)[0]
  332. If Not p Return "Null"
  333. Local s$=String.FromCString( p )
  334. Return DebugEscapeString( s )
  335. Case Asc("w")
  336. p=(Byte Ptr Ptr p)[0]
  337. If Not p Return "Null"
  338. Local s$=String.FromWString( Short Ptr p )
  339. Return DebugEscapeString( s )
  340. Case Asc("*"),Asc("?"),Asc("#")
  341. Local deref:String
  342. If tag = Asc("*") Then deref = DebugDerefPointer(decl, p)
  343. ?Not ptr64
  344. Return "$" + ToHex( (Int Ptr p)[0] ) + deref
  345. ?ptr64
  346. Return "$" + ToHex( (Long Ptr p)[0] ) + deref
  347. ?
  348. Case Asc("(")
  349. p=(Byte Ptr Ptr p)[0]
  350. If p=bmx_debugger_ref_brl_blitz_NullFunctionError() Return "Null"
  351. Case Asc(":")
  352. p=(Byte Ptr Ptr p)[0]
  353. If p=bmx_debugger_ref_bbNullObject() Return "Null"
  354. If p=bmx_debugger_ref_bbEmptyArray() Return "Null[]"
  355. If p=bmx_debugger_ref_bbEmptyString() Return "Null$"
  356. Case Asc("[")
  357. p=(Byte Ptr Ptr p)[0]
  358. If Not p Return "Null"
  359. If IsNumeric(bmx_debugger_DebugDeclTypeChar(decl, 1)) Then
  360. Local index:Int = 1
  361. Local length:Int
  362. While IsNumeric(bmx_debugger_DebugDeclTypeChar(decl, index))
  363. length = length * 10 + Int(Chr(bmx_debugger_DebugDeclTypeChar(decl, index)))
  364. index :+ 1
  365. Wend
  366. ?Not ptr64
  367. Return "$"+ToHex( Int p ) + "^" + length
  368. ?ptr64
  369. Return "$"+ToHex( Long p ) + "^" + length
  370. ?
  371. End If
  372. If Not bmx_debugger_DebugDecl_ArraySize(p) Return "Null"
  373. Case Asc("@")
  374. ?Not ptr64
  375. Return "$"+ToHex( Int p ) + "@" + bmx_debugger_DebugDeclType(decl)[1..]
  376. ?ptr64
  377. Return "$"+ToHex( Long p ) + "@" + bmx_debugger_DebugDeclType(decl)[1..]
  378. ?
  379. Case Asc("h")
  380. Return Float Ptr (Varptr p)[0] + "," + Float Ptr (Varptr p)[1]
  381. Case Asc("j")
  382. Return Int Ptr (Varptr p)[0] + "," + Int Ptr (Varptr p)[1] + "," + Int Ptr (Varptr p)[2] + "," + Int Ptr (Varptr p)[3]
  383. Case Asc("k")
  384. Return Float Ptr (Varptr p)[0] + "," + Float Ptr (Varptr p)[1] + "," + Float Ptr (Varptr p)[2] + "," + Float Ptr (Varptr p)[3]
  385. Case Asc("m")
  386. Return Double Ptr(Varptr p)[0] + "," + Double Ptr (Varptr p)[1]
  387. Case Asc("/")
  388. Return bmx_debugger_DebugEnumDeclValue(decl, p)
  389. Default
  390. DebugError "Invalid decl typetag:"+Chr(tag)
  391. End Select
  392. ?Not ptr64
  393. Return "$"+ToHex( Int p )
  394. ?ptr64
  395. Return "$"+ToHex( Long p )
  396. ?
  397. End Function
  398. Function DebugScopeKind$( scope:Int Ptr )
  399. Select bmx_debugger_DebugScopeKind(scope)
  400. Case DEBUGSCOPEKIND_FUNCTION Return "Function"
  401. Case DEBUGSCOPEKIND_TYPE Return "Type"
  402. Case DEBUGSCOPEKIND_LOCAL Return "Local"
  403. Case DEBUGSCOPEKIND_INTERFACE Return "Interface"
  404. Case DEBUGSCOPEKIND_STRUCT Return "Struct"
  405. End Select
  406. DebugError "Invalid scope kind"
  407. End Function
  408. Function DebugDerefPointer:String(decl:Int Ptr, pointer:Byte Ptr)
  409. Const derefFailure:String = "{?}"
  410. Const derefSymbol:String = "->"
  411. Local declType:String = DebugDeclType(decl)
  412. Local dataType:String = declType
  413. Local ptrDepth:Int = 0
  414. While dataType.EndsWith(" Ptr")
  415. dataType = dataType[..dataType.length - " Ptr".length]
  416. ptrDepth :+ 1
  417. Wend
  418. Local result:String = ""
  419. Local dataSize:Size_T
  420. Select dataType
  421. Case "Byte" dataSize = SizeOf(Byte Null)
  422. Case "Short" dataSize = SizeOf(Short Null)
  423. Case "Int" dataSize = SizeOf(Int Null)
  424. Case "UInt" dataSize = SizeOf(UInt Null)
  425. Case "Long" dataSize = SizeOf(Long Null)
  426. Case "ULong" dataSize = SizeOf(ULong Null)
  427. Case "Size_T" dataSize = SizeOf(Size_T Null)
  428. Case "Float" dataSize = SizeOf(Float Null)
  429. Case "Double" dataSize = SizeOf(Double Null)
  430. ? Ptr64
  431. Case "Float64" dataSize = SizeOf(Float64 Null)
  432. Case "Float128" dataSize = SizeOf(Float128 Null)
  433. Case "Double128" dataSize = SizeOf(Double128 Null)
  434. Case "Int128" dataSize = SizeOf(Int128 Null)
  435. ? Win32
  436. Case "WParam" dataSize = SizeOf(WParam Null)
  437. Case "LParam" dataSize = SizeOf(LParam Null)
  438. ?
  439. Default dataSize = 0 ' cannot dereference this
  440. EndSelect
  441. Local buffer:Byte Ptr = MemAlloc(Size_T(Max(dataSize, SizeOf(Byte Ptr Null))))
  442. (Byte Ptr Ptr buffer)[0] = Null
  443. Local res:Int
  444. ?win32
  445. result = DebugDerefPointerWin32(dataSize, ptrDepth, pointer, buffer, res)
  446. ?linux
  447. result = DebugDerefPointerLinux(dataSize, ptrDepth, pointer, buffer, res)
  448. ?macos
  449. result = DebugDerefPointerMacos(dataSize, ptrDepth, pointer, buffer, res)
  450. ?
  451. If Not res Then
  452. Return result
  453. End If
  454. Local value:String
  455. Select dataType
  456. Case "Byte" value = String((Byte Ptr buffer)[0])
  457. Case "Short" value = String((Short Ptr buffer)[0])
  458. Case "Int" value = String((Int Ptr buffer)[0])
  459. Case "UInt" value = String((UInt Ptr buffer)[0])
  460. Case "Long" value = String((Long Ptr buffer)[0])
  461. Case "ULong" value = String((ULong Ptr buffer)[0])
  462. Case "Size_T" value = String((Size_T Ptr buffer)[0])
  463. Case "Float" value = String((Float Ptr buffer)[0])
  464. Case "Double" value = String((Double Ptr buffer)[0])
  465. ? Ptr64
  466. Case "Float64" value = String((Float Ptr buffer)[0]) + "," + ..
  467. String((Float Ptr buffer)[1])
  468. Case "Float128" value = String((Float Ptr buffer)[0]) + "," + ..
  469. String((Float Ptr buffer)[1]) + "," + ..
  470. String((Float Ptr buffer)[2]) + "," + ..
  471. String((Float Ptr buffer)[3])
  472. Case "Double128" value = String((Double Ptr buffer)[0]) + "," + ..
  473. String((Double Ptr buffer)[1])
  474. Case "Int128" value = String((Int Ptr buffer)[0]) + "," + ..
  475. String((Int Ptr buffer)[1]) + "," + ..
  476. String((Int Ptr buffer)[2]) + "," + ..
  477. String((Int Ptr buffer)[3])
  478. ? Win32
  479. Case "WParam" value = String((WParam Ptr buffer)[0])
  480. Case "LParam" value = String((LParam Ptr buffer)[0])
  481. ?
  482. Default
  483. MemFree buffer
  484. result :+ derefSymbol + derefFailure
  485. Return result
  486. EndSelect
  487. MemFree buffer
  488. result :+ derefSymbol + "{" + value + "}"
  489. ?
  490. Return result
  491. EndFunction
  492. Extern
  493. Global bbOnDebugStop()="void bbOnDebugStop()!"
  494. Global bbOnDebugLog( message$ )="void bbOnDebugLog( BBString * )!"
  495. Global bbOnDebugEnterStm( stm:Int Ptr )="void bbOnDebugEnterStm( BBDebugStm * )!"
  496. Global bbOnDebugEnterScope( scope:Int Ptr)="void bbOnDebugEnterScope( BBDebugScope * )!"
  497. Global bbOnDebugLeaveScope()="void bbOnDebugLeaveScope()!"
  498. Global bbOnDebugPushExState()="void bbOnDebugPushExState()!"
  499. Global bbOnDebugPopExState()="void bbOnDebugPopExState()!"
  500. Global bbOnDebugUnhandledEx( ex:Object )="void bbOnDebugUnhandledEx( BBObject * )!"
  501. End Extern
  502. bbOnDebugStop=OnDebugStop
  503. bbOnDebugLog=OnDebugLog
  504. bbOnDebugEnterStm=OnDebugEnterStm
  505. bbOnDebugEnterScope=OnDebugEnterScope
  506. bbOnDebugLeaveScope=OnDebugLeaveScope
  507. bbOnDebugPushExState=OnDebugPushExState
  508. bbOnDebugPopExState=OnDebugPopExState
  509. bbOnDebugUnhandledEx=OnDebugUnhandledEx
  510. ?Win32
  511. Global _ideHwnd:Byte Ptr=GetForegroundWindow();
  512. Global _appHwnd:Byte Ptr
  513. ?
  514. '********** Debugger code here **********
  515. Const MODE_RUN:Int=0
  516. Const MODE_STEP:Int=1
  517. Const MODE_STEPIN:Int=2
  518. Const MODE_STEPOUT:Int=3
  519. Const MODE_BREAK:Int=4
  520. Type TScope
  521. Field scope:Int Ptr,inst:Byte Ptr,stm:Int Ptr
  522. End Type
  523. Type TExState
  524. Field scopeStackTop:Int
  525. End Type
  526. Type TDbgState
  527. Field Mode:Int,debugLevel:Int,funcLevel:Int
  528. Field currentScope:TScope=New TScope
  529. Field scopeStack:TScope[],scopeStackTop:Int
  530. Field exStateStack:TExState[],exStateStackTop:Int
  531. End Type
  532. ?Threaded
  533. Extern
  534. Function bbThreadAllocData:Int()
  535. Function bbThreadSetData( index:Int,data:Object )
  536. Function bbThreadGetData:TDbgState( index:Int )="BBObject* bbThreadGetData(int )!"
  537. End Extern
  538. ?
  539. Global _bpCount:Int
  540. Global _debugPort:Int = 31666
  541. Global _debugWait:Int = True
  542. Global _debugSetup:Int = True
  543. Global _debugData:TDebugData = New TDebugData
  544. _initDebugger()
  545. Const STATEMENT_TIMER:Int = 50
  546. Global _debugSocket:TSocket, _serverSocket:TSocket
  547. Global _debugConnected:Int
  548. _debugSocket = TSocket.CreateTCP()
  549. If Not _debugSocket Then
  550. _debugSocket = TSocket.CreateTCP()
  551. End If
  552. If _debugSocket Then
  553. OnDebugLog("Listening on " + _debugPort)
  554. _debugSocket.Bind(_debugPort)
  555. _debugSocket.Listen(1)
  556. _debugSetup = False
  557. End If
  558. Function _initDebugger()
  559. ' port to accept debugger connections against
  560. Local env:String = getenv_("BMX_DEBUG_PORT")
  561. If env Then
  562. Local port:Int = env.ToInt()
  563. If port Then
  564. _debugPort = port
  565. End If
  566. End If
  567. ' wait for debugger to connect before running?
  568. ' set to non zero for Yes
  569. env = getenv_("BMX_DEBUG_WAIT")
  570. If env Then
  571. Local wait:Int = env.ToInt()
  572. If wait Then
  573. _debugWait = True
  574. End If
  575. End If
  576. End Function
  577. Function GetDbgState:TDbgState()
  578. Global dbgStateMain:TDbgState=New TDbgState
  579. ?Threaded
  580. If bbIsMainThread() Return dbgStateMain
  581. Global dbgStateId:Int=bbThreadAllocData()
  582. Local dbgState:TDbgState=bbThreadGetData( dbgStateId )
  583. If Not dbgState
  584. dbgState = New TDbgState
  585. bbThreadSetData( dbgStateId,dbgState )
  586. End If
  587. Return dbgState
  588. ?Not Threaded
  589. Return dbgStateMain
  590. ?
  591. End Function
  592. Global _WAITING_FOR_INPUT:Int
  593. Function ReadDebug$(skipNotAvail:Int = False)
  594. If _debugConnected Then
  595. If Not _serverSocket.Connected() Then
  596. _debugConnected = False
  597. Return Null
  598. End If
  599. If _WAITING_FOR_INPUT Then
  600. Return ""
  601. End If
  602. Const BUFLEN:Int = 64
  603. Local buf:Byte Ptr = StackAlloc(BUFLEN)
  604. Local p:Int, n:Byte
  605. Local s:String
  606. Local count:Int = _serverSocket.ReadAvail()
  607. If skipNotAvail And Not count Then
  608. Return ""
  609. End If
  610. _WAITING_FOR_INPUT = True
  611. Repeat
  612. _serverSocket.Recv(Varptr n, 1)
  613. If n = 10 And s.length > 0 Then
  614. Exit
  615. End If
  616. buf[p]=n
  617. p:+1
  618. If p<>BUFLEN And p < count Then
  619. Continue
  620. End If
  621. s:+ String.FromBytes(buf,p)
  622. p=0
  623. count = _serverSocket.ReadAvail()
  624. If n = 13 Then
  625. Continue
  626. End If
  627. Delay 50
  628. Forever
  629. If p > 0 Then
  630. s :+ String.FromBytes(buf,p)
  631. End If
  632. _WAITING_FOR_INPUT = False
  633. Return s
  634. 'Return ReadStdin()
  635. End If
  636. End Function
  637. Function WriteDebug( t$, complete:Int = False )
  638. If _debugConnected Then
  639. If Not _serverSocket.Connected() Then
  640. _debugConnected = False
  641. Return
  642. End If
  643. _debugData.Append(t)
  644. If complete Then
  645. Local n:Size_T = bmx_snprintf(_debugData.data, 8, Size_T(_debugData.length - 8))
  646. _debugData.data[_debugData.length] = 0
  647. _serverSocket.Send(_debugData.data, Size_T(_debugData.length))
  648. _debugData.Reset()
  649. End If
  650. End If
  651. End Function
  652. Function DumpScope( scope:Byte Ptr, inst:Byte Ptr )
  653. Local decl:Byte Ptr=bmx_debugger_DebugScopeDecl(scope)
  654. Local kind$=DebugScopeKind( scope )
  655. Local name$=DebugScopeName( scope )
  656. If Not name name="<local>"
  657. WriteDebug kind+" "+name+"~n"
  658. While bmx_debugger_DebugDeclKind(decl)<>DEBUGDECLKIND_END
  659. Select bmx_debugger_DebugDeclKind(decl)
  660. Case DEBUGDECLKIND_TYPEMETHOD,DEBUGDECLKIND_TYPEFUNCTION
  661. decl = bmx_debugger_DebugDeclNext(decl)
  662. Continue
  663. End Select
  664. Local kind$=DebugDeclKind( decl )
  665. Local name$=DebugDeclname( decl )
  666. Local tipe$=DebugDeclType( decl )
  667. Local value$=DebugDeclValue( decl, inst )
  668. If tipe.find("[") >= 0 Then
  669. ?Not ptr64
  670. Local pointer:Int = Int( value )
  671. ?ptr64
  672. Local pointer:Long = Long( value )
  673. ?
  674. ?Not ptr64
  675. Local dinst:Int Ptr=Int Ptr pointer
  676. ?ptr64
  677. Local dinst:Long Ptr=Long Ptr pointer
  678. ?
  679. Local length:Int=bmx_debugger_DebugDecl_ArraySize(dinst)
  680. value :+ ":" + length
  681. End If
  682. WriteDebug kind+" "+name+":"+tipe+"="+value+"~n"
  683. decl = bmx_debugger_DebugDeclNext(decl)
  684. Wend
  685. End Function
  686. Function DumpClassScope( clas:Int Ptr,inst:Byte Ptr )
  687. Local supa:Int Ptr = bmx_debugger_DebugClassSuper(clas)
  688. If Not supa Return
  689. DumpClassScope supa,inst
  690. DumpScope bmx_debugger_DebugClassScope(clas),inst
  691. End Function
  692. Function DumpObject( inst:Byte Ptr,index:Int, count:Int = 100 )
  693. Local clas:Byte Ptr=bmx_debugger_DebugDecl_clas(inst)
  694. If bmx_debugger_DebugDecl_isStringClass(clas)
  695. WriteDebug DebugEscapeString(bmx_debugger_DebugDecl_StringFromAddress(inst))+"~n"
  696. Return
  697. Else If bmx_debugger_DebugDecl_isArrayClass(clas)
  698. Local length:Int=bmx_debugger_DebugDecl_ArraySize(inst)
  699. If Not length Return
  700. Local decl:Byte Ptr = bmx_debugger_DebugDecl_ArrayDecl(inst)
  701. For Local i:Int=1 To count
  702. If index>=length Exit
  703. bmx_debugger_DebugDecl_ArrayDeclIndexedPart(decl, inst, index)
  704. Local value$=DebugDeclValue( decl,inst )
  705. WriteDebug "["+index+"]="+value+"~n"
  706. index:+1
  707. Next
  708. bmx_debugger_DebugDecl_ArrayDeclFree(decl)
  709. ' If index<length
  710. '
  711. ' WriteDebug "...=$"+ToHex(Int inst)+":"+index+"~n"
  712. '
  713. ' EndIf
  714. Else
  715. If bmx_debugger_DebugDecl_isBaseObject(clas) Then
  716. WriteDebug "Object~n"
  717. Return
  718. EndIf
  719. DumpClassScope clas,inst
  720. EndIf
  721. End Function
  722. Function DumpStruct( inst:Byte Ptr,index:Int,structName:String )
  723. Local s:Byte Ptr = structName.ToCString()
  724. Local scope:Byte Ptr = bbObjectStructInfo(s)
  725. If scope Then
  726. DumpScope scope,inst
  727. End If
  728. MemFree s
  729. End Function
  730. Function DumpScopeStack()
  731. Local dbgState:TDbgState = GetDbgState()
  732. For Local i:Int=Max(dbgState.scopeStackTop-100,0) Until dbgState.scopeStackTop
  733. Local t:TScope=dbgState.scopeStack[i]
  734. Local stm:Int Ptr=t.stm
  735. If Not stm Continue
  736. WriteDebug "@"+DebugStmFile(stm)+"<"+DebugStmLine(stm)+","+DebugStmChar(stm)+">~n"
  737. DumpScope t.scope, t.inst
  738. Next
  739. End Function
  740. Function UpdateDebug( msg$ )
  741. Global indebug:Int
  742. If indebug Return
  743. indebug=True
  744. Local dbgState:TDbgState = GetDbgState()
  745. ?Win32
  746. _appHwnd=GetForegroundWindow();
  747. 'SetForegroundWindow( _ideHwnd );
  748. ?
  749. ?MacOs
  750. 'fullscreen debug too hard in MacOS!
  751. If CGDisplayIsCaptured( 0 )
  752. WriteStdout msg
  753. End
  754. EndIf
  755. ?
  756. ' we really need a connection...
  757. Local timeout:Int = 5000
  758. While Not _checkConnection()
  759. timeout:-1
  760. If Not timeout Then
  761. End
  762. End If
  763. Wend
  764. WriteDebug msg
  765. Repeat
  766. WriteDebug "~n", True
  767. Local line$=ReadDebug()
  768. Select line[..1].ToLower()
  769. Case "r"
  770. dbgState.Mode=MODE_RUN
  771. Exit
  772. Case "s"
  773. dbgState.Mode=MODE_STEP
  774. dbgState.debugLevel=dbgState.funcLevel
  775. Exit
  776. Case "e"
  777. dbgState.Mode=MODE_STEPIN
  778. Exit
  779. Case "l"
  780. dbgState.Mode=MODE_STEPOUT
  781. dbgState.debugLevel=dbgState.scopeStackTop-1
  782. Exit
  783. Case "t"
  784. WriteDebug "StackTrace{~n"
  785. DumpScopeStack
  786. WriteDebug "}~n"
  787. Case "d"
  788. Local t$=line[1..].Trim()
  789. Local index:Int
  790. Local count:Int = 100
  791. Local i:Int=t.Find(":")
  792. If i<>-1
  793. Local Range:String = t[i+1..]
  794. t=t[..i]
  795. Local n:Int = Range.Find(",")
  796. If n <> -1 Then
  797. index=Int(Range[..n])
  798. count=Int(Range[n+1..])
  799. Else
  800. index = Int(Range)
  801. End If
  802. EndIf
  803. Local structType:String
  804. Local saLength:Int
  805. Local n:Int = t.Find("@")
  806. If n <> -1 Then
  807. structType = t[n+1..]
  808. t = t[..n]
  809. Else
  810. n = t.Find("^")
  811. If n <> -1 Then
  812. saLength = Int(t[n+1..])
  813. t = t[..n]
  814. Else
  815. If t[..1]="$" t=t[1..].Trim()
  816. If t[..2].ToLower()="0x" t=t[2..].Trim()
  817. End If
  818. End If
  819. ?Not ptr64
  820. Local pointer:Int = Int( "$"+t )
  821. ?ptr64
  822. Local pointer:Long = Long( "$"+t )
  823. ?
  824. If Not structType And Not (pointer And bbGCValidate(Byte Ptr(pointer))) Then Continue
  825. If saLength Continue
  826. ?Not ptr64
  827. Local inst:Int Ptr=Int Ptr pointer
  828. Local cmd$="ObjectDump@"+ToHex( Int inst )
  829. ?ptr64
  830. Local inst:Long Ptr=Long Ptr pointer
  831. Local cmd$="ObjectDump@"+ToHex( Long inst )
  832. ?
  833. If structType Then
  834. cmd :+ "@" + structType
  835. End If
  836. If i<>-1 cmd:+":"+index
  837. WriteDebug cmd$+"{~n"
  838. If structType Then
  839. DumpStruct inst,index,structType
  840. Else
  841. DumpObject inst,index,count
  842. End If
  843. WriteDebug "}~n"
  844. Case "h"
  845. WriteDebug "T - Stack trace~n"
  846. WriteDebug "R - Run from here~n"
  847. WriteDebug "S - Step through source code~n"
  848. WriteDebug "E - Step into function call~n"
  849. WriteDebug "L - Leave function or local block~n"
  850. WriteDebug "Q - Quit~n"
  851. WriteDebug "H - This text~n"
  852. WriteDebug "Dxxxxxxxx - Dump object at hex address xxxxxxxx~n"
  853. Case "q"
  854. End
  855. End Select
  856. Forever
  857. ?Win32
  858. If _appHwnd And _appHwnd<>_ideHwnd
  859. If IsIconic(_apphwnd)
  860. ShowWindow _appHwnd,SW_RESTORE
  861. Else
  862. ShowWindow _appHwnd,SW_SHOW
  863. EndIf
  864. _apphwnd=0
  865. EndIf
  866. ?
  867. indebug=False
  868. End Function
  869. Function _checkConnection:Int()
  870. If Not _debugConnected Then
  871. Global checking:Int
  872. If _debugSocket And Not checking And Not _debugSetup Then
  873. checking = True
  874. If _debugWait Then
  875. ' wait 5 mins
  876. _serverSocket = _debugSocket.Accept(300000)
  877. ' after this, fallback to normal and commence running
  878. If Not _serverSocket
  879. _debugWait = False
  880. End If
  881. Else
  882. _serverSocket = _debugSocket.Accept(0)
  883. End If
  884. If _serverSocket Then
  885. _debugConnected = True
  886. End If
  887. checking = False
  888. End If
  889. End If
  890. Return _debugConnected
  891. End Function
  892. Function OnDebugStop()
  893. UpdateDebug "DebugStop:~n"
  894. End Function
  895. Function OnDebugLog( message$ )
  896. WriteStdout "DebugLog:"+message+"~n"
  897. End Function
  898. Function OnDebugEnterStm( stm:Int Ptr )
  899. Local dbgState:TDbgState = GetDbgState()
  900. dbgState.currentScope.stm=stm
  901. _checkConnection()
  902. Select dbgState.Mode
  903. Case MODE_RUN
  904. If _debugConnected Then
  905. ' because of the nature of the debugger, we need to switch modes since OnDebugEnterStm is called
  906. ' during socket access - which screws the stack up.
  907. dbgState.Mode = MODE_BREAK
  908. Local s:String = ReadDebug(True)
  909. If _debugWait Then
  910. _debugWait = False
  911. ' enter debugging mode!
  912. OnDebugStop()
  913. ' done debugging. If we are still in BREAK mode, return to Running mode
  914. If dbgState.Mode = MODE_BREAK Then
  915. dbgState.Mode = MODE_RUN
  916. End If
  917. Return
  918. End If
  919. If s Then
  920. If s[..1].ToLower() = "x" Then
  921. ' enter debugging mode!
  922. OnDebugStop()
  923. ' done debugging. If we are still in BREAK mode, return to Running mode
  924. If dbgState.Mode = MODE_BREAK Then
  925. dbgState.Mode = MODE_RUN
  926. End If
  927. Return
  928. Else If s[..1].ToLower() = "b" Then
  929. ' format
  930. ' b<FILENAME@line>
  931. Local off:Int = s.find("@")
  932. If off >= 1 Then
  933. Local file:String = s[2..off]
  934. Local line:Int = s[off + 1..s.length - 2].ToInt()
  935. If bmx_debugger_AddBreakpoint(file, line) Then
  936. _bpCount :+ 1
  937. End If
  938. End If
  939. Else If s[..1].ToLower() = "z" Then
  940. ' format
  941. ' z<FILENAME@line>
  942. Local off:Int = s.find("@")
  943. If off >= 1 Then
  944. Local file:String = s[2..off]
  945. Local line:Int = s[off + 1..s.length - 2].ToInt()
  946. Local count:Int = bmx_debugger_RemoveBreakpoint(file, line)
  947. If count Then
  948. _bpCount :- count
  949. End If
  950. End If
  951. End If
  952. ' done debugging. If we are still in BREAK mode, return to Running mode
  953. If dbgState.Mode = MODE_BREAK Then
  954. dbgState.Mode = MODE_RUN
  955. End If
  956. Return
  957. Else If _bpCount Then
  958. ' breakpoints have been defined
  959. If DebugBreakOnLine(stm) Then
  960. ' enter debugging mode!
  961. OnDebugStop()
  962. ' done debugging. If we are still in BREAK mode, return to Running mode
  963. If dbgState.Mode = MODE_BREAK Then
  964. dbgState.Mode = MODE_RUN
  965. End If
  966. Return
  967. End If
  968. ' carry on as before
  969. dbgState.Mode = MODE_RUN
  970. Return
  971. Else
  972. ' carry on as before
  973. dbgState.Mode = MODE_RUN
  974. Return
  975. End If
  976. Else
  977. ' carry on as before
  978. Return
  979. End If
  980. Case MODE_STEP
  981. If dbgState.funcLevel>dbgState.debugLevel
  982. Return
  983. EndIf
  984. Case MODE_STEPOUT
  985. If dbgState.scopeStackTop>dbgState.debugLevel
  986. Return
  987. EndIf
  988. Case MODE_BREAK
  989. Return
  990. End Select
  991. UpdateDebug "Debug:~n"
  992. End Function
  993. Function OnDebugEnterScope( scope:Int Ptr)',inst:Byte Ptr )
  994. Local dbgState:TDbgState = GetDbgState()
  995. GCSuspend
  996. If dbgState.scopeStackTop=dbgState.scopeStack.length
  997. dbgState.scopeStack=dbgState.scopeStack[..dbgState.scopeStackTop * 2 + 32]
  998. For Local i:Int=dbgState.scopeStackTop Until dbgState.scopeStack.length
  999. dbgState.scopeStack[i]=New TScope
  1000. Next
  1001. EndIf
  1002. dbgState.currentScope=dbgState.scopeStack[dbgState.scopeStackTop]
  1003. dbgState.currentScope.scope=scope
  1004. dbgState.currentScope.inst=0
  1005. dbgState.scopeStackTop:+1
  1006. If bmx_debugger_DebugScopeKind(dbgState.currentScope.scope)=DEBUGSCOPEKIND_FUNCTION dbgState.funcLevel:+1
  1007. GCResume
  1008. End Function
  1009. Function OnDebugLeaveScope()
  1010. Local dbgState:TDbgState = GetDbgState()
  1011. GCSuspend
  1012. If Not dbgState.scopeStackTop DebugError "scope stack underflow"
  1013. If bmx_debugger_DebugScopeKind(dbgState.currentScope.scope)=DEBUGSCOPEKIND_FUNCTION dbgState.funcLevel:-1
  1014. dbgState.scopeStackTop:-1
  1015. If dbgState.scopeStackTop
  1016. dbgState.currentScope=dbgState.scopeStack[dbgState.scopeStackTop-1]
  1017. Else
  1018. dbgState.currentScope=Null
  1019. EndIf
  1020. GCResume
  1021. End Function
  1022. Function OnDebugPushExState()
  1023. Local dbgState:TDbgState = GetDbgState()
  1024. GCSuspend
  1025. If dbgState.exStateStackTop=dbgState.exStateStack.length
  1026. dbgState.exStateStack=dbgState.exStateStack[..dbgState.exStateStackTop * 2 + 32]
  1027. For Local i:Int=dbgState.exStateStackTop Until dbgState.exStateStack.length
  1028. dbgState.exStateStack[i]=New TExState
  1029. Next
  1030. EndIf
  1031. dbgState.exStateStack[dbgState.exStateStackTop].scopeStackTop=dbgState.scopeStackTop
  1032. dbgState.exStateStackTop:+1
  1033. GCResume
  1034. End Function
  1035. Function OnDebugPopExState()
  1036. Local dbgState:TDbgState = GetDbgState()
  1037. GCSuspend
  1038. If Not dbgState.exStateStackTop DebugError "exception stack underflow"
  1039. dbgState.exStateStackTop:-1
  1040. dbgState.scopeStackTop=dbgState.exStateStack[dbgState.exStateStackTop].scopeStackTop
  1041. If dbgState.scopeStackTop
  1042. dbgState.currentScope=dbgState.scopeStack[dbgState.scopeStackTop-1]
  1043. Else
  1044. dbgState.currentScope=Null
  1045. EndIf
  1046. GCResume
  1047. End Function
  1048. Function OnDebugUnhandledEx( ex:Object )
  1049. GCSuspend
  1050. UpdateDebug "Unhandled Exception:"+ex.ToString()+"~n"
  1051. GCResume
  1052. End Function
  1053. Type TDebugData
  1054. Field length:Int = 8
  1055. Field data:Byte[1024]
  1056. Field prefix:Byte Ptr = "~~>".ToUTF8String()
  1057. Method Append(s:String)
  1058. Local b:Byte Ptr = s.toUTF8String()
  1059. Local i:Size_T = strlen_(b)
  1060. If length + i + 2 >= data.length Then
  1061. data = data[..length + i + data.length * 2/3]
  1062. End If
  1063. MemCopy(Byte Ptr(data) + length, prefix, 2)
  1064. MemCopy(Byte Ptr(data) + length + 2, b, i)
  1065. MemFree(b)
  1066. length :+ i + 2
  1067. End Method
  1068. Method Reset()
  1069. length = 8
  1070. End Method
  1071. End Type