PageRenderTime 52ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

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

#
C | 1785 lines | 1469 code | 256 blank | 60 comment | 266 complexity | f2fa49082a2f639fa99fa8133910a9ff 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 7892 2007-11-01 16:03:54Z 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 int
  880. hb_dbgEvalSubstituteVar( HB_WATCHPOINT *watch, char *szWord, int nStart, int nLen )
  881. {
  882. int j;
  883. char *t;
  884. for ( j = 0; j < watch->nVars; j++ )
  885. {
  886. if ( !strcmp( szWord, watch->aVars[ j ] ) )
  887. {
  888. break;
  889. }
  890. }
  891. if ( j == watch->nVars )
  892. {
  893. *ARRAY_ADD( char *, watch->aVars, watch->nVars ) = szWord;
  894. }
  895. else
  896. {
  897. FREE( szWord );
  898. }
  899. t = (char *) ALLOC( strlen( watch->szExpr ) - nLen + 9 + 1 );
  900. memmove( t, watch->szExpr, nStart );
  901. memmove( t + nStart, "__dbg[", 6 );
  902. t[ nStart + 6 ] = '0' + ( ( j + 1 ) / 10 );
  903. t[ nStart + 7 ] = '0' + ( ( j + 1 ) % 10 );
  904. t[ nStart + 8 ] = ']';
  905. strcpy( t + nStart + 9, watch->szExpr + nStart + nLen );
  906. FREE( watch->szExpr );
  907. watch->szExpr = t;
  908. return nStart + 9;
  909. }
  910. static PHB_ITEM
  911. hb_dbgEvalMakeBlock( HB_WATCHPOINT *watch )
  912. {
  913. int i = 0;
  914. PHB_ITEM pBlock;
  915. BOOL bAfterId = FALSE;
  916. char *s;
  917. watch->nVars = 0;
  918. while ( watch->szExpr[ i ] )
  919. {
  920. char c = watch->szExpr[ i ];
  921. if ( IS_IDENT_START( c ) )
  922. {
  923. int nStart = i, nLen;
  924. int j = i;
  925. char *szWord;
  926. while ( c && IS_IDENT_CHAR( c ) )
  927. {
  928. j++;
  929. c = watch->szExpr[ j ];
  930. }
  931. nLen = j - i;
  932. STRNDUP( szWord, watch->szExpr + i, nLen );
  933. i = j;
  934. if ( c )
  935. {
  936. while ( watch->szExpr[ i ] && watch->szExpr[ i ] == ' ' )
  937. {
  938. i++;
  939. }
  940. if ( watch->szExpr[ i ] == '(' )
  941. {
  942. FREE( szWord );
  943. continue;
  944. }
  945. if ( watch->szExpr[ i ] == '-' && watch->szExpr[ i + 1 ] == '>' )
  946. {
  947. i += 2;
  948. while ( ( c = watch->szExpr[ i ] ) != '\0' && IS_IDENT_CHAR( c ) )
  949. {
  950. i++;
  951. }
  952. FREE( szWord );
  953. continue;
  954. }
  955. }
  956. hb_strupr( szWord );
  957. i = hb_dbgEvalSubstituteVar( watch, szWord, nStart, nLen );
  958. bAfterId = TRUE;
  959. continue;
  960. }
  961. if ( c == '.' )
  962. {
  963. if ( watch->szExpr[ i + 1 ]
  964. && strchr( "TtFf", watch->szExpr[ i + 1 ] )
  965. && watch->szExpr[ i + 2 ] == '.' )
  966. {
  967. i += 3;
  968. }
  969. else if ( !hb_strnicmp( watch->szExpr + i + 1, "OR.", 3 ) )
  970. {
  971. i += 4;
  972. }
  973. else if ( !hb_strnicmp( watch->szExpr + i + 1, "AND.", 4 )
  974. || !hb_strnicmp( watch->szExpr + i + 1, "NOT.", 4 ) )
  975. {
  976. i += 5;
  977. }
  978. else
  979. {
  980. i++;
  981. }
  982. bAfterId = FALSE;
  983. continue;
  984. }
  985. if ( c == ':'
  986. || ( c == '-' && watch->szExpr[ i + 1 ] == '>'
  987. && IS_IDENT_START( watch->szExpr[ i + 2 ] ) ) )
  988. {
  989. if ( c == ':' && watch->szExpr[ i + 1 ] == ':' )
  990. {
  991. i = hb_dbgEvalSubstituteVar( watch, hb_strdup( "SELF" ), i, 1 );
  992. bAfterId = TRUE;
  993. continue;
  994. }
  995. if ( c == '-' )
  996. {
  997. i++;
  998. }
  999. i++;
  1000. while ( watch->szExpr[ i ] && IS_IDENT_CHAR( watch->szExpr[ i ] ) )
  1001. {
  1002. i++;
  1003. }
  1004. bAfterId = TRUE;
  1005. continue;
  1006. }
  1007. if ( strchr( " !#$=<>(+-*/%^|,{&", c ) )
  1008. {
  1009. i++;
  1010. bAfterId = FALSE;
  1011. continue;
  1012. }
  1013. if ( c == '\'' || c == '\"' )
  1014. {
  1015. i++;
  1016. while ( watch->szExpr[ i ] && watch->szExpr[ i ] != c )
  1017. {
  1018. i++;
  1019. }
  1020. if ( watch->szExpr[ i ] )
  1021. {
  1022. i++;
  1023. }
  1024. bAfterId = TRUE;
  1025. continue;
  1026. }
  1027. if ( c == '[' )
  1028. {
  1029. i++;
  1030. if ( bAfterId )
  1031. {
  1032. bAfterId = FALSE;
  1033. }
  1034. else
  1035. {
  1036. while ( watch->szExpr[ i ] && watch->szExpr[ i ] != ']' )
  1037. {
  1038. i++;
  1039. }
  1040. if ( watch->szExpr[ i ] )
  1041. {
  1042. i++;
  1043. }
  1044. bAfterId = TRUE;
  1045. }
  1046. continue;
  1047. }
  1048. i++;
  1049. }
  1050. s = ( char * ) ALLOC( 8 + strlen( watch->szExpr ) + 1 + 1 );
  1051. strcpy( s, "{|__dbg|" );
  1052. strcat( s, watch->szExpr );
  1053. strcat( s, "}" );
  1054. pBlock = hb_itemNew( NULL );
  1055. if( ! hb_dbgEvalMacro( s, pBlock ) )
  1056. {
  1057. hb_itemRelease( pBlock );
  1058. pBlock = NULL;
  1059. }
  1060. FREE( s );
  1061. return pBlock;
  1062. }
  1063. static PHB_ITEM
  1064. hb_dbgEvalResolve( HB_DEBUGINFO *info, HB_WATCHPOINT *watch )
  1065. {
  1066. int i;
  1067. HB_CALLSTACKINFO *top = &info->aCallStack[ info->nCallStackLen - 1 ];
  1068. PHB_ITEM aVars = hb_itemArrayNew( watch->nVars );
  1069. HB_VARINFO *scopes;
  1070. HB_MODULEINFO *module = NULL;
  1071. int nProcLevel;
  1072. if ( !watch->nVars )
  1073. {
  1074. return aVars;
  1075. }
  1076. scopes = (HB_VARINFO *) ALLOC( watch->nVars * sizeof( HB_VARINFO ) );
  1077. nProcLevel = hb_dbg_ProcLevel();
  1078. for ( i = 0; i < info->nModules; i++ )
  1079. {
  1080. if ( !strcmp( info->aModules[ i ].szModule, top->szModule ) )
  1081. {
  1082. module = &info->aModules[ i ];
  1083. break;
  1084. }
  1085. }
  1086. for ( i = 0; i < watch->nVars; i++ )
  1087. {
  1088. char *name = watch->aVars[ i ];
  1089. HB_VARINFO *var;
  1090. int j;
  1091. PHB_ITEM pItem;
  1092. for ( j = 0; j < top->nLocals; j++ )
  1093. {
  1094. var = &top->aLocals[ j ];
  1095. if ( !strcmp( name, var->szName ) )
  1096. {
  1097. scopes[ i ].cType = 'L';
  1098. scopes[ i ].nFrame = nProcLevel - var->nFrame;
  1099. scopes[ i ].nIndex = var->nIndex;
  1100. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1101. break;
  1102. }
  1103. }
  1104. if ( j < top->nLocals )
  1105. continue;
  1106. for ( j = 0; j < top->nStatics; j++ )
  1107. {
  1108. var = &top->aStatics[ j ];
  1109. if ( !strcmp( name, var->szName ) )
  1110. {
  1111. scopes[ i ].cType = 'S';
  1112. scopes[ i ].nFrame = var->nFrame;
  1113. scopes[ i ].nIndex = var->nIndex;
  1114. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1115. break;
  1116. }
  1117. }
  1118. if ( j < top->nStatics )
  1119. continue;
  1120. if ( module )
  1121. {
  1122. for ( j = 0; j < module->nStatics; j++ )
  1123. {
  1124. var = &module->aStatics[ j ];
  1125. if ( !strcmp( name, var->szName ) )
  1126. {
  1127. scopes[ i ].cType = 'S';
  1128. scopes[ i ].nFrame = var->nFrame;
  1129. scopes[ i ].nIndex = var->nIndex;
  1130. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1131. break;
  1132. }
  1133. }
  1134. if ( j < module->nStatics )
  1135. continue;
  1136. for ( j = 0; j < module->nGlobals; j++ )
  1137. {
  1138. var = &module->aGlobals[ j ];
  1139. if ( !strcmp( name, var->szName ) )
  1140. {
  1141. scopes[ i ].cType = 'G';
  1142. scopes[ i ].nFrame = var->nFrame;
  1143. scopes[ i ].nIndex = var->nIndex;
  1144. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1145. break;
  1146. }
  1147. }
  1148. if ( j < module->nGlobals )
  1149. continue;
  1150. for ( j = 0; j < module->nExternGlobals; j++ )
  1151. {
  1152. var = &module->aExternGlobals[ j ];
  1153. if ( !strcmp( name, var->szName ) )
  1154. {
  1155. scopes[ i ].cType = 'G';
  1156. scopes[ i ].nFrame = var->nFrame;
  1157. scopes[ i ].nIndex = var->nIndex;
  1158. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1159. break;
  1160. }
  1161. }
  1162. if ( j < module->nExternGlobals )
  1163. continue;
  1164. }
  1165. scopes[ i ].cType = 'M';
  1166. scopes[ i ].szName = STRDUP( name );
  1167. pItem = hb_dbgVarGet( &scopes[ i ] );
  1168. if ( pItem )
  1169. {
  1170. hb_itemArrayPut( aVars, i + 1, pItem );
  1171. }
  1172. if ( scopes[ i ].cType == 'F' )
  1173. {
  1174. hb_itemRelease( pItem );
  1175. }
  1176. }
  1177. watch->aScopes = scopes;
  1178. return aVars;
  1179. }
  1180. HB_EXPORT PHB_ITEM
  1181. hb_dbgGetExpressionValue( void *handle, char *expression )
  1182. {
  1183. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1184. PHB_ITEM result;
  1185. HB_WATCHPOINT point;
  1186. point.szExpr = STRDUP( expression );
  1187. point.pBlock = NULL;
  1188. point.nVars = 0;
  1189. result = hb_dbgEval( info, &point );
  1190. hb_dbgClearWatch( &point );
  1191. return result;
  1192. }
  1193. HB_EXPORT PHB_ITEM
  1194. hb_dbgGetSourceFiles( void *handle )
  1195. {
  1196. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1197. int nModules = hb_itemSize( info->pStopLines );
  1198. PHB_ITEM ret = hb_itemArrayNew( nModules );
  1199. int i;
  1200. for ( i = 1; i <= nModules; i++ )
  1201. {
  1202. hb_arraySet( ret, i, hb_arrayGetItemPtr( hb_arrayGetItemPtr( info->pStopLines, i ), 1 ) );
  1203. }
  1204. return ret;
  1205. }
  1206. HB_EXPORT PHB_ITEM
  1207. hb_dbgGetWatchValue( void *handle, int nWatch )
  1208. {
  1209. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1210. return hb_dbgEval( info, &( info->aWatch[ nWatch ] ) );
  1211. }
  1212. static BOOL
  1213. hb_dbgIsAltD( void )
  1214. {
  1215. char szName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5];
  1216. hb_procinfo( 1, szName, NULL, NULL );
  1217. return !strcmp( szName, "ALTD" );
  1218. }
  1219. static BOOL
  1220. hb_dbgIsBreakPoint( HB_DEBUGINFO *info, char *szModule, int nLine )
  1221. {
  1222. int i;
  1223. for ( i = 0; i < info->nBreakPoints; i++ )
  1224. {
  1225. HB_BREAKPOINT *point = &info->aBreak[ i ];
  1226. if ( point->nLine == nLine
  1227. && FILENAME_EQUAL( szModule, point->szModule ) )
  1228. return TRUE;
  1229. }
  1230. return FALSE;
  1231. }
  1232. HB_EXPORT BOOL
  1233. hb_dbgIsValidStopLine( void *handle, char *szModule, int nLine )
  1234. {
  1235. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1236. int nModules = hb_itemSize( info->pStopLines );
  1237. int i;
  1238. for ( i = 1; i <= nModules; i++ )
  1239. {
  1240. PHB_ITEM pEntry = hb_arrayGetItemPtr( info->pStopLines, i );
  1241. if ( FILENAME_EQUAL( hb_arrayGetCPtr( pEntry, 1 ), szModule ) )
  1242. {
  1243. int nMin = hb_arrayGetNL( pEntry, 2 );
  1244. int nOfs = nLine - nMin;
  1245. if ( nLine < nMin || (ULONG)( nOfs / 8 ) > hb_arrayGetCLen( pEntry, 3 ) )
  1246. {
  1247. return FALSE;
  1248. }
  1249. return ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs / 8 ] & ( 1 << ( nOfs % 8 ) ) ) != 0;
  1250. }
  1251. }
  1252. return FALSE;
  1253. }
  1254. static void
  1255. hb_dbgQuit( HB_DEBUGINFO *info )
  1256. {
  1257. while ( info->nWatchPoints )
  1258. {
  1259. hb_dbgDelWatch( info, info->nWatchPoints - 1 );
  1260. }
  1261. while ( info->nBreakPoints )
  1262. {
  1263. hb_dbgDelBreak( info, info->nBreakPoints - 1 );
  1264. }
  1265. while ( info->nCallStackLen )
  1266. {
  1267. hb_dbgEndProc( info );
  1268. }
  1269. if ( info->pStopLines )
  1270. {
  1271. hb_itemRelease( info->pStopLines );
  1272. }
  1273. while ( info->nModules )
  1274. {
  1275. int nModules = info->nModules - 1;
  1276. HB_MODULEINFO *module = &info->aModules[ nModules ];
  1277. if ( module->nStatics )
  1278. {
  1279. FREE( module->aStatics );
  1280. }
  1281. ARRAY_DEL( HB_MODULEINFO, info->aModules, info->nModules, nModules );
  1282. }
  1283. if ( info->bToCursor )
  1284. {
  1285. info->bToCursor = FALSE;
  1286. FREE( info->szToCursorModule );
  1287. }
  1288. }
  1289. HB_EXPORT void
  1290. hb_dbgSetCBTrace( void *handle, BOOL bCBTrace )
  1291. {
  1292. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1293. info->bCBTrace = bCBTrace;
  1294. }
  1295. HB_EXPORT void
  1296. hb_dbgSetGo( void *handle )
  1297. {
  1298. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1299. info->bGo = TRUE;
  1300. }
  1301. HB_EXPORT void
  1302. hb_dbgSetInvoke( void *handle, BOOL ( *pFunInvoke )( void ) )
  1303. {
  1304. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1305. info->pFunInvoke = pFunInvoke;
  1306. }
  1307. HB_EXPORT void
  1308. hb_dbgSetNextRoutine( void *handle )
  1309. {
  1310. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1311. info->bNextRoutine = TRUE;
  1312. }
  1313. HB_EXPORT void
  1314. hb_dbgSetQuit( void *handle )
  1315. {
  1316. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1317. info->bQuit = TRUE;
  1318. }
  1319. HB_EXPORT void
  1320. hb_dbgSetToCursor( void *handle, char *szModule, int nLine )
  1321. {
  1322. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1323. info->bToCursor = TRUE;
  1324. info->szToCursorModule = STRDUP( szModule );
  1325. info->nToCursorLine = nLine;
  1326. }
  1327. HB_EXPORT void
  1328. hb_dbgSetTrace( void *handle )
  1329. {
  1330. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1331. info->bTraceOver = TRUE;
  1332. info->nTraceLevel = info->nCallStackLen;
  1333. }
  1334. HB_EXPORT void
  1335. hb_dbgSetWatch( void *handle, int nWatch, char *szExpr, BOOL bTrace )
  1336. {
  1337. HB_DEBUGINFO *info = (HB_DEBUGINFO *)handle;
  1338. HB_WATCHPOINT *pWatch = &info->aWatch[ nWatch ];
  1339. int i;
  1340. hb_dbgClearWatch( pWatch );
  1341. pWatch->szExpr = STRDUP( szExpr );
  1342. pWatch->pBlock = NULL;
  1343. for ( i = 0; i < info->nTracePoints; i++ )
  1344. {
  1345. HB_TRACEPOINT *pTrace = &info->aTrace[ i ];
  1346. if ( pTrace->nIndex == nWatch )
  1347. {
  1348. if ( pTrace->xValue )
  1349. {
  1350. hb_itemRelease( pTrace->xValue );
  1351. }
  1352. ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i );
  1353. break;
  1354. }
  1355. }
  1356. if ( bTrace )
  1357. {
  1358. HB_TRACEPOINT *pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
  1359. pTrace->nIndex = nWatch;
  1360. pTrace->xValue = hb_dbgEval( info, pWatch );
  1361. }
  1362. }
  1363. static PHB_ITEM
  1364. hb_dbgVarGet( HB_VARINFO *scope )
  1365. {
  1366. switch ( scope->cType )
  1367. {
  1368. case 'G':
  1369. return hb_dbg_vmVarGGet( scope->nFrame, scope->nIndex );
  1370. case 'L':
  1371. return hb_dbg_vmVarLGet( scope->nFrame, scope->nIndex );
  1372. case 'S':
  1373. return hb_dbg_vmVarSGet( scope->nFrame, scope->nIndex );
  1374. case 'M':
  1375. {
  1376. PHB_DYNS pDyn;
  1377. pDyn = hb_dynsymFind( scope->szName );
  1378. if ( pDyn != NULL )
  1379. {
  1380. if ( pDyn->hMemvar == 0 )
  1381. {
  1382. PHB_ITEM pItem = hb_itemNew( NULL );
  1383. if ( hb_rddFieldGet( pItem, pDyn->pSymbol ) == SUCCESS )
  1384. {
  1385. scope->cType = 'F';
  1386. return pItem;
  1387. }
  1388. hb_itemRelease( pItem );
  1389. }
  1390. else
  1391. {
  1392. return hb_memvarGetValueByHandle( pDyn->hMemvar );
  1393. }
  1394. }
  1395. return NULL;
  1396. }
  1397. default:
  1398. return NULL;
  1399. }
  1400. }
  1401. static void
  1402. hb_dbgVarSet( HB_VARINFO *scope, PHB_ITEM xNewValue )
  1403. {
  1404. switch ( scope->cType )
  1405. {
  1406. case 'G':
  1407. case 'L':
  1408. case 'S':
  1409. hb_itemCopy( hb_dbgVarGet( scope ), xNewValue );
  1410. break;
  1411. case 'M':
  1412. {
  1413. PHB_DYNS pDynSym = hb_dynsymFind( "__MVPUT" );
  1414. if ( pDynSym && pDynSym->pSymbol->value.pFunPtr )
  1415. {
  1416. hb_vmPushDynSym( pDynSym );
  1417. hb_vmPushNil();
  1418. hb_vmPushString( scope->szName, strlen( scope->szName ) );
  1419. hb_vmPush( xNewValue );
  1420. hb_vmDo( 2 );
  1421. }
  1422. break;
  1423. }
  1424. }
  1425. }
  1426. /*
  1427. * .prg functions
  1428. */
  1429. HB_FUNC( HB_DBG_SETENTRY )
  1430. {
  1431. hb_dbg_SetEntry( hb_dbgEntry );
  1432. }
  1433. HB_FUNC( HB_DBG_SETGO )
  1434. {
  1435. void * ptr = hb_parptr( 1 );
  1436. if( ptr )
  1437. hb_dbgSetGo( ptr );
  1438. }
  1439. HB_FUNC( HB_DBG_SETTRACE )
  1440. {
  1441. void * ptr = hb_parptr( 1 );
  1442. if( ptr )
  1443. hb_dbgSetTrace( ptr );
  1444. }
  1445. HB_FUNC( HB_DBG_SETCBTRACE )
  1446. {
  1447. void * ptr = hb_parptr( 1 );
  1448. if( ptr )
  1449. hb_dbgSetCBTrace( ptr, hb_parl( 2 ) );
  1450. }
  1451. HB_FUNC( HB_DBG_SETNEXTROUTINE )
  1452. {
  1453. void * ptr = hb_parptr( 1 );
  1454. if( ptr )
  1455. hb_dbgSetNextRoutine( ptr );
  1456. }
  1457. HB_FUNC( HB_DBG_SETQUIT )
  1458. {
  1459. void * ptr = hb_parptr( 1 );
  1460. if( ptr )
  1461. hb_dbgSetQuit( ptr );
  1462. }
  1463. HB_FUNC( HB_DBG_SETTOCURSOR )
  1464. {
  1465. void * ptr = hb_parptr( 1 );
  1466. if( ptr )
  1467. hb_dbgSetToCursor( ptr, hb_parc( 2 ), hb_parni( 3 ) );
  1468. }
  1469. HB_FUNC( HB_DBG_GETEXPRVALUE )
  1470. {
  1471. void * ptr = hb_parptr( 1 );
  1472. if( ptr )
  1473. {
  1474. PHB_ITEM pItem;
  1475. if( ISCHAR( 2 ) )
  1476. pItem = hb_dbgGetExpressionValue( hb_parptr( 1 ), hb_parc( 2 ) );
  1477. else
  1478. pItem = hb_dbgGetWatchValue( hb_parptr( 1 ), hb_parni( 2 ) - 1 );
  1479. if( pItem )
  1480. {
  1481. hb_storl( TRUE, 3 );
  1482. hb_itemRelease( hb_itemReturn( pItem ) );
  1483. }
  1484. else
  1485. hb_storl( FALSE, 3 );
  1486. }
  1487. }
  1488. HB_FUNC( HB_DBG_GETSOURCEFILES )
  1489. {
  1490. void * ptr = hb_parptr( 1 );
  1491. if( ptr )
  1492. hb_itemRelease( hb_itemReturn( hb_dbgGetSourceFiles( ptr ) ) );
  1493. }
  1494. HB_FUNC( HB_DBG_ISVALIDSTOPLINE )
  1495. {
  1496. void * ptr = hb_parptr( 1 );
  1497. if( ptr )
  1498. hb_retl( hb_dbgIsValidStopLine( ptr, hb_parc( 2 ), hb_parni( 3 ) ) );
  1499. }
  1500. HB_FUNC( HB_DBG_ADDBREAK )
  1501. {
  1502. void * ptr = hb_parptr( 1 );
  1503. if( ptr )
  1504. hb_dbgAddBreak( ptr, hb_parc( 2 ), hb_parni( 3 ), NULL );
  1505. }
  1506. HB_FUNC( HB_DBG_DELBREAK )
  1507. {
  1508. void * ptr = hb_parptr( 1 );
  1509. if( ptr )
  1510. hb_dbgDelBreak( ptr, hb_parni( 2 ) );
  1511. }
  1512. HB_FUNC( HB_DBG_ADDWATCH )
  1513. {
  1514. void * ptr = hb_parptr( 1 );
  1515. if( ptr )
  1516. hb_dbgAddWatch( ptr, hb_parc( 2 ), hb_parl( 3 ) );
  1517. }
  1518. HB_FUNC( HB_DBG_DELWATCH )
  1519. {
  1520. void * ptr = hb_parptr( 1 );
  1521. if( ptr )
  1522. hb_dbgDelWatch( ptr, hb_parni( 2 ) );
  1523. }
  1524. HB_FUNC( HB_DBG_SETWATCH )
  1525. {
  1526. void * ptr = hb_parptr( 1 );
  1527. if( ptr )
  1528. hb_dbgSetWatch( ptr, hb_parni( 2 ), hb_parc( 3 ), hb_parl( 4 ) );
  1529. }