PageRenderTime 68ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/harbour-2.0.0/src/debug/dbgentry.c

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