debugger.stdio.bmx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711
  1. Strict
  2. NoDebug
  3. Private
  4. ?Win32
  5. Extern "Win32"
  6. Const SW_SHOW=5
  7. Const SW_RESTORE=9
  8. Function IsIconic( hwnd )
  9. Function GetForegroundWindow()
  10. Function SetForegroundWindow( hwnd )
  11. Function ShowWindow( hwnd,cmdShow )
  12. Function GetCurrentThreadId()
  13. End Extern
  14. ?
  15. ?MacOS
  16. Extern
  17. Function CGDisplayIsCaptured( displayId )
  18. End Extern
  19. ?
  20. Extern
  21. Global bbStringClass:Byte
  22. Global bbArrayClass:Byte
  23. Global bbNullObject:Byte
  24. Global bbEmptyArray:Byte
  25. Global bbEmptyString:Byte
  26. Global brl_blitz_NullFunctionError:Byte Ptr
  27. Function bbIsMainThread()="bbIsMainThread"
  28. Function bbGCValidate:Int( mem:Int ) = "bbGCValidate"
  29. End Extern
  30. Function ToHex$( val )
  31. Local buf:Short[8]
  32. For Local k=7 To 0 Step -1
  33. Local n=(val&15)+Asc("0")
  34. If n>Asc("9") n=n+(Asc("A")-Asc("9")-1)
  35. buf[k]=n
  36. val:Shr 4
  37. Next
  38. Return String.FromShorts( buf,8 ).ToLower()
  39. End Function
  40. Function IsAlpha( ch )
  41. Return (ch>=Asc("a") And ch<=Asc("z")) Or (ch>=Asc("A") And ch<=Asc("Z"))
  42. End Function
  43. Function IsNumeric( ch )
  44. Return ch>=Asc("0") And ch<=Asc("9")
  45. End Function
  46. Function IsAlphaNumeric( ch )
  47. Return IsAlpha(ch) Or IsNumeric(ch)
  48. End Function
  49. Function IsUnderscore( ch )
  50. Return ch=Asc("_")
  51. End Function
  52. Function Ident$( tag$ Var )
  53. If Not tag Return ""
  54. If Not IsAlpha( tag[0] ) And Not IsUnderscore( tag[0] ) Return ""
  55. Local i=1
  56. While i<tag.length And (IsAlphaNumeric(tag[i]) Or IsUnderscore(tag[i]))
  57. i:+1
  58. Wend
  59. Local id$=tag[..i]
  60. tag=tag[i..]
  61. Return id
  62. End Function
  63. Function TypeName$( tag$ Var )
  64. Local t$=tag[..1]
  65. tag=tag[1..]
  66. Select t
  67. Case "b"
  68. Return "Byte"
  69. Case "s"
  70. Return "Short"
  71. Case "i"
  72. Return "Int"
  73. Case "l"
  74. Return "Long"
  75. Case "f"
  76. Return "Float"
  77. Case "d"
  78. Return "Double"
  79. Case "$"
  80. Return "String"
  81. Case "z"
  82. Return "CString"
  83. Case "w"
  84. Return "WString"
  85. Case ":","?"
  86. Local id$=Ident( tag )
  87. While tag And tag[0]=Asc(".")
  88. tag=tag[1..]
  89. id=Ident( tag )
  90. Wend
  91. If Not id DebugError "Invalid object typetag"
  92. Return id
  93. Case "*"
  94. Return TypeName( tag )+" Ptr"
  95. Case "["
  96. While tag[..1]=","
  97. tag=tag[1..]
  98. t:+","
  99. Wend
  100. If tag[..1]<>"]" DebugError "Invalid array typetag"
  101. tag=tag[1..]
  102. Return TypeName( tag )+t+"]"
  103. Case "("
  104. If tag[..1]<>")"
  105. t:+TypeName( tag )
  106. While tag[..1]=","
  107. tag=tag[1..]
  108. t:+","+TypeName( tag )
  109. Wend
  110. If tag[..1]<>")" DebugError "Invalid function typetag"
  111. EndIf
  112. tag=tag[1..]
  113. Return TypeName( tag )+t+")"
  114. End Select
  115. DebugError "Invalid debug typetag:"+t
  116. End Function
  117. 'int offsets into 12 byte DebugStm struct
  118. Const DEBUGSTM_FILE=0
  119. Const DEBUGSTM_LINE=1
  120. Const DEBUGSTM_CHAR=2
  121. 'int offsets into 16 byte DebugDecl struct
  122. Const DEBUGDECL_KIND=0
  123. Const DEBUGDECL_NAME=1
  124. Const DEBUGDECL_TYPE=2
  125. Const DEBUGDECL_ADDR=3
  126. 'DEBUGDECL_KIND values
  127. Const DEBUGDECLKIND_END=0
  128. Const DEBUGDECLKIND_CONST=1
  129. Const DEBUGDECLKIND_LOCAL=2
  130. Const DEBUGDECLKIND_FIELD=3
  131. Const DEBUGDECLKIND_GLOBAL=4
  132. Const DEBUGDECLKIND_VARPARAM=5
  133. Const DEBUGDECLKIND_TYPEMETHOD=6
  134. Const DEBUGDECLKIND_TYPEFUNCTION=7
  135. 'int offsets into 12+n_decls*4 byte DebugScope struct
  136. Const DEBUGSCOPE_KIND=0
  137. Const DEBUGSCOPE_NAME=1
  138. Const DEBUGSCOPE_DECLS=2
  139. 'DEBUGSCOPE_KIND values
  140. Const DEBUGSCOPEKIND_FUNCTION=1
  141. Const DEBUGSCOPEKIND_TYPE=2
  142. Const DEBUGSCOPEKIND_LOCAL=3
  143. Function DebugError( t$ )
  144. WriteStderr "Debugger Error:"+t+"~n"
  145. End
  146. End Function
  147. Function DebugStmFile$( stm:Int Ptr )
  148. Return String.FromCString( Byte Ptr stm[DEBUGSTM_FILE] )
  149. End Function
  150. Function DebugStmLine( stm:Int Ptr )
  151. Return stm[DEBUGSTM_LINE]
  152. End Function
  153. Function DebugStmChar( stm:Int Ptr )
  154. Return stm[DEBUGSTM_CHAR]
  155. End Function
  156. Function DebugDeclKind$( decl:Int Ptr )
  157. Select decl[DEBUGDECL_KIND]
  158. Case DEBUGDECLKIND_CONST Return "Const"
  159. Case DEBUGDECLKIND_LOCAL Return "Local"
  160. Case DEBUGDECLKIND_FIELD Return "Field"
  161. Case DEBUGDECLKIND_GLOBAL Return "Global"
  162. Case DEBUGDECLKIND_VARPARAM Return "Local"
  163. End Select
  164. DebugError "Invalid decl kind"
  165. End Function
  166. Function DebugDeclName$( decl:Int Ptr )
  167. Return String.FromCString( Byte Ptr decl[DEBUGDECL_NAME] )
  168. End Function
  169. Function DebugDeclType$( decl:Int Ptr )
  170. Local t$=String.FromCString( Byte Ptr decl[DEBUGDECL_TYPE] )
  171. Local ty$=TypeName( t )
  172. Return ty
  173. End Function
  174. Function DebugDeclSize( decl:Int Ptr )
  175. Local tag=(Byte Ptr Ptr(decl+DEBUGDECL_TYPE))[0][0]
  176. Select tag
  177. Case Asc("b") Return 1
  178. Case Asc("s") Return 2
  179. Case Asc("l") Return 8
  180. Case Asc("d") Return 8
  181. End Select
  182. Return 4
  183. End Function
  184. Function DebugEscapeString$( s$ )
  185. s=s.Replace( "~~","~~~~")
  186. s=s.Replace( "~0","~~0" )
  187. s=s.Replace( "~t","~~t" )
  188. s=s.Replace( "~n","~~n" )
  189. s=s.Replace( "~r","~~r" )
  190. s=s.Replace( "~q","~~q" )
  191. Return "~q"+s+"~q"
  192. End Function
  193. Function DebugDeclValue$( decl:Int Ptr,inst:Byte Ptr )
  194. If decl[DEBUGDECL_KIND]=DEBUGDECLKIND_CONST
  195. Local p:Byte Ptr=Byte Ptr decl[DEBUGDECL_ADDR]
  196. Return DebugEscapeString(String.FromShorts( Short Ptr(p+12),(Int Ptr (p+8))[0] ))
  197. EndIf
  198. Local p:Byte Ptr
  199. Select decl[DEBUGDECL_KIND]
  200. Case DEBUGDECLKIND_GLOBAL
  201. p=Byte Ptr decl[DEBUGDECL_ADDR]
  202. Case DEBUGDECLKIND_LOCAL,DEBUGDECLKIND_FIELD
  203. p=Byte Ptr (inst+decl[DEBUGDECL_ADDR])
  204. Case DEBUGDECLKIND_VARPARAM
  205. p=Byte Ptr (inst+decl[DEBUGDECL_ADDR])
  206. p=Byte Ptr ( (Int Ptr p)[0] )
  207. Default
  208. DebugError "Invalid decl kind"
  209. End Select
  210. Local tag=(Byte Ptr Ptr(decl+DEBUGDECL_TYPE))[0][0]
  211. Select tag
  212. Case Asc("b")
  213. Return String.FromInt( (Byte Ptr p)[0] )
  214. Case Asc("s")
  215. Return String.FromInt( (Short Ptr p)[0] )
  216. Case Asc("i")
  217. Return String.FromInt( (Int Ptr p)[0] )
  218. Case Asc("l")
  219. Return String.FromLong( (Long Ptr p)[0] )
  220. Case Asc("f")
  221. Return String.FromFloat( (Float Ptr p)[0] )
  222. Case Asc("d")
  223. Return String.FromDouble( (Double Ptr p)[0] )
  224. Case Asc("$")
  225. p=(Byte Ptr Ptr p)[0]
  226. Local sz=Int Ptr(p+8)[0]
  227. Local s$=String.FromShorts( Short Ptr(p+12),sz )
  228. Return DebugEscapeString( s )
  229. Case Asc("z")
  230. p=(Byte Ptr Ptr p)[0]
  231. If Not p Return "Null"
  232. Local s$=String.FromCString( p )
  233. Return DebugEscapeString( s )
  234. Case Asc("w")
  235. p=(Byte Ptr Ptr p)[0]
  236. If Not p Return "Null"
  237. Local s$=String.FromWString( Short Ptr p )
  238. Return DebugEscapeString( s )
  239. Case Asc("*"),Asc("?")
  240. Return "$"+ToHex( (Int Ptr p)[0] )
  241. Case Asc("(")
  242. p=(Byte Ptr Ptr p)[0]
  243. If p=brl_blitz_NullFunctionError Return "Null"
  244. Case Asc(":")
  245. p=(Byte Ptr Ptr p)[0]
  246. If p=Varptr bbNullObject Return "Null"
  247. If p=Varptr bbEmptyArray Return "Null[]"
  248. If p=Varptr bbEmptyString Return "Null$"
  249. Case Asc("[")
  250. p=(Byte Ptr Ptr p)[0]
  251. If Not p Return "Null"
  252. If Not (Int Ptr (p+20))[0] Return "Null"
  253. Default
  254. DebugError "Invalid decl typetag:"+Chr(tag)
  255. End Select
  256. Return "$"+ToHex( Int p )
  257. End Function
  258. Function DebugScopeKind$( scope:Int Ptr )
  259. Select scope[DEBUGSCOPE_KIND]
  260. Case DEBUGSCOPEKIND_FUNCTION Return "Function"
  261. Case DEBUGSCOPEKIND_TYPE Return "Type"
  262. Case DEBUGSCOPEKIND_LOCAL Return "Local"
  263. End Select
  264. DebugError "Invalid scope kind"
  265. End Function
  266. Function DebugScopeName$( scope:Int Ptr )
  267. Return String.FromCString( Byte Ptr scope[DEBUGSCOPE_NAME] )
  268. End Function
  269. Function DebugScopeDecls:Int Ptr[]( scope:Int Ptr )
  270. Local n,p:Int Ptr=scope+DEBUGSCOPE_DECLS
  271. While p[n]<>DEBUGDECLKIND_END
  272. n:+1
  273. Wend
  274. Local decls:Int Ptr[n]
  275. For Local i=0 Until n
  276. decls[i]=p+i*4
  277. Next
  278. Return decls
  279. End Function
  280. Function DebugObjectScope:Int Ptr( inst:Byte Ptr )
  281. Local clas:Int Ptr Ptr=(Int Ptr Ptr Ptr inst)[0]
  282. Return clas[2]
  283. End Function
  284. Extern
  285. Global bbOnDebugStop()
  286. Global bbOnDebugLog( message$ )
  287. Global bbOnDebugEnterStm( stm:Int Ptr )
  288. Global bbOnDebugEnterScope( scope:Int Ptr,inst:Byte Ptr )
  289. Global bbOnDebugLeaveScope()
  290. Global bbOnDebugPushExState()
  291. Global bbOnDebugPopExState()
  292. Global bbOnDebugUnhandledEx( ex:Object )
  293. End Extern
  294. bbOnDebugStop=OnDebugStop
  295. bbOnDebugLog=OnDebugLog
  296. bbOnDebugEnterStm=OnDebugEnterStm
  297. bbOnDebugEnterScope=OnDebugEnterScope
  298. bbOnDebugLeaveScope=OnDebugLeaveScope
  299. bbOnDebugPushExState=OnDebugPushExState
  300. bbOnDebugPopExState=OnDebugPopExState
  301. bbOnDebugUnhandledEx=OnDebugUnhandledEx
  302. ?Win32
  303. Global _ideHwnd=GetForegroundWindow();
  304. Global _appHwnd
  305. ?
  306. '********** Debugger code here **********
  307. Const MODE_RUN=0
  308. Const MODE_STEP=1
  309. Const MODE_STEPIN=2
  310. Const MODE_STEPOUT=3
  311. Type TScope
  312. Field scope:Int Ptr,inst:Byte Ptr,stm:Int Ptr
  313. End Type
  314. Type TExState
  315. Field scopeStackTop
  316. End Type
  317. Global mode,debugLevel,funcLevel
  318. Global currentScope:TScope=New TScope
  319. Global scopeStack:TScope[],scopeStackTop
  320. Global exStateStack:TExState[],exStateStackTop
  321. Function ReadDebug$()
  322. Return ReadStdin()
  323. End Function
  324. Function WriteDebug( t$ )
  325. WriteStderr "~~>"+t
  326. End Function
  327. Function DumpScope( scope:Int Ptr,inst:Byte Ptr )
  328. Local decl:Int Ptr=scope+DEBUGSCOPE_DECLS
  329. Local kind$=DebugScopeKind( scope ),name$=DebugScopeName( scope )
  330. If Not name name="<local>"
  331. WriteDebug kind+" "+name+"~n"
  332. While decl[DEBUGDECL_KIND]<>DEBUGDECLKIND_END
  333. Select decl[DEBUGDECL_KIND]
  334. Case DEBUGDECLKIND_TYPEMETHOD,DEBUGDECLKIND_TYPEFUNCTION
  335. decl:+4
  336. Continue
  337. End Select
  338. Local kind$=DebugDeclKind( decl )
  339. Local name$=DebugDeclname( decl )
  340. Local tipe$=DebugDeclType( decl )
  341. Local value$=DebugDeclValue( decl,inst )
  342. WriteDebug kind+" "+name+":"+tipe+"="+value+"~n"
  343. decl:+4
  344. Wend
  345. End Function
  346. Function DumpClassScope( clas:Int Ptr,inst:Byte Ptr )
  347. Local supa:Int Ptr=Int Ptr clas[0]
  348. If Not supa Return
  349. DumpClassScope supa,inst
  350. DumpScope Int Ptr clas[2],inst
  351. End Function
  352. Function DumpObject( inst:Byte Ptr,index )
  353. Local clas:Int Ptr=(Int Ptr Ptr inst)[0]
  354. If clas=Int Ptr Varptr bbStringClass
  355. WriteDebug DebugEscapeString(String.FromShorts( Short Ptr(inst+12),(Int Ptr (inst+8))[0] ))+"~n"
  356. Return
  357. Else If clas=Int Ptr Varptr bbArrayClass
  358. Local length=(Int Ptr (inst+20))[0]
  359. If Not length Return
  360. Local decl:Int[3]
  361. decl[0]=DEBUGDECLKIND_LOCAL
  362. decl[2]=(Int Ptr (inst+8))[0]
  363. Local sz=DebugDeclSize( decl )
  364. Local p:Byte Ptr=Byte Ptr(20+(Int Ptr (inst+12))[0]*4)
  365. For Local i=1 To 10
  366. If index>=length Exit
  367. decl[3]=Int(p+index*sz)
  368. Local value$=DebugDeclValue( decl,inst )
  369. WriteDebug "["+index+"]="+value+"~n"
  370. index:+1
  371. Next
  372. If index<length
  373. WriteDebug "...=$"+ToHex(Int inst)+":"+index+"~n"
  374. EndIf
  375. Else
  376. If Not clas[0]
  377. WriteDebug "Object~n"
  378. Return
  379. EndIf
  380. DumpClassScope clas,inst
  381. EndIf
  382. End Function
  383. Function DumpScopeStack()
  384. For Local i=Max(scopeStackTop-100,0) Until scopeStackTop
  385. Local t:TScope=scopeStack[i]
  386. Local stm:Int Ptr=t.stm
  387. If Not stm Continue
  388. WriteDebug "@"+DebugStmFile(stm)+"<"+DebugStmLine(stm)+","+DebugStmChar(stm)+">~n"
  389. DumpScope t.scope,t.inst
  390. Next
  391. End Function
  392. Function UpdateDebug( msg$ )
  393. Global indebug
  394. If indebug Return
  395. indebug=True
  396. ?Win32
  397. _appHwnd=GetForegroundWindow();
  398. 'SetForegroundWindow( _ideHwnd );
  399. ?
  400. ?MacOs
  401. 'fullscreen debug too hard in MacOS!
  402. If CGDisplayIsCaptured( 0 )
  403. WriteStdout msg
  404. End
  405. EndIf
  406. ?
  407. WriteDebug msg
  408. Repeat
  409. WriteDebug "~n"
  410. Local line$=ReadDebug()
  411. Select line[..1].ToLower()
  412. Case "r"
  413. mode=MODE_RUN
  414. Exit
  415. Case "s"
  416. mode=MODE_STEP
  417. debugLevel=funcLevel
  418. Exit
  419. Case "e"
  420. mode=MODE_STEPIN
  421. Exit
  422. Case "l"
  423. mode=MODE_STEPOUT
  424. debugLevel=scopeStackTop-1
  425. Exit
  426. Case "t"
  427. WriteDebug "StackTrace{~n"
  428. DumpScopeStack
  429. WriteDebug "}~n"
  430. Case "d"
  431. Local t$=line[1..].Trim()
  432. Local index
  433. Local i=t.Find(":")
  434. If i<>-1
  435. index=Int( t[i+1..] )
  436. t=t[..i]
  437. EndIf
  438. If t[..1]="$" t=t[1..].Trim()
  439. If t[..2].ToLower()="0x" t=t[2..].Trim()
  440. Local pointer = Int( "$"+t )
  441. If Not (pointer And bbGCValidate(pointer)) Then Continue
  442. Local inst:Int Ptr=Int Ptr pointer
  443. Local cmd$="ObjectDump@"+ToHex( Int inst )
  444. If i<>-1 cmd:+":"+index
  445. WriteDebug cmd$+"{~n"
  446. DumpObject inst,index
  447. WriteDebug "}~n"
  448. Case "h"
  449. WriteDebug "T - Stack trace~n"
  450. WriteDebug "R - Run from here~n"
  451. WriteDebug "S - Step through source code~n"
  452. WriteDebug "E - Step into function call~n"
  453. WriteDebug "L - Leave function or local block~n"
  454. WriteDebug "Q - Quit~n"
  455. WriteDebug "H - This text~n"
  456. WriteDebug "Dxxxxxxxx - Dump object at hex address xxxxxxxx~n"
  457. Case "q"
  458. End
  459. End Select
  460. Forever
  461. ?Win32
  462. If _appHwnd And _appHwnd<>_ideHwnd
  463. If IsIconic(_apphwnd)
  464. ShowWindow _appHwnd,SW_RESTORE
  465. Else
  466. ShowWindow _appHwnd,SW_SHOW
  467. EndIf
  468. _apphwnd=0
  469. EndIf
  470. ?
  471. indebug=False
  472. End Function
  473. Function OnDebugStop()
  474. ?Threaded
  475. If Not bbIsMainThread() Return
  476. ?
  477. UpdateDebug "DebugStop:~n"
  478. End Function
  479. Function OnDebugLog( message$ )
  480. ?Threaded
  481. If Not bbIsMainThread() Return
  482. ?
  483. WriteStdout "DebugLog:"+message+"~n"
  484. End Function
  485. Function OnDebugEnterStm( stm:Int Ptr )
  486. ?Threaded
  487. If Not bbIsMainThread() Return
  488. ?
  489. currentScope.stm=stm
  490. Select mode
  491. Case MODE_RUN
  492. Return
  493. Case MODE_STEP
  494. If funcLevel>debugLevel
  495. Return
  496. EndIf
  497. Case MODE_STEPOUT
  498. If scopeStackTop>debugLevel
  499. Return
  500. EndIf
  501. End Select
  502. UpdateDebug "Debug:~n"
  503. End Function
  504. Function OnDebugEnterScope( scope:Int Ptr,inst:Byte Ptr )
  505. ?Threaded
  506. If Not bbIsMainThread() Return
  507. ?
  508. GCSuspend
  509. If scopeStackTop=scopeStack.length
  510. scopeStack=scopeStack[..scopeStackTop * 2 + 32]
  511. For Local i=scopeStackTop Until scopeStack.length
  512. scopeStack[i]=New TScope
  513. Next
  514. EndIf
  515. currentScope=scopeStack[scopeStackTop]
  516. currentScope.scope=scope
  517. currentScope.inst=inst
  518. scopeStackTop:+1
  519. If currentScope.scope[DEBUGSCOPE_KIND]=DEBUGSCOPEKIND_FUNCTION funcLevel:+1
  520. GCResume
  521. End Function
  522. Function OnDebugLeaveScope()
  523. ?Threaded
  524. If Not bbIsMainThread() Return
  525. ?
  526. GCSuspend
  527. If Not scopeStackTop DebugError "scope stack underflow"
  528. If currentScope.scope[DEBUGSCOPE_KIND]=DEBUGSCOPEKIND_FUNCTION funcLevel:-1
  529. scopeStackTop:-1
  530. If scopeStackTop
  531. currentScope=scopeStack[scopeStackTop-1]
  532. Else
  533. currentScope=New TScope
  534. EndIf
  535. GCResume
  536. End Function
  537. Function OnDebugPushExState()
  538. ?Threaded
  539. If Not bbIsMainThread() Return
  540. ?
  541. GCSuspend
  542. If exStateStackTop=exStateStack.length
  543. exStateStack=exStateStack[..exStateStackTop * 2 + 32]
  544. For Local i=exStateStackTop Until exStateStack.length
  545. exStateStack[i]=New TExState
  546. Next
  547. EndIf
  548. exStateStack[exStateStackTop].scopeStackTop=scopeStackTop
  549. exStateStackTop:+1
  550. GCResume
  551. End Function
  552. Function OnDebugPopExState()
  553. ?Threaded
  554. If Not bbIsMainThread() Return
  555. ?
  556. GCSuspend
  557. If Not exStateStackTop DebugError "exception stack underflow"
  558. exStateStackTop:-1
  559. scopeStackTop=exStateStack[exStateStackTop].scopeStackTop
  560. If scopeStackTop
  561. currentScope=scopeStack[scopeStackTop-1]
  562. Else
  563. currentScope=New TScope
  564. EndIf
  565. GCResume
  566. End Function
  567. Function OnDebugUnhandledEx( ex:Object )
  568. ?Threaded
  569. If Not bbIsMainThread() Return
  570. ?
  571. GCSuspend
  572. UpdateDebug "Unhandled Exception:"+ex.ToString()+"~n"
  573. GCResume
  574. End Function