PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/beta3/harbour/source/debug/dbgentry.c

#
C | 1766 lines | 1453 code | 253 blank | 60 comment | 261 complexity | 62e803a67139477ca1a0b35b53328294 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause, CC-BY-SA-3.0, LGPL-3.0, GPL-2.0, LGPL-2.0, LGPL-2.1
  1. /*
  2. * $Id: dbgentry.c 7523 2007-06-05 08:50:19Z druzus $
  3. */
  4. /*
  5. * xHarbour Project source code:
  6. * Debugger entry routine
  7. *
  8. * Copyright 2005 Phil Krylov <phil a t newstar.rinet.ru>
  9. * www - http://www.xharbour.org
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2, or (at your option)
  14. * any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this software; see the file COPYING. If not, write to
  23. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  24. * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
  25. *
  26. * As a special exception, xHarbour license gives permission for
  27. * additional uses of the text contained in its release of xHarbour.
  28. *
  29. * The exception is that, if you link the xHarbour libraries with other
  30. * files to produce an executable, this does not by itself cause the
  31. * resulting executable to be covered by the GNU General Public License.
  32. * Your use of that executable is in no way restricted on account of
  33. * linking the xHarbour library code into it.
  34. *
  35. * This exception does not however invalidate any other reasons why
  36. * the executable file might be covered by the GNU General Public License.
  37. *
  38. * This exception applies only to the code released with this xHarbour
  39. * explicit exception. If you add/copy code from other sources,
  40. * as the General Public License permits, the above exception does
  41. * not apply to the code that you add in this way. To avoid misleading
  42. * anyone as to the status of such modified files, you must delete
  43. * this exception notice from them.
  44. *
  45. * If you write modifications of your own for xHarbour, it is your choice
  46. * whether to permit this exception to apply to your modifications.
  47. * If you do not wish that, delete this exception notice.
  48. *
  49. */
  50. #include <ctype.h>
  51. #include "hbvmopt.h"
  52. #include "hbapidbg.h"
  53. #include "hbapiitm.h"
  54. #include "hbapirdd.h"
  55. #include "hbstack.h"
  56. #include "hbvm.h"
  57. #include "hbdebug.ch"
  58. #include "hbmacro.ch"
  59. /* dummy function declaration */
  60. static BOOL hb_clsSetScope( BOOL fScope ) { return fScope; }
  61. #if defined( HB_OS_UNIX_COMPATIBLE )
  62. #define FILENAME_EQUAL(s1, s2) ( !strcmp( (s1), (s2) ) )
  63. #else
  64. #define FILENAME_EQUAL(s1, s2) ( !hb_stricmp( (s1), (s2) ) )
  65. #endif
  66. #define ALLOC hb_xgrab
  67. #define FREE hb_xfree
  68. #define STRDUP hb_strdup
  69. #define STRNDUP( dest, source, len ) ( dest = hb_strndup( (source), (len) ) )
  70. #define ARRAY_ADD( type, array, length ) \
  71. ( ( ++length == 1 ) ? ( array = ( type * ) hb_xgrab( sizeof( type ) ) ) : \
  72. ( ( array = ( type * ) hb_xrealloc( array, sizeof( type ) * length ) ) + \
  73. length - 1 ) )
  74. #define ARRAY_DEL( type, array, length, index ) \
  75. do { \
  76. if ( !--length ) \
  77. hb_xfree( array ); \
  78. else if( index < length ) \
  79. memmove( array + index, array + index + 1, sizeof( type ) * ( length - index ) ); \
  80. } while( 0 )
  81. typedef struct
  82. {
  83. char *szModule;
  84. int nLine;
  85. char *szFunction;
  86. } HB_BREAKPOINT;
  87. typedef struct
  88. {
  89. int nIndex;
  90. PHB_ITEM xValue;
  91. } HB_TRACEPOINT;
  92. typedef struct
  93. {
  94. char *szName;
  95. char cType;
  96. int nFrame;
  97. int nIndex;
  98. } HB_VARINFO;
  99. typedef struct
  100. {
  101. char *szExpr;
  102. PHB_ITEM pBlock;
  103. int nVars;
  104. char **aVars;
  105. HB_VARINFO *aScopes;
  106. } HB_WATCHPOINT;
  107. typedef struct
  108. {
  109. char *szModule;
  110. char *szFunction;
  111. int nLine;
  112. int nProcLevel;
  113. int nLocals;
  114. HB_VARINFO *aLocals;
  115. int nStatics;
  116. HB_VARINFO *aStatics;
  117. } HB_CALLSTACKINFO;
  118. typedef struct
  119. {
  120. char *szModule;
  121. int nStatics;
  122. HB_VARINFO *aStatics;
  123. int nGlobals;
  124. HB_VARINFO *aGlobals;
  125. int nExternGlobals;
  126. HB_VARINFO *aExternGlobals;
  127. } HB_MODULEINFO;
  128. typedef struct
  129. {
  130. BOOL bQuit;
  131. BOOL bGo;
  132. BOOL bInside;
  133. int nBreakPoints;
  134. HB_BREAKPOINT *aBreak;
  135. int nTracePoints;
  136. HB_TRACEPOINT *aTrace;
  137. int nWatchPoints;
  138. HB_WATCHPOINT *aWatch;
  139. BOOL bTraceOver;
  140. int nTraceLevel;
  141. BOOL bNextRoutine;
  142. BOOL bCodeBlock;
  143. BOOL bToCursor;
  144. int nToCursorLine;
  145. char *szToCursorModule;
  146. int nProcLevel;
  147. int nCallStackLen;
  148. HB_CALLSTACKINFO *aCallStack;
  149. int nModules;
  150. HB_MODULEINFO *aModules;
  151. BOOL bCBTrace;
  152. BOOL ( *pFunInvoke )( void );
  153. BOOL bInitGlobals;
  154. BOOL bInitStatics;
  155. BOOL bInitLines;
  156. PHB_ITEM pStopLines;
  157. } HB_DEBUGINFO;
  158. static HB_DEBUGINFO s_Info = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* bCBTrace */ TRUE, 0, 0, 0, 0, 0 };
  159. static HB_DEBUGINFO *info = &s_Info;
  160. static PHB_ITEM
  161. hb_dbgActivateBreakArray( HB_DEBUGINFO *info );
  162. static PHB_ITEM
  163. hb_dbgActivateModuleArray( HB_DEBUGINFO *info );
  164. static PHB_ITEM
  165. hb_dbgActivateVarArray( int nVars, HB_VARINFO *aVars );
  166. static void
  167. hb_dbgAddLocal( HB_DEBUGINFO *info, char *szName, int nIndex, int nFrame );
  168. static void
  169. hb_dbgAddModule( HB_DEBUGINFO *info, char *szName );
  170. static void
  171. hb_dbgAddStack( HB_DEBUGINFO *info, char *szName, int nProcLevel );
  172. static void
  173. hb_dbgAddStatic( HB_DEBUGINFO *info, char *szName, int nIndex, int nFrame );
  174. static void
  175. hb_dbgAddStopLines( HB_DEBUGINFO *info, PHB_ITEM pItem );
  176. static void
  177. hb_dbgAddVar( int *nVars, HB_VARINFO **aVars, char *szName, char cType, int nIndex, int nFrame );
  178. static void
  179. hb_dbgEndProc( HB_DEBUGINFO *info );
  180. static PHB_ITEM
  181. hb_dbgEval( HB_DEBUGINFO *info, HB_WATCHPOINT *watch );
  182. static PHB_ITEM
  183. hb_dbgEvalMacro( char *szExpr, PHB_ITEM pItem );
  184. static PHB_ITEM
  185. hb_dbgEvalMakeBlock( HB_WATCHPOINT *watch );
  186. static PHB_ITEM
  187. hb_dbgEvalResolve( HB_DEBUGINFO *info, HB_WATCHPOINT *watch );
  188. static BOOL
  189. hb_dbgIsAltD( void );
  190. static BOOL
  191. hb_dbgIsBreakPoint( HB_DEBUGINFO *info, char *szModule, int nLine );
  192. static BOOL
  193. hb_dbgEqual( PHB_ITEM pItem1, PHB_ITEM pItem2 );
  194. static void
  195. hb_dbgQuit( HB_DEBUGINFO *info );
  196. static PHB_ITEM
  197. hb_dbgVarGet( HB_VARINFO *scope );
  198. static void
  199. hb_dbgVarSet( HB_VARINFO *scope, PHB_ITEM xNewValue );
  200. static void
  201. hb_dbgActivate( HB_DEBUGINFO *info )
  202. {
  203. PHB_DYNS pDynSym = hb_dynsymFind( "__DBGENTRY" );
  204. if( pDynSym && pDynSym->pSymbol->value.pFunPtr )
  205. {
  206. int i;
  207. PHB_ITEM aCallStack = hb_itemArrayNew( info->nCallStackLen );
  208. PHB_ITEM aModules;
  209. PHB_ITEM aBreak;
  210. for ( i = 0; i < info->nCallStackLen; i++ )
  211. {
  212. HB_CALLSTACKINFO *pEntry = &info->aCallStack[ i ];
  213. PHB_ITEM aEntry = hb_itemArrayNew( 6 );
  214. PHB_ITEM pItem;
  215. pItem = hb_itemPutC( NULL, pEntry->szModule );
  216. hb_arraySet( aEntry, 1, pItem );
  217. hb_itemRelease( pItem );
  218. pItem = hb_itemPutC( NULL, pEntry->szFunction );
  219. hb_arraySet( aEntry, 2, pItem );
  220. hb_itemRelease( pItem );
  221. pItem = hb_itemPutNL( NULL, pEntry->nLine );
  222. hb_arraySet( aEntry, 3, pItem );
  223. hb_itemRelease( pItem );
  224. pItem = hb_itemPutNL( NULL, pEntry->nProcLevel );
  225. hb_arraySet( aEntry, 4, pItem );
  226. hb_itemRelease( pItem );
  227. pItem = hb_dbgActivateVarArray( pEntry->nLocals, pEntry->aLocals );
  228. hb_arraySet( aEntry, 5, pItem );
  229. hb_itemRelease( pItem );
  230. pItem = hb_dbgActivateVarArray( pEntry->nStatics, pEntry->aStatics );
  231. hb_arraySet( aEntry, 6, pItem );
  232. hb_itemRelease( pItem );
  233. hb_arraySet( aCallStack, info->nCallStackLen - i, aEntry );
  234. hb_itemRelease( aEntry );
  235. }
  236. aModules = hb_dbgActivateModuleArray( info );
  237. aBreak = hb_dbgActivateBreakArray( info );
  238. hb_vmPushDynSym( pDynSym );
  239. hb_vmPushNil();
  240. hb_vmPushLong( HB_DBG_ACTIVATE );
  241. hb_vmPushPointer( info );
  242. hb_vmPushLong( info->nProcLevel );
  243. hb_vmPush( aCallStack );
  244. hb_vmPush( aModules );
  245. hb_vmPush( aBreak );
  246. hb_itemRelease( aCallStack );
  247. hb_itemRelease( aModules );
  248. hb_itemRelease( aBreak );
  249. hb_vmDo( 6 );
  250. }
  251. }
  252. static PHB_ITEM
  253. hb_dbgActivateBreakArray( HB_DEBUGINFO *info )
  254. {
  255. int i;
  256. PHB_ITEM pArray = hb_itemArrayNew( info->nBreakPoints );
  257. for ( i = 0; i < info->nBreakPoints; i++ )
  258. {
  259. PHB_ITEM pBreak = hb_itemArrayNew( 3 );
  260. PHB_ITEM item;
  261. if ( !info->aBreak[ i ].szFunction )
  262. {
  263. item = hb_itemPutNI( NULL, info->aBreak[ i ].nLine );
  264. hb_arraySet( pBreak, 1, item );
  265. hb_itemRelease( item );
  266. item = hb_itemPutC( NULL, info->aBreak[ i ].szModule );
  267. hb_arraySet( pBreak, 2, item );
  268. hb_itemRelease( item );
  269. }
  270. else
  271. {
  272. item = hb_itemPutC( NULL, info->aBreak[ i ].szFunction );
  273. hb_arraySet( pBreak, 3, item );
  274. hb_itemRelease( item );
  275. }
  276. hb_arraySet( pArray, i + 1, pBreak );
  277. hb_itemRelease( pBreak );
  278. }
  279. return pArray;
  280. }
  281. static PHB_ITEM
  282. hb_dbgActivateModuleArray( HB_DEBUGINFO *info )
  283. {
  284. int i;
  285. PHB_ITEM pArray = hb_itemArrayNew( info->nModules );
  286. for ( i = 0; i < info->nModules; i++ )
  287. {
  288. PHB_ITEM pModule = hb_itemArrayNew( 4 );
  289. PHB_ITEM item;
  290. item = hb_itemPutC( NULL, info->aModules[ i ].szModule );
  291. hb_arraySet( pModule, 1, item );
  292. hb_itemRelease( item );
  293. item = hb_dbgActivateVarArray( info->aModules[ i ].nStatics,
  294. info->aModules[ i ].aStatics );
  295. hb_arraySet( pModule, 2, item );
  296. hb_itemRelease( item );
  297. item = hb_dbgActivateVarArray( info->aModules[ i ].nGlobals,
  298. info->aModules[ i ].aGlobals );
  299. hb_arraySet( pModule, 3, item );
  300. hb_itemRelease( item );
  301. item = hb_dbgActivateVarArray( info->aModules[ i ].nExternGlobals,
  302. info->aModules[ i ].aExternGlobals );
  303. hb_arraySet( pModule, 4, item );
  304. hb_itemRelease( item );
  305. hb_arraySet( pArray, i + 1, pModule );
  306. hb_itemRelease( pModule );
  307. }
  308. return pArray;
  309. }
  310. static PHB_ITEM
  311. hb_dbgActivateVarArray( int nVars, HB_VARINFO *aVars )
  312. {
  313. int i;
  314. PHB_ITEM pArray = hb_itemArrayNew( nVars );
  315. for ( i = 0; i < nVars; i++ )
  316. {
  317. PHB_ITEM aVar = hb_itemArrayNew( 4 );
  318. PHB_ITEM item;
  319. item = hb_itemPutC( NULL, aVars[ i ].szName );
  320. hb_arraySet( aVar, 1, item );
  321. hb_itemRelease( item );
  322. item = hb_itemPutNL( NULL, aVars[ i ].nIndex );
  323. hb_arraySet( aVar, 2, item );
  324. hb_itemRelease( item );
  325. item = hb_itemPutCL( NULL, &aVars[ i ].cType, 1 );
  326. hb_arraySet( aVar, 3, item );
  327. hb_itemRelease( item );
  328. item = hb_itemPutNL( NULL, aVars[ i ].nFrame );
  329. hb_arraySet( aVar, 4, item );
  330. hb_itemRelease( item );
  331. hb_arraySet( pArray, i + 1, aVar );
  332. hb_itemRelease( aVar );
  333. }
  334. return pArray;
  335. }
  336. HB_EXPORT void
  337. hb_dbgEntry( int nMode, int nLine, char *szName, int nIndex, int nFrame )
  338. {
  339. int i;
  340. ULONG nProcLevel;
  341. char szProcName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ];
  342. if ( ( info->bInside || info->bQuit ) && nMode != HB_DBG_VMQUIT )
  343. return;
  344. switch ( nMode )
  345. {
  346. case HB_DBG_MODULENAME:
  347. HB_TRACE( HB_TR_DEBUG, ( "MODULENAME %s", szName ) );
  348. if ( szName[ strlen( szName ) - 1 ] == ':' )
  349. return;
  350. hb_procinfo( 0, szProcName, NULL, NULL );
  351. if ( !strncmp( szProcName, "(_INITSTATICS", 13 ) )
  352. info->bInitStatics = TRUE;
  353. else if ( !strncmp( szProcName, "(_INITGLOBALS", 13 ) )
  354. info->bInitGlobals = TRUE;
  355. else if ( !strncmp( szProcName, "(_INITLINES", 11 ) )
  356. info->bInitLines = TRUE;
  357. if ( info->bInitStatics || info->bInitGlobals )
  358. hb_dbgAddModule( info, szName );
  359. else if ( !strncmp( szProcName, "(b)", 3 ) )
  360. info->bCodeBlock = TRUE;
  361. else if ( info->bNextRoutine )
  362. info->bNextRoutine = FALSE;
  363. hb_dbgAddStack( info, szName, hb_dbg_ProcLevel() );
  364. for ( i = 0; i < info->nBreakPoints; i++ )
  365. {
  366. if ( info->aBreak[ i ].szFunction
  367. && !strcmp( info->aBreak[ i ].szFunction, szProcName ) )
  368. {
  369. hb_dbg_InvokeDebug( TRUE );
  370. break;
  371. }
  372. }
  373. return;
  374. case HB_DBG_LOCALNAME:
  375. HB_TRACE( HB_TR_DEBUG, ( "LOCALNAME %s index %d", szName, nIndex ) );
  376. hb_dbgAddLocal( info, szName, nIndex, hb_dbg_ProcLevel() );
  377. return;
  378. case HB_DBG_STATICNAME:
  379. HB_TRACE( HB_TR_DEBUG, ( "STATICNAME %s index %d frame %d", szName, nIndex, nFrame ) );
  380. hb_dbgAddStatic( info, szName, nIndex, nFrame );
  381. return;
  382. case HB_DBG_SHOWLINE:
  383. {
  384. HB_CALLSTACKINFO *pTop = &info->aCallStack[ info->nCallStackLen - 1 ];
  385. BOOL bOldClsScope;
  386. HB_TRACE( HB_TR_DEBUG, ( "SHOWLINE %d", nLine ) );
  387. nProcLevel = hb_dbg_ProcLevel();
  388. /* Check if we've hit a tracepoint */
  389. bOldClsScope = hb_clsSetScope( FALSE );
  390. for ( i = 0; i < info->nTracePoints; i++ )
  391. {
  392. HB_TRACEPOINT *tp = &info->aTrace[ i ];
  393. PHB_ITEM xValue;
  394. xValue = hb_dbgEval( info, &info->aWatch[ tp->nIndex ] );
  395. if ( !xValue )
  396. xValue = hb_itemNew( NULL );
  397. if ( xValue->type != tp->xValue->type || !hb_dbgEqual( xValue, tp->xValue ) )
  398. {
  399. hb_itemCopy( tp->xValue, xValue );
  400. hb_itemRelease( xValue );
  401. pTop->nLine = nLine;
  402. info->nProcLevel = nProcLevel - ( hb_dbgIsAltD() ? 2 : 0 );
  403. info->bTraceOver = FALSE;
  404. info->bCodeBlock = FALSE;
  405. info->bGo = FALSE;
  406. if ( info->bToCursor )
  407. {
  408. info->bToCursor = FALSE;
  409. FREE( info->szToCursorModule );
  410. }
  411. info->bNextRoutine = FALSE;
  412. hb_dbgActivate( info );
  413. return;
  414. }
  415. hb_itemRelease( xValue );
  416. }
  417. hb_clsSetScope( bOldClsScope );
  418. if ( hb_dbgIsBreakPoint( info, pTop->szModule, nLine )
  419. || hb_dbg_InvokeDebug( FALSE )
  420. || ( info->pFunInvoke && info->pFunInvoke() ) )
  421. {
  422. info->bTraceOver = FALSE;
  423. if ( info->bToCursor )
  424. {
  425. info->bToCursor = FALSE;
  426. FREE( info->szToCursorModule );
  427. }
  428. info->bNextRoutine = FALSE;
  429. info->bGo = FALSE;
  430. }
  431. /* Check if we must skip every level above info->nTraceLevel */
  432. if ( info->bTraceOver )
  433. {
  434. if ( info->nTraceLevel < info->nCallStackLen )
  435. return;
  436. info->bTraceOver = FALSE;
  437. }
  438. /* Check if we're skipping to a specific line of source */
  439. if ( info->bToCursor )
  440. {
  441. if ( nLine == info->nToCursorLine
  442. && FILENAME_EQUAL( pTop->szModule, info->szToCursorModule ) )
  443. {
  444. FREE( info->szToCursorModule );
  445. info->bToCursor = FALSE;
  446. }
  447. else
  448. {
  449. return;
  450. }
  451. }
  452. /* Check if'we skipping to the end of current routine */
  453. if ( info->bNextRoutine )
  454. return;
  455. if ( info->bCodeBlock )
  456. {
  457. info->bCodeBlock = FALSE;
  458. if ( !info->bCBTrace )
  459. return;
  460. }
  461. pTop->nLine = nLine;
  462. if ( !info->bGo )
  463. {
  464. info->nProcLevel = nProcLevel - ( hb_dbgIsAltD() ? 2 : 0 );
  465. hb_dbgActivate( info );
  466. }
  467. return;
  468. }
  469. case HB_DBG_ENDPROC:
  470. if ( info->bQuit )
  471. return;
  472. HB_TRACE( HB_TR_DEBUG, ( "ENDPROC", nLine ) );
  473. if ( info->bInitLines )
  474. {
  475. hb_dbgAddStopLines( info, hb_stackReturnItem() );
  476. }
  477. info->bCodeBlock = FALSE;
  478. info->bInitStatics = FALSE;
  479. info->bInitGlobals = FALSE;
  480. info->bInitLines = FALSE;
  481. hb_dbgEndProc( info );
  482. return;
  483. case HB_DBG_VMQUIT:
  484. hb_dbgQuit( info );
  485. return;
  486. }
  487. }
  488. HB_EXPORT void
  489. hb_dbgAddBreak( void *handle, char *cModule, int nLine, char *szFunction )
  490. {
  491. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  492. HB_BREAKPOINT *pBreak;
  493. pBreak = ARRAY_ADD( HB_BREAKPOINT, info->aBreak, info->nBreakPoints );
  494. pBreak->szModule = STRDUP( cModule );
  495. pBreak->nLine = nLine;
  496. if ( szFunction )
  497. {
  498. pBreak->szFunction = STRDUP( szFunction );
  499. }
  500. else
  501. {
  502. pBreak->szFunction = NULL;
  503. }
  504. }
  505. static void
  506. hb_dbgAddLocal( HB_DEBUGINFO *info, char *szName, int nIndex, int nFrame )
  507. {
  508. if ( info->bInitGlobals )
  509. {
  510. HB_MODULEINFO *module = &info->aModules[ info->nModules - 1 ];
  511. hb_dbgAddVar( &module->nGlobals, &module->aGlobals, szName, 'G', nIndex, hb_dbg_vmVarGCount() );
  512. }
  513. else
  514. {
  515. HB_CALLSTACKINFO *top = &info->aCallStack[ info->nCallStackLen - 1 ];
  516. hb_dbgAddVar( &top->nLocals, &top->aLocals, szName, 'L', nIndex, nFrame );
  517. }
  518. }
  519. static void
  520. hb_dbgAddModule( HB_DEBUGINFO *info, char *szName )
  521. {
  522. char *ptr;
  523. if ( NULL != ( ptr = strrchr( szName, '/' ) ) )
  524. {
  525. szName = ptr + 1;
  526. }
  527. if ( NULL != ( ptr = strrchr( szName, '\\' ) ) )
  528. {
  529. szName = ptr + 1;
  530. }
  531. if ( !info->nModules || strcmp( info->aModules[ info->nModules - 1 ].szModule, szName ) )
  532. {
  533. HB_MODULEINFO *pModule;
  534. pModule = ARRAY_ADD( HB_MODULEINFO, info->aModules, info->nModules );
  535. pModule->szModule = szName;
  536. pModule->nStatics = 0;
  537. pModule->nGlobals = 0;
  538. pModule->nExternGlobals = 0;
  539. }
  540. }
  541. static void
  542. hb_dbgAddStack( HB_DEBUGINFO *info, char *szName, int nProcLevel )
  543. {
  544. char szBuff[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ];
  545. HB_CALLSTACKINFO *top;
  546. char *szFunction = strrchr( szName, ':' );
  547. char *tmp;
  548. if ( szFunction )
  549. {
  550. szFunction++;
  551. }
  552. top = ARRAY_ADD( HB_CALLSTACKINFO, info->aCallStack, info->nCallStackLen );
  553. if ( info->bCodeBlock )
  554. {
  555. memcpy( szBuff, "(b)", 3 );
  556. hb_strncpy( szBuff + 3, szFunction, sizeof( szBuff ) - 4 );
  557. top->szFunction = STRDUP( szBuff );
  558. }
  559. else
  560. {
  561. if ( szFunction )
  562. {
  563. top->szFunction = STRDUP( szFunction );
  564. }
  565. else
  566. {
  567. /* We're in an (_INITSTATICSnnnnn) pseudo-function */
  568. hb_procinfo( 0, szBuff, NULL, NULL );
  569. top->szFunction = STRDUP( szBuff );
  570. }
  571. }
  572. tmp = strrchr( szName, '/' );
  573. if ( tmp )
  574. szName = tmp + 1;
  575. tmp = strrchr( szName, '\\' );
  576. if ( tmp )
  577. szName = tmp + 1;
  578. if ( szFunction )
  579. {
  580. STRNDUP( top->szModule, szName, szFunction - szName - 1 );
  581. }
  582. else
  583. {
  584. top->szModule = STRDUP( szName );
  585. }
  586. top->nProcLevel = nProcLevel;
  587. top->nLine = 0;
  588. top->nLocals = 0;
  589. top->nStatics = 0;
  590. }
  591. static void
  592. hb_dbgAddStatic( HB_DEBUGINFO *info, char *szName, int nIndex, int nFrame )
  593. {
  594. if ( info->bInitGlobals )
  595. {
  596. HB_MODULEINFO *module = &info->aModules[ info->nModules - 1 ];
  597. hb_dbgAddVar( &module->nExternGlobals, &module->aExternGlobals, szName,
  598. 'G', nIndex, hb_dbg_vmVarGCount() );
  599. }
  600. else if ( info->bInitStatics )
  601. {
  602. HB_MODULEINFO *module = &info->aModules[ info->nModules - 1 ];
  603. hb_dbgAddVar( &module->nStatics, &module->aStatics, szName, 'S', nIndex, nFrame );
  604. }
  605. else
  606. {
  607. HB_CALLSTACKINFO *top = &info->aCallStack[ info->nCallStackLen - 1 ];
  608. hb_dbgAddVar( &top->nStatics, &top->aStatics, szName, 'S', nIndex, nFrame );
  609. }
  610. }
  611. static void
  612. hb_dbgAddStopLines( HB_DEBUGINFO *info, PHB_ITEM pItem )
  613. {
  614. int i, nLinesLen;
  615. if ( !info->pStopLines )
  616. {
  617. info->pStopLines = hb_itemNew( pItem );
  618. }
  619. else
  620. {
  621. int j;
  622. int nItemLen = hb_itemSize( pItem );
  623. nLinesLen = hb_itemSize( info->pStopLines );
  624. for ( i = 1; i <= nItemLen; i++ )
  625. {
  626. PHB_ITEM pEntry = hb_arrayGetItemPtr( pItem, i );
  627. char *szModule = hb_arrayGetCPtr( pEntry, 1 );
  628. char *p;
  629. BOOL bFound = FALSE;
  630. if ( ( p = strrchr( szModule, '/' ) ) != NULL
  631. || ( p = strrchr( szModule, '\\' ) ) != NULL )
  632. {
  633. szModule = p + 1;
  634. }
  635. for ( j = 1; j <= nLinesLen; j++ )
  636. {
  637. PHB_ITEM pLines = hb_arrayGetItemPtr( info->pStopLines, j );
  638. if ( !strcmp( hb_arrayGetCPtr( pLines, 1 ), szModule ) )
  639. {
  640. /* Merge stopline info */
  641. int nOrigMin = hb_arrayGetNL( pLines, 2 );
  642. int nNewMin = hb_arrayGetNL( pEntry, 2 );
  643. int nOrigLen = hb_arrayGetCLen( pLines, 3 );
  644. int nNewLen = hb_arrayGetCLen( pEntry, 3 );
  645. int nMin = HB_MIN( nNewMin, nOrigMin );
  646. int nMax = HB_MAX( nNewMin + nNewLen * 8, nOrigMin + nOrigLen * 8 );
  647. char *pOrigBuffer = hb_arrayGetCPtr( pLines, 3 );
  648. char *pNewBuffer = hb_arrayGetCPtr( pEntry, 3 );
  649. int nLen = ( nMax + 1 - nMin + 7 ) / 8 + 1;
  650. int k;
  651. char *pBuffer = (char *) hb_xgrab( nLen );
  652. hb_xmemset( pBuffer, 0, nLen );
  653. memmove( &( pBuffer[ ( nNewMin - nMin ) / 8 ] ), pNewBuffer, nNewLen );
  654. for ( k = 0; k < nOrigLen; k++ )
  655. {
  656. pBuffer[ nOrigMin / 8 + k - nMin / 8 ] |= pOrigBuffer[ k ];
  657. }
  658. hb_itemPutNL( hb_arrayGetItemPtr( pLines, 2 ), nMin );
  659. hb_itemPutCPtr( hb_arrayGetItemPtr( pLines, 3 ), pBuffer, nLen - 1 );
  660. bFound = TRUE;
  661. break;
  662. }
  663. }
  664. if ( !bFound )
  665. {
  666. hb_arrayAddForward( info->pStopLines, pEntry );
  667. }
  668. }
  669. }
  670. nLinesLen = hb_itemSize( info->pStopLines );
  671. for ( i = 1; i <= nLinesLen; i++ )
  672. {
  673. PHB_ITEM pEntry = hb_arrayGetItemPtr( info->pStopLines, i );
  674. char *szModule = hb_arrayGetCPtr( pEntry, 1 );
  675. char *p;
  676. if ( ( p = strrchr( szModule, '/' ) ) != NULL
  677. || ( p = strrchr( szModule, '\\' ) ) != NULL )
  678. {
  679. char *szName = hb_strdup( p + 1 );
  680. hb_itemPutC( hb_arrayGetItemPtr( pEntry, 1 ), szName );
  681. hb_xfree( szName );
  682. }
  683. }
  684. }
  685. static void
  686. hb_dbgAddVar( int *nVars, HB_VARINFO **aVars, char *szName, char cType, int nIndex, int nFrame )
  687. {
  688. HB_VARINFO *var;
  689. var = ARRAY_ADD( HB_VARINFO, *aVars, *nVars );
  690. var->szName = szName;
  691. var->cType = cType;
  692. var->nIndex = nIndex;
  693. var->nFrame = nFrame;
  694. }
  695. HB_EXPORT void
  696. hb_dbgAddWatch( void *handle, char *szExpr, BOOL bTrace )
  697. {
  698. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  699. HB_WATCHPOINT *pWatch;
  700. pWatch = ARRAY_ADD( HB_WATCHPOINT, info->aWatch, info->nWatchPoints );
  701. pWatch->szExpr = STRDUP( szExpr );
  702. pWatch->pBlock = NULL;
  703. pWatch->nVars = 0;
  704. if ( bTrace )
  705. {
  706. HB_TRACEPOINT *pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
  707. pTrace->nIndex = info->nWatchPoints - 1;
  708. pTrace->xValue = hb_dbgEval( info, pWatch );
  709. }
  710. }
  711. static void
  712. hb_dbgClearWatch( HB_WATCHPOINT *pWatch )
  713. {
  714. FREE( pWatch->szExpr );
  715. if ( pWatch->pBlock )
  716. {
  717. hb_itemRelease( pWatch->pBlock );
  718. }
  719. if ( pWatch->nVars )
  720. {
  721. int i;
  722. for (i = 0; i < pWatch->nVars; i++)
  723. {
  724. FREE( pWatch->aVars[ i ] );
  725. }
  726. FREE( pWatch->aVars );
  727. }
  728. }
  729. HB_EXPORT void
  730. hb_dbgDelBreak( void *handle, int nBreak )
  731. {
  732. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  733. HB_BREAKPOINT *pBreak = &info->aBreak[ nBreak ];
  734. FREE( pBreak->szModule );
  735. if ( pBreak->szFunction )
  736. {
  737. FREE( pBreak->szFunction );
  738. }
  739. ARRAY_DEL( HB_BREAKPOINT, info->aBreak, info->nBreakPoints, nBreak );
  740. }
  741. HB_EXPORT void
  742. hb_dbgDelWatch( void *handle, int nWatch )
  743. {
  744. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  745. HB_WATCHPOINT *pWatch = &info->aWatch[ nWatch ];
  746. int i;
  747. hb_dbgClearWatch( pWatch );
  748. ARRAY_DEL( HB_WATCHPOINT, info->aWatch, info->nWatchPoints, nWatch );
  749. for ( i = 0; i < info->nTracePoints; i++ )
  750. {
  751. HB_TRACEPOINT *pTrace = &info->aTrace[ i ];
  752. if ( pTrace->nIndex == nWatch )
  753. {
  754. if ( pTrace->xValue )
  755. {
  756. hb_itemRelease( pTrace->xValue );
  757. }
  758. ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i );
  759. i--;
  760. }
  761. else if ( pTrace->nIndex > nWatch )
  762. {
  763. pTrace->nIndex--;
  764. }
  765. }
  766. }
  767. static void
  768. hb_dbgEndProc( HB_DEBUGINFO *info )
  769. {
  770. HB_CALLSTACKINFO *top;
  771. if ( !info->nCallStackLen )
  772. return;
  773. top = &info->aCallStack[ --info->nCallStackLen ];
  774. FREE( top->szFunction );
  775. FREE( top->szModule );
  776. if ( top->nLocals )
  777. {
  778. FREE( top->aLocals );
  779. }
  780. if ( top->nStatics )
  781. {
  782. FREE( top->aStatics );
  783. }
  784. if ( !info->nCallStackLen )
  785. {
  786. FREE( info->aCallStack );
  787. info->aCallStack = NULL;
  788. }
  789. }
  790. static BOOL
  791. hb_dbgEqual( PHB_ITEM pItem1, PHB_ITEM pItem2 )
  792. {
  793. if ( pItem1->type != pItem2->type )
  794. return FALSE;
  795. if ( HB_IS_NIL( pItem1 ) )
  796. return HB_IS_NIL( pItem2 );
  797. if ( HB_IS_LOGICAL( pItem1 ) )
  798. return ( pItem1->item.asLogical.value == pItem2->item.asLogical.value );
  799. if ( HB_IS_POINTER( pItem1 ) )
  800. return ( pItem1->item.asPointer.value == pItem2->item.asPointer.value );
  801. if ( HB_IS_STRING( pItem1 ) )
  802. return !hb_itemStrCmp( pItem1, pItem2, TRUE );
  803. if ( HB_IS_NUMINT( pItem1 ) )
  804. return ( HB_ITEM_GET_NUMINTRAW( pItem1 ) == HB_ITEM_GET_NUMINTRAW( pItem2 ) );
  805. if ( HB_IS_NUMERIC( pItem1 ) )
  806. return ( hb_itemGetND( pItem1 ) == hb_itemGetND( pItem2 ) );
  807. if ( HB_IS_ARRAY( pItem1 ) )
  808. return ( pItem1->item.asArray.value == pItem2->item.asArray.value );
  809. if ( HB_IS_HASH( pItem1 ) )
  810. return ( pItem1->item.asHash.value == pItem2->item.asHash.value );
  811. return FALSE;
  812. }
  813. static PHB_ITEM
  814. hb_dbgEval( HB_DEBUGINFO *info, HB_WATCHPOINT *watch )
  815. {
  816. PHB_ITEM xResult = NULL;
  817. HB_TRACE( HB_TR_DEBUG, ( "expr %s", watch->szExpr ) );
  818. /* Check if we have a cached pBlock */
  819. if ( !watch->pBlock )
  820. {
  821. watch->pBlock = hb_dbgEvalMakeBlock( watch );
  822. }
  823. if ( watch->pBlock )
  824. {
  825. PHB_ITEM aVars = hb_dbgEvalResolve( info, watch );
  826. PHB_ITEM aNewVars = hb_itemArrayNew( watch->nVars );
  827. int i;
  828. hb_arrayCopy( aVars, aNewVars, NULL, NULL, NULL );
  829. info->bInside = TRUE;
  830. xResult = hb_itemDo( watch->pBlock, 1, aNewVars );
  831. info->bInside = FALSE;
  832. for ( i = 0; i < watch->nVars; i++ )
  833. {
  834. PHB_ITEM xOldValue = hb_itemArrayGet( aVars, i + 1 );
  835. PHB_ITEM xNewValue = hb_itemArrayGet( aNewVars, i + 1 );
  836. if ( !hb_dbgEqual( xOldValue, xNewValue ) )
  837. {
  838. hb_dbgVarSet( &watch->aScopes[ i ], xNewValue );
  839. }
  840. hb_itemRelease( xOldValue );
  841. hb_itemRelease( xNewValue );
  842. }
  843. hb_itemRelease( aVars );
  844. hb_itemRelease( aNewVars );
  845. for ( i = 0; i < watch->nVars; i++ )
  846. {
  847. if ( watch->aScopes[ i ].cType == 'M' )
  848. {
  849. FREE( watch->aScopes[ i ].szName );
  850. }
  851. }
  852. if ( watch->nVars )
  853. {
  854. FREE( watch->aScopes );
  855. }
  856. }
  857. return xResult;
  858. }
  859. static PHB_ITEM
  860. hb_dbgEvalMacro( char *szExpr, PHB_ITEM pItem )
  861. {
  862. PHB_ITEM pStr;
  863. const char *type;
  864. pStr = hb_itemPutC( NULL, szExpr );
  865. type = hb_macroGetType( pStr );
  866. hb_itemRelease( pStr );
  867. if ( ( !strcmp( type, "U" ) || !strcmp( type, "UE" ) ) )
  868. {
  869. return NULL;
  870. }
  871. hb_vmPushString( szExpr, strlen( szExpr ) );
  872. hb_macroGetValue( hb_stackItemFromTop( -1 ), 0, HB_SM_RT_MACRO );
  873. hb_itemForwardValue( pItem, hb_stackItemFromTop( -1 ) );
  874. hb_stackPop();
  875. return pItem;
  876. }
  877. #define IS_IDENT_START( c ) ( isalpha( (UCHAR) (c) ) || (c) == '_' )
  878. #define IS_IDENT_CHAR( c ) ( IS_IDENT_START( (c) ) || isdigit( (UCHAR) (c) ) )
  879. static PHB_ITEM
  880. hb_dbgEvalMakeBlock( HB_WATCHPOINT *watch )
  881. {
  882. int i = 0;
  883. PHB_ITEM pBlock;
  884. BOOL bAfterId = FALSE;
  885. char *s;
  886. watch->nVars = 0;
  887. while ( watch->szExpr[ i ] )
  888. {
  889. char c = watch->szExpr[ i ];
  890. if ( IS_IDENT_START( c ) )
  891. {
  892. int nStart = i, nLen;
  893. int j = i;
  894. char *szWord;
  895. while ( c && IS_IDENT_CHAR( c ) )
  896. {
  897. j++;
  898. c = watch->szExpr[ j ];
  899. }
  900. nLen = j - i;
  901. STRNDUP( szWord, watch->szExpr + i, nLen );
  902. i = j;
  903. if ( c )
  904. {
  905. while ( watch->szExpr[ i ] && watch->szExpr[ i ] == ' ' )
  906. {
  907. i++;
  908. }
  909. if ( watch->szExpr[ i ] == '(' )
  910. {
  911. FREE( szWord );
  912. continue;
  913. }
  914. if ( watch->szExpr[ i ] == '-' && watch->szExpr[ i + 1 ] == '>' )
  915. {
  916. i += 2;
  917. while ( ( c = watch->szExpr[ i ] ) != '\0' && IS_IDENT_CHAR( c ) )
  918. {
  919. i++;
  920. }
  921. FREE( szWord );
  922. continue;
  923. }
  924. }
  925. hb_strupr( szWord );
  926. for ( j = 0; j < watch->nVars; j++ )
  927. {
  928. if ( !strcmp( szWord, watch->aVars[ j ] ) )
  929. {
  930. break;
  931. }
  932. }
  933. if ( j == watch->nVars )
  934. {
  935. *ARRAY_ADD( char *, watch->aVars, watch->nVars ) = szWord;
  936. }
  937. else
  938. {
  939. FREE( szWord );
  940. }
  941. {
  942. char *t = (char *) ALLOC( strlen( watch->szExpr ) - nLen + 9 + 1 );
  943. memmove( t, watch->szExpr, nStart );
  944. memmove( t + nStart, "__dbg[", 6 );
  945. t[ nStart + 6 ] = '0' + ( ( j + 1 ) / 10 );
  946. t[ nStart + 7 ] = '0' + ( ( j + 1 ) % 10 );
  947. t[ nStart + 8 ] = ']';
  948. strcpy( t + nStart + 9, watch->szExpr + nStart + nLen );
  949. FREE( watch->szExpr );
  950. watch->szExpr = t;
  951. i = nStart + 9;
  952. }
  953. bAfterId = TRUE;
  954. continue;
  955. }
  956. if ( c == '.' )
  957. {
  958. if ( watch->szExpr[ i + 1 ]
  959. && strchr( "TtFf", watch->szExpr[ i + 1 ] )
  960. && watch->szExpr[ i + 2 ] == '.' )
  961. {
  962. i += 3;
  963. }
  964. else if ( !hb_strnicmp( watch->szExpr + i + 1, "OR.", 3 ) )
  965. {
  966. i += 4;
  967. }
  968. else if ( !hb_strnicmp( watch->szExpr + i + 1, "AND.", 4 )
  969. || !hb_strnicmp( watch->szExpr + i + 1, "NOT.", 4 ) )
  970. {
  971. i += 5;
  972. }
  973. else
  974. {
  975. i++;
  976. }
  977. bAfterId = FALSE;
  978. continue;
  979. }
  980. if ( c == ':'
  981. || ( c == '-' && watch->szExpr[ i + 1 ] == '>'
  982. && IS_IDENT_START( watch->szExpr[ i + 2 ] ) ) )
  983. {
  984. if ( c == '-' )
  985. {
  986. i++;
  987. }
  988. i++;
  989. while ( watch->szExpr[ i ] && IS_IDENT_CHAR( watch->szExpr[ i ] ) )
  990. {
  991. i++;
  992. }
  993. bAfterId = TRUE;
  994. continue;
  995. }
  996. if ( strchr( " !#$=<>(+-*/%^|,{&", c ) )
  997. {
  998. i++;
  999. bAfterId = FALSE;
  1000. continue;
  1001. }
  1002. if ( c == '\'' || c == '\"' )
  1003. {
  1004. i++;
  1005. while ( watch->szExpr[ i ] && watch->szExpr[ i ] != c )
  1006. {
  1007. i++;
  1008. }
  1009. if ( watch->szExpr[ i ] )
  1010. {
  1011. i++;
  1012. }
  1013. bAfterId = TRUE;
  1014. continue;
  1015. }
  1016. if ( c == '[' )
  1017. {
  1018. i++;
  1019. if ( bAfterId )
  1020. {
  1021. bAfterId = FALSE;
  1022. }
  1023. else
  1024. {
  1025. while ( watch->szExpr[ i ] && watch->szExpr[ i ] != ']' )
  1026. {
  1027. i++;
  1028. }
  1029. if ( watch->szExpr[ i ] )
  1030. {
  1031. i++;
  1032. }
  1033. bAfterId = TRUE;
  1034. }
  1035. continue;
  1036. }
  1037. i++;
  1038. }
  1039. s = ( char * ) ALLOC( 8 + strlen( watch->szExpr ) + 1 + 1 );
  1040. strcpy( s, "{|__dbg|" );
  1041. strcat( s, watch->szExpr );
  1042. strcat( s, "}" );
  1043. pBlock = hb_itemNew( NULL );
  1044. if( ! hb_dbgEvalMacro( s, pBlock ) )
  1045. {
  1046. hb_itemRelease( pBlock );
  1047. pBlock = NULL;
  1048. }
  1049. FREE( s );
  1050. return pBlock;
  1051. }
  1052. static PHB_ITEM
  1053. hb_dbgEvalResolve( HB_DEBUGINFO *info, HB_WATCHPOINT *watch )
  1054. {
  1055. int i;
  1056. HB_CALLSTACKINFO *top = &info->aCallStack[ info->nCallStackLen - 1 ];
  1057. PHB_ITEM aVars = hb_itemArrayNew( watch->nVars );
  1058. HB_VARINFO *scopes;
  1059. HB_MODULEINFO *module = NULL;
  1060. int nProcLevel;
  1061. if ( !watch->nVars )
  1062. {
  1063. return aVars;
  1064. }
  1065. scopes = (HB_VARINFO *) ALLOC( watch->nVars * sizeof( HB_VARINFO ) );
  1066. nProcLevel = hb_dbg_ProcLevel();
  1067. for ( i = 0; i < info->nModules; i++ )
  1068. {
  1069. if ( !strcmp( info->aModules[ i ].szModule, top->szModule ) )
  1070. {
  1071. module = &info->aModules[ i ];
  1072. break;
  1073. }
  1074. }
  1075. for ( i = 0; i < watch->nVars; i++ )
  1076. {
  1077. char *name = watch->aVars[ i ];
  1078. HB_VARINFO *var;
  1079. int j;
  1080. PHB_ITEM pItem;
  1081. for ( j = 0; j < top->nLocals; j++ )
  1082. {
  1083. var = &top->aLocals[ j ];
  1084. if ( !strcmp( name, var->szName ) )
  1085. {
  1086. scopes[ i ].cType = 'L';
  1087. scopes[ i ].nFrame = nProcLevel - var->nFrame;
  1088. scopes[ i ].nIndex = var->nIndex;
  1089. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1090. break;
  1091. }
  1092. }
  1093. if ( j < top->nLocals )
  1094. continue;
  1095. for ( j = 0; j < top->nStatics; j++ )
  1096. {
  1097. var = &top->aStatics[ j ];
  1098. if ( !strcmp( name, var->szName ) )
  1099. {
  1100. scopes[ i ].cType = 'S';
  1101. scopes[ i ].nFrame = var->nFrame;
  1102. scopes[ i ].nIndex = var->nIndex;
  1103. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1104. break;
  1105. }
  1106. }
  1107. if ( j < top->nStatics )
  1108. continue;
  1109. if ( module )
  1110. {
  1111. for ( j = 0; j < module->nStatics; j++ )
  1112. {
  1113. var = &module->aStatics[ j ];
  1114. if ( !strcmp( name, var->szName ) )
  1115. {
  1116. scopes[ i ].cType = 'S';
  1117. scopes[ i ].nFrame = var->nFrame;
  1118. scopes[ i ].nIndex = var->nIndex;
  1119. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1120. break;
  1121. }
  1122. }
  1123. if ( j < module->nStatics )
  1124. continue;
  1125. for ( j = 0; j < module->nGlobals; j++ )
  1126. {
  1127. var = &module->aGlobals[ j ];
  1128. if ( !strcmp( name, var->szName ) )
  1129. {
  1130. scopes[ i ].cType = 'G';
  1131. scopes[ i ].nFrame = var->nFrame;
  1132. scopes[ i ].nIndex = var->nIndex;
  1133. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1134. break;
  1135. }
  1136. }
  1137. if ( j < module->nGlobals )
  1138. continue;
  1139. for ( j = 0; j < module->nExternGlobals; j++ )
  1140. {
  1141. var = &module->aExternGlobals[ j ];
  1142. if ( !strcmp( name, var->szName ) )
  1143. {
  1144. scopes[ i ].cType = 'G';
  1145. scopes[ i ].nFrame = var->nFrame;
  1146. scopes[ i ].nIndex = var->nIndex;
  1147. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1148. break;
  1149. }
  1150. }
  1151. if ( j < module->nExternGlobals )
  1152. continue;
  1153. }
  1154. scopes[ i ].cType = 'M';
  1155. scopes[ i ].szName = STRDUP( name );
  1156. pItem = hb_dbgVarGet( &scopes[ i ] );
  1157. if ( pItem )
  1158. {
  1159. hb_itemArrayPut( aVars, i + 1, pItem );
  1160. }
  1161. if ( scopes[ i ].cType == 'F' )
  1162. {
  1163. hb_itemRelease( pItem );
  1164. }
  1165. }
  1166. watch->aScopes = scopes;
  1167. return aVars;
  1168. }
  1169. HB_EXPORT PHB_ITEM
  1170. hb_dbgGetExpressionValue( void *handle, char *expression )
  1171. {
  1172. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1173. PHB_ITEM result;
  1174. HB_WATCHPOINT point;
  1175. point.szExpr = STRDUP( expression );
  1176. point.pBlock = NULL;
  1177. point.nVars = 0;
  1178. result = hb_dbgEval( info, &point );
  1179. hb_dbgClearWatch( &point );
  1180. return result;
  1181. }
  1182. HB_EXPORT PHB_ITEM
  1183. hb_dbgGetSourceFiles( void *handle )
  1184. {
  1185. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1186. int nModules = hb_itemSize( info->pStopLines );
  1187. PHB_ITEM ret = hb_itemArrayNew( nModules );
  1188. int i;
  1189. for ( i = 1; i <= nModules; i++ )
  1190. {
  1191. hb_arraySet( ret, i, hb_arrayGetItemPtr( hb_arrayGetItemPtr( info->pStopLines, i ), 1 ) );
  1192. }
  1193. return ret;
  1194. }
  1195. HB_EXPORT PHB_ITEM
  1196. hb_dbgGetWatchValue( void *handle, int nWatch )
  1197. {
  1198. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1199. return hb_dbgEval( info, &( info->aWatch[ nWatch ] ) );
  1200. }
  1201. static BOOL
  1202. hb_dbgIsAltD( void )
  1203. {
  1204. char szName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5];
  1205. hb_procinfo( 1, szName, NULL, NULL );
  1206. return !strcmp( szName, "ALTD" );
  1207. }
  1208. static BOOL
  1209. hb_dbgIsBreakPoint( HB_DEBUGINFO *info, char *szModule, int nLine )
  1210. {
  1211. int i;
  1212. for ( i = 0; i < info->nBreakPoints; i++ )
  1213. {
  1214. HB_BREAKPOINT *point = &info->aBreak[ i ];
  1215. if ( point->nLine == nLine
  1216. && FILENAME_EQUAL( szModule, point->szModule ) )
  1217. return TRUE;
  1218. }
  1219. return FALSE;
  1220. }
  1221. HB_EXPORT BOOL
  1222. hb_dbgIsValidStopLine( void *handle, char *szModule, int nLine )
  1223. {
  1224. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1225. int nModules = hb_itemSize( info->pStopLines );
  1226. int i;
  1227. for ( i = 1; i <= nModules; i++ )
  1228. {
  1229. PHB_ITEM pEntry = hb_arrayGetItemPtr( info->pStopLines, i );
  1230. if ( FILENAME_EQUAL( hb_arrayGetCPtr( pEntry, 1 ), szModule ) )
  1231. {
  1232. int nMin = hb_arrayGetNL( pEntry, 2 );
  1233. int nOfs = nLine - nMin;
  1234. if ( nLine < nMin || (ULONG)( nOfs / 8 ) > hb_arrayGetCLen( pEntry, 3 ) )
  1235. {
  1236. return FALSE;
  1237. }
  1238. return ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs / 8 ] & ( 1 << ( nOfs % 8 ) ) ) != 0;
  1239. }
  1240. }
  1241. return FALSE;
  1242. }
  1243. static void
  1244. hb_dbgQuit( HB_DEBUGINFO *info )
  1245. {
  1246. while ( info->nWatchPoints )
  1247. {
  1248. hb_dbgDelWatch( info, info->nWatchPoints - 1 );
  1249. }
  1250. while ( info->nBreakPoints )
  1251. {
  1252. hb_dbgDelBreak( info, info->nBreakPoints - 1 );
  1253. }
  1254. while ( info->nCallStackLen )
  1255. {
  1256. hb_dbgEndProc( info );
  1257. }
  1258. if ( info->pStopLines )
  1259. {
  1260. hb_itemRelease( info->pStopLines );
  1261. }
  1262. while ( info->nModules )
  1263. {
  1264. int nModules = info->nModules - 1;
  1265. HB_MODULEINFO *module = &info->aModules[ nModules ];
  1266. if ( module->nStatics )
  1267. {
  1268. FREE( module->aStatics );
  1269. }
  1270. ARRAY_DEL( HB_MODULEINFO, info->aModules, info->nModules, nModules );
  1271. }
  1272. }
  1273. HB_EXPORT void
  1274. hb_dbgSetCBTrace( void *handle, BOOL bCBTrace )
  1275. {
  1276. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1277. info->bCBTrace = bCBTrace;
  1278. }
  1279. HB_EXPORT void
  1280. hb_dbgSetGo( void *handle )
  1281. {
  1282. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1283. info->bGo = TRUE;
  1284. }
  1285. HB_EXPORT void
  1286. hb_dbgSetInvoke( void *handle, BOOL ( *pFunInvoke )( void ) )
  1287. {
  1288. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1289. info->pFunInvoke = pFunInvoke;
  1290. }
  1291. HB_EXPORT void
  1292. hb_dbgSetNextRoutine( void *handle )
  1293. {
  1294. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1295. info->bNextRoutine = TRUE;
  1296. }
  1297. HB_EXPORT void
  1298. hb_dbgSetQuit( void *handle )
  1299. {
  1300. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1301. info->bQuit = TRUE;
  1302. }
  1303. HB_EXPORT void
  1304. hb_dbgSetToCursor( void *handle, char *szModule, int nLine )
  1305. {
  1306. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1307. info->bToCursor = TRUE;
  1308. info->szToCursorModule = STRDUP( szModule );
  1309. info->nToCursorLine = nLine;
  1310. }
  1311. HB_EXPORT void
  1312. hb_dbgSetTrace( void *handle )
  1313. {
  1314. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1315. info->bTraceOver = TRUE;
  1316. info->nTraceLevel = info->nCallStackLen;
  1317. }
  1318. HB_EXPORT void
  1319. hb_dbgSetWatch( void *handle, int nWatch, char *szExpr, BOOL bTrace )
  1320. {
  1321. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1322. HB_WATCHPOINT *pWatch = &info->aWatch[ nWatch ];
  1323. int i;
  1324. hb_dbgClearWatch( pWatch );
  1325. pWatch->szExpr = STRDUP( szExpr );
  1326. pWatch->pBlock = NULL;
  1327. for ( i = 0; i < info->nTracePoints; i++ )
  1328. {
  1329. HB_TRACEPOINT *pTrace = &info->aTrace[ i ];
  1330. if ( pTrace->nIndex == nWatch )
  1331. {
  1332. if ( pTrace->xValue )
  1333. {
  1334. hb_itemRelease( pTrace->xValue );
  1335. }
  1336. ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i );
  1337. break;
  1338. }
  1339. }
  1340. if ( bTrace )
  1341. {
  1342. HB_TRACEPOINT *pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
  1343. pTrace->nIndex = nWatch;
  1344. pTrace->xValue = hb_dbgEval( info, pWatch );
  1345. }
  1346. }
  1347. static PHB_ITEM
  1348. hb_dbgVarGet( HB_VARINFO *scope )
  1349. {
  1350. switch ( scope->cType )
  1351. {
  1352. case 'G':
  1353. return hb_dbg_vmVarGGet( scope->nFrame, scope->nIndex );
  1354. case 'L':
  1355. return hb_dbg_vmVarLGet( scope->nFrame, scope->nIndex );
  1356. case 'S':
  1357. return hb_dbg_vmVarSGet( scope->nFrame, scope->nIndex );
  1358. case 'M':
  1359. {
  1360. PHB_DYNS pDyn;
  1361. pDyn = hb_dynsymFind( scope->szName );
  1362. if ( pDyn != NULL )
  1363. {
  1364. if ( pDyn->hMemvar == 0 )
  1365. {
  1366. PHB_ITEM pItem = hb_itemNew( NULL );
  1367. if ( hb_rddFieldGet( pItem, pDyn->pSymbol ) == SUCCESS )
  1368. {
  1369. scope->cType = 'F';
  1370. return pItem;
  1371. }
  1372. hb_itemRelease( pItem );
  1373. }
  1374. else
  1375. {
  1376. return hb_memvarGetValueByHandle( pDyn->hMemvar );
  1377. }
  1378. }
  1379. return NULL;
  1380. }
  1381. default:
  1382. return NULL;
  1383. }
  1384. }
  1385. static void
  1386. hb_dbgVarSet( HB_VARINFO *scope, PHB_ITEM xNewValue )
  1387. {
  1388. switch ( scope->cType )
  1389. {
  1390. case 'G':
  1391. case 'L':
  1392. case 'S':
  1393. hb_itemCopy( hb_dbgVarGet( scope ), xNewValue );
  1394. break;
  1395. case 'M':
  1396. {
  1397. PHB_DYNS pDynSym = hb_dynsymFind( "__MVPUT" );
  1398. if ( pDynSym && pDynSym->pSymbol->value.pFunPtr )
  1399. {
  1400. hb_vmPushDynSym( pDynSym );
  1401. hb_vmPushNil();
  1402. hb_vmPushString( scope->szName, strlen( scope->szName ) );
  1403. hb_vmPush( xNewValue );
  1404. hb_vmDo( 2 );
  1405. }
  1406. break;
  1407. }
  1408. }
  1409. }
  1410. /*
  1411. * .prg functions
  1412. */
  1413. HB_FUNC( HB_DBG_SETENTRY )
  1414. {
  1415. hb_dbg_SetEntry( hb_dbgEntry );
  1416. }
  1417. HB_FUNC( HB_DBG_SETGO )
  1418. {
  1419. void * ptr = hb_parptr( 1 );
  1420. if( ptr )
  1421. hb_dbgSetGo( ptr );
  1422. }
  1423. HB_FUNC( HB_DBG_SETTRACE )
  1424. {
  1425. void * ptr = hb_parptr( 1 );
  1426. if( ptr )
  1427. hb_dbgSetTrace( ptr );
  1428. }
  1429. HB_FUNC( HB_DBG_SETCBTRACE )
  1430. {
  1431. void * ptr = hb_parptr( 1 );
  1432. if( ptr )
  1433. hb_dbgSetCBTrace( ptr, hb_parl( 2 ) );
  1434. }
  1435. HB_FUNC( HB_DBG_SETNEXTROUTINE )
  1436. {
  1437. void * ptr = hb_parptr( 1 );
  1438. if( ptr )
  1439. hb_dbgSetNextRoutine( ptr );
  1440. }
  1441. HB_FUNC( HB_DBG_SETQUIT )
  1442. {
  1443. void * ptr = hb_parptr( 1 );
  1444. if( ptr )
  1445. hb_dbgSetQuit( ptr );
  1446. }
  1447. HB_FUNC( HB_DBG_SETTOCURSOR )
  1448. {
  1449. void * ptr = hb_parptr( 1 );
  1450. if( ptr )
  1451. hb_dbgSetToCursor( ptr, hb_parc( 2 ), hb_parni( 3 ) );
  1452. }
  1453. HB_FUNC( HB_DBG_GETEXPRVALUE )
  1454. {
  1455. void * ptr = hb_parptr( 1 );
  1456. if( ptr )
  1457. {
  1458. PHB_ITEM pItem;
  1459. if( ISCHAR( 2 ) )
  1460. pItem = hb_dbgGetExpressionValue( hb_parptr( 1 ), hb_parc( 2 ) );
  1461. else
  1462. pItem = hb_dbgGetWatchValue( hb_parptr( 1 ), hb_parni( 2 ) - 1 );
  1463. if( pItem )
  1464. {
  1465. hb_storl( TRUE, 3 );
  1466. hb_itemRelease( hb_itemReturn( pItem ) );
  1467. }
  1468. else
  1469. hb_storl( FALSE, 3 );
  1470. }
  1471. }
  1472. HB_FUNC( HB_DBG_GETSOURCEFILES )
  1473. {
  1474. void * ptr = hb_parptr( 1 );
  1475. if( ptr )
  1476. hb_itemRelease( hb_itemReturn( hb_dbgGetSourceFiles( ptr ) ) );
  1477. }
  1478. HB_FUNC( HB_DBG_ISVALIDSTOPLINE )
  1479. {
  1480. void * ptr = hb_parptr( 1 );
  1481. if( ptr )
  1482. hb_retl( hb_dbgIsValidStopLine( ptr, hb_parc( 2 ), hb_parni( 3 ) ) );
  1483. }
  1484. HB_FUNC( HB_DBG_ADDBREAK )
  1485. {
  1486. void * ptr = hb_parptr( 1 );
  1487. if( ptr )
  1488. hb_dbgAddBreak( ptr, hb_parc( 2 ), hb_parni( 3 ), NULL );
  1489. }
  1490. HB_FUNC( HB_DBG_DELBREAK )
  1491. {
  1492. void * ptr = hb_parptr( 1 );
  1493. if( ptr )
  1494. hb_dbgDelBreak( ptr, hb_parni( 2 ) );
  1495. }
  1496. HB_FUNC( HB_DBG_ADDWATCH )
  1497. {
  1498. void * ptr = hb_parptr( 1 );
  1499. if( ptr )
  1500. hb_dbgAddWatch( ptr, hb_parc( 2 ), hb_parl( 3 ) );
  1501. }
  1502. HB_FUNC( HB_DBG_DELWATCH )
  1503. {
  1504. void * ptr = hb_parptr( 1 );
  1505. if( ptr )
  1506. hb_dbgDelWatch( ptr, hb_parni( 2 ) );
  1507. }
  1508. HB_FUNC( HB_DBG_SETWATCH )
  1509. {
  1510. void * ptr = hb_parptr( 1 );
  1511. if( ptr )
  1512. hb_dbgSetWatch( ptr, hb_parni( 2 ), hb_parc( 3 ), hb_parl( 4 ) );
  1513. }